--- /dev/null
+"""\r
+Douban OAuth support.\r
+\r
+This adds support for Douban OAuth service. An application must\r
+be registered first on douban.com and the settings DOUBAN_CONSUMER_KEY\r
+and DOUBAN_CONSUMER_SECRET must be defined with they corresponding\r
+values.\r
+\r
+By default account id is stored in extra_data field, check OAuthBackend\r
+class for details on how to extend it.\r
+"""\r
+from django.utils import simplejson\r
+\r
+from social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME\r
+from social_auth.backends.exceptions import AuthCanceled\r
+\r
+\r
+DOUBAN_SERVER = 'www.douban.com'\r
+DOUBAN_REQUEST_TOKEN_URL = 'http://%s/service/auth/request_token' % DOUBAN_SERVER\r
+DOUBAN_ACCESS_TOKEN_URL = 'http://%s/service/auth/access_token' % DOUBAN_SERVER\r
+\r
+DOUBAN_AUTHORIZATION_URL = 'http://%s/service/auth/authorize' % DOUBAN_SERVER\r
+\r
+\r
+class DoubanBackend(OAuthBackend):\r
+ """Douban OAuth authentication backend"""\r
+ name = 'douban'\r
+ EXTRA_DATA = [('id', 'id')]\r
+ \r
+ def get_user_id(self, details, response):\r
+ return response['db:uid']['$t']\r
+ \r
+ def get_user_details(self, response):\r
+ """Return user details from Douban"""\r
+ return {USERNAME: response["db:uid"]["$t"],\r
+ 'email': ''}\r
+\r
+\r
+class DoubanAuth(ConsumerBasedOAuth):\r
+ """Douban OAuth authentication mechanism"""\r
+ AUTHORIZATION_URL = DOUBAN_AUTHORIZATION_URL\r
+ REQUEST_TOKEN_URL = DOUBAN_REQUEST_TOKEN_URL\r
+ ACCESS_TOKEN_URL = DOUBAN_ACCESS_TOKEN_URL\r
+ SERVER_URL = DOUBAN_SERVER\r
+ AUTH_BACKEND = DoubanBackend\r
+ SETTINGS_KEY_NAME = 'DOUBAN_CONSUMER_KEY'\r
+ SETTINGS_SECRET_NAME = 'DOUBAN_CONSUMER_SECRET'\r
+\r
+ def user_data(self, access_token, *args, **kwargs):\r
+ """Return user data provided"""\r
+ url = 'http://api.douban.com/people/%40me?&alt=json'\r
+ request = self.oauth_request(access_token, url)\r
+ json = self.fetch_response(request)\r
+ \r
+ try:\r
+ return simplejson.loads(json)\r
+ except ValueError:\r
+ return None\r
+\r
+ def auth_complete(self, *args, **kwargs):\r
+ """Completes login process, must return user instance"""\r
+ print dir(self)\r
+ if 'denied' in self.data:\r
+ raise AuthCanceled(self)\r
+ else:\r
+ return super(DoubanAuth, self).auth_complete(*args, **kwargs)\r
+\r
+\r
+# Backend definition\r
+BACKENDS = {\r
+ 'douban': DoubanAuth,\r
+}\r