]> git.parisson.com Git - django-social-auth.git/commitdiff
add github OAuth backend fix #122
authorrevolunet <julien@bouquillon.com>
Fri, 19 Aug 2011 13:46:31 +0000 (15:46 +0200)
committerrevolunet <julien@bouquillon.com>
Fri, 19 Aug 2011 13:48:26 +0000 (15:48 +0200)
README.rst
example/local_settings.py.template
social_auth/backends/contrib/github.py [new file with mode: 0644]

index e93016a050761ab37e7fec255c88ce0ff8b225aa..8159877938b1bdfdb072426a23460931b5c321ee 100644 (file)
@@ -41,6 +41,7 @@ credentials, some features are:
     * `Orkut OAuth`_
     * `Linkedin OAuth`_
     * `Foursquare OAuth2`_
+    * `GitHub OAuth`_
 
 - Basic user data population and signaling, to allows custom fields values
   from providers response
@@ -112,6 +113,7 @@ Configuration
         'social_auth.backends.contrib.LiveJournalBackend',
         'social_auth.backends.contrib.orkut.OrkutBackend',
         'social_auth.backends.contrib.orkut.FoursquareBackend',
+        'social_auth.backends.contrib.github.GithubBackend',
         'social_auth.backends.OpenIDBackend',
         'django.contrib.auth.backends.ModelBackend',
     )
@@ -150,6 +152,8 @@ Configuration
     GOOGLE_OAUTH2_CLIENT_SECRET  = ''
     FOURSQUARE_CONSUMER_KEY      = ''
     FOURSQUARE_CONSUMER_SECRET   = ''
+    GITHUB_APP_ID                = ''
+    GITHUB_API_SECRET            = ''
 
 - Setup login URLs::
 
index 46ac46600a934bf07f0112fd59b8b75d9168a67d..8b52a3b7bce763a3bf80d0523b20105b6a9fb086 100644 (file)
@@ -15,3 +15,5 @@ SOCIAL_AUTH_COMPLETE_URL_NAME     = 'socialauth_complete'
 LOGIN_ERROR_URL                   = '/login/error/'
 #SOCIAL_AUTH_USER_MODEL            = 'app.CustomUser'
 SOCIAL_AUTH_ERROR_KEY             = 'socialauth_error'
+GITHUB_APP_ID                     = ''
+GITHUB_API_SECRET                 = ''
\ No newline at end of file
diff --git a/social_auth/backends/contrib/github.py b/social_auth/backends/contrib/github.py
new file mode 100644 (file)
index 0000000..d53801e
--- /dev/null
@@ -0,0 +1,104 @@
+"""
+GitHub OAuth support.
+
+This contribution adds support for GitHub OAuth service. The settings
+GITHUB_APP_ID and GITHUB_API_SECRET must be defined with the values
+given by Facebook application registration process.
+
+Extended permissions are supported by defining GITHUB_EXTENDED_PERMISSIONS
+setting, it must be a list of values to request.
+
+By default account id and token expiration time are stored in extra_data
+field, check OAuthBackend class for details on how to extend it.
+"""
+import cgi
+import urllib
+
+from django.conf import settings
+from django.utils import simplejson
+from django.contrib.auth import authenticate
+
+from social_auth.backends import BaseOAuth, OAuthBackend, USERNAME
+
+# Facebook configuration
+GITHUB_SERVER = 'github.com'
+GITHUB_AUTHORIZATION_URL = 'https://%s/login/oauth/authorize' % GITHUB_SERVER
+GITHUB_ACCESS_TOKEN_URL = 'https://%s/login/oauth/access_token' % GITHUB_SERVER
+GITHUB_API_URL = 'https://api.%s' % GITHUB_SERVER
+EXPIRES_NAME = getattr(settings, 'SOCIAL_AUTH_EXPIRATION', 'expires')
+
+class GithubBackend(OAuthBackend):
+    """Github OAuth authentication backend"""
+    name = 'github'
+    # Default extra data to store
+    EXTRA_DATA = [('id', 'id'), ('expires', EXPIRES_NAME)]
+
+    def get_user_details(self, response):
+        """Return user details from Github account"""
+        return {
+            'username':response.get('login'),
+            'email':response.get('email'),
+            'firstname':response.get('name')
+            }
+
+class GithubAuth(BaseOAuth):
+    """Github OAuth mechanism"""
+    AUTH_BACKEND = GithubBackend
+
+    def auth_url(self):
+        """Returns redirect url"""
+        args = {'client_id': settings.GITHUB_APP_ID,
+                'redirect_uri': self.redirect_uri}
+        if hasattr(settings, 'GITHUB_EXTENDED_PERMISSIONS'):
+            args['scope'] = ','.join(settings.GITHUB_EXTENDED_PERMISSIONS)
+        return GITHUB_AUTHORIZATION_URL + '?' + urllib.urlencode(args)
+
+    def auth_complete(self, *args, **kwargs):
+        """Returns user, might be logged in"""
+        if 'code' in self.data:
+            
+            url = GITHUB_ACCESS_TOKEN_URL + '?' + \
+                  urllib.urlencode({'client_id': settings.GITHUB_APP_ID,
+                                'redirect_uri': self.redirect_uri,
+                                'client_secret': settings.GITHUB_API_SECRET,
+                                'code': self.data['code']})
+            response = cgi.parse_qs(urllib.urlopen(url).read())
+            if response.get('error'):
+                error = self.data.get('error') or 'unknown error'
+                raise ValueError('Authentication error: %s' % error)
+            access_token = response['access_token'][0]
+            data = self.user_data(access_token)
+            if data is not None:
+                if 'error' in data:
+                    error = self.data.get('error') or 'unknown error'
+                    raise ValueError('Authentication error: %s' % error)
+                data['access_token'] = access_token
+            kwargs.update({'response': data, GithubBackend.name: True})
+            return authenticate(*args, **kwargs)
+        else:
+            error = self.data.get('error') or 'unknown error'
+            raise ValueError('Authentication error: %s' % error)
+
+    def user_data(self, access_token):
+        """Loads user data from service"""
+        params = {'access_token': access_token,}
+        url = '%s/user' % GITHUB_API_URL + '?' + urllib.urlencode(params)
+        try:
+            data = simplejson.load(urllib.urlopen(url))
+            return data
+        except ValueError:
+            return None
+
+
+    @classmethod
+    def enabled(cls):
+        """Return backend enabled status by checking basic settings"""
+        return all(hasattr(settings, name) for name in
+                        ('GITHUB_APP_ID',
+                         'GITHUB_API_SECRET'))
+
+
+# Backend definition
+BACKENDS = {
+    'github': GithubAuth,
+}