]> git.parisson.com Git - django-social-auth.git/commitdiff
VKontakte OAuth2 authentication support added.
authorStas Kravets <skravets@applebough.(none)>
Thu, 28 Apr 2011 11:52:57 +0000 (15:52 +0400)
committerStas Kravets <skravets@applebough.(none)>
Thu, 28 Apr 2011 11:52:57 +0000 (15:52 +0400)
example/settings.py
example/templates/done.html
example/templates/home.html
social_auth/backends/contrib/vkontakte.py

index 4fd4c14baee73752ccfbfc64dcc7908e85d08468..06d3e89e590c4cf2e093fc4530ac5db62e92ea23 100644 (file)
@@ -74,6 +74,7 @@ AUTHENTICATION_BACKENDS = (
     'social_auth.backends.contrib.vkontakte.VKontakteBackend',
     'social_auth.backends.contrib.yandex.YandexBackend',
     'social_auth.backends.contrib.odnoklassniki.OdnoklassnikiBackend',
+    'social_auth.backends.contrib.vkontakte.VKontakteOAuth2Backend',
     'django.contrib.auth.backends.ModelBackend',
 )
 
index 6dab979fb8c253092e381d7c6a2aa0a1d36e52e1..cc846351a62a97d616fd00c660a75e2e6a1622a0 100644 (file)
@@ -46,6 +46,9 @@
       {% if google_oauth2 %}<span class="disconnect">(<a href="{% url disconnect "google-oauth2" %}">disconnect</a>)</span>{% endif %}
          <li><a rel="nofollow" href="{% url associate_begin "odnoklassniki" %}">Odnoklassniki OAuth 2.0</a></li>
          {% if odnoklassniki %}<span class="disconnect">(<a href="{% url disconnect "odnoklassniki" %}">disconnect</a>)</span>{% endif %}
+         <li><a rel="nofollow" href="{% url associate_begin "vkontakte-oauth2" %}">VKontakte OAuth 2.0</a></li>
+         {% if vkontakte_oauth2 %}<span class="disconnect">(<a href="{% url disconnect "vkontakte-oauth2" %}">disconnect</a>)</span>{% endif %}
+
     </li>
   </ul>
 
index f5b3360970f05a139d8844082089d95bf86e39be..46c03a6d73699120c165e7ff9d590458cdc03efe 100644 (file)
@@ -19,6 +19,7 @@
   <ul>
     <li><a rel="nofollow" href="{% url begin "google-oauth2" %}">Google OAuth2</a></li>
        <li><a rel="nofollow" href="{% url begin "odnoklassniki" %}">Odnoklassniki OAuth 2.0</a></li>
+       <li><a rel="nofollow" href="{% url begin "vkontakte-oauth2" %}">VKontakte OAuth 2.0</a></li>
   </ul>
 </div>
 
index ee830dfd6df2415ac96cfb6b1779f495a282753b..0c547736df8d8ef46f0e832096f9bcb255dfe4b1 100644 (file)
@@ -1,20 +1,29 @@
 """
-VKontakte OpenAPI support.
+VKontakte OpenAPI and OAuth 2.0 support.
 
-This contribution adds support for VKontakte OpenAPI service in the form
+This contribution adds support for VKontakte OpenAPI and OAuth 2.0 service in the form
 www.vkontakte.ru. Username is retrieved from the identity returned by server.
 """
 
 from django.conf import settings
 from django.contrib.auth import authenticate
-from urllib import unquote
+from django.utils import simplejson
+
+from urllib import urlencode, unquote
+from urllib2 import Request, urlopen
 from hashlib import md5
 from time import time
 
-from social_auth.backends import SocialAuthBackend, BaseAuth, USERNAME
+from social_auth.backends import SocialAuthBackend, OAuthBackend, BaseAuth, BaseOAuth2, USERNAME
 
 VKONTAKTE_LOCAL_HTML  = 'vkontakte.html'
 
+VKONTAKTE_API_URL       = 'https://api.vkontakte.ru/method/'
+VKONTAKTE_OAUTH2_SCOPE  = [''] # Enough for authentication
+
+EXPIRES_NAME = getattr(settings, 'SOCIAL_AUTH_EXPIRATION', 'expires')
+
+
 class VKontakteBackend(SocialAuthBackend):
     """VKontakte authentication backend"""
     name = 'vkontakte'
@@ -31,6 +40,28 @@ class VKontakteBackend(SocialAuthBackend):
         return values
 
 
+class VKontakteOAuth2Backend(OAuthBackend):
+    """VKontakteOAuth2 authentication backend"""
+    name = 'vkontakte-oauth2'
+    EXTRA_DATA = [('expires_in', EXPIRES_NAME)]
+
+    def get_user_id(self, details, response):
+        """Return user unique id provided by VKontakte"""
+        return int(response['user_id'])
+    
+    def get_user_details(self, response):
+        """Return user details from VKontakte request"""
+        values = { USERNAME: response['user_id'], 'email': '', 'fullname': unquote(response['response']['user_name']),
+                  'first_name': '', 'last_name': ''}
+        
+        if ' ' in values['fullname']:
+            values['first_name'], values['last_name'] = values['fullname'].split()
+        else:
+            values['first_name'] = values['fullname']
+            
+        return values
+
+
 class VKontakteAuth(BaseAuth):
     """VKontakte OpenAPI authorization mechanism"""
     AUTH_BACKEND = VKontakteBackend
@@ -73,10 +104,41 @@ class VKontakteAuth(BaseAuth):
         to do authentication, so auth_xxx methods are not needed to be called.
         Their current implementation is just an example"""
         return False
+
     
-    
+class VKontakteOAuth2(BaseOAuth2):
+    """VKontakte OAuth2 support"""
+    AUTH_BACKEND = VKontakteOAuth2Backend
+    AUTHORIZATION_URL = 'http://api.vkontakte.ru/oauth/authorize'
+    ACCESS_TOKEN_URL = ' https://api.vkontakte.ru/oauth/access_token'
+    SETTINGS_KEY_NAME = 'VKONTAKTE_APP_ID'
+    SETTINGS_SECRET_NAME = 'VKONTAKTE_APP_SECRET'
+
+    def get_scope(self):
+        return VKONTAKTE_OAUTH2_SCOPE + getattr(settings, 'VKONTAKTE_OAUTH2_EXTRA_SCOPE', [])
+
+    def user_data(self, access_token):
+        """Return user data from VKontakte OpenAPI"""
+        data = {'access_token': access_token }
+        
+        return vkontakte_api('getUserInfoEx', data)
+
+def vkontakte_api(method, data):
+    """ Calls VKontakte OpenAPI method
+        http://vkontakte.ru/apiclub, 
+        http://vkontakte.ru/pages.php?o=-1&p=%C2%FB%EF%EE%EB%ED%E5%ED%E8%E5%20%E7%E0%EF%F0%EE%F1%EE%E2%20%EA%20API
+    """
+
+    params = urlencode(data)
+    request = Request(VKONTAKTE_API_URL + method + '?' + params)
+    try:
+        return simplejson.loads(urlopen(request).read())
+    except (TypeError, KeyError, IOError, ValueError, IndexError):
+        return None
+        
 # Backend definition
 BACKENDS = {
     'vkontakte': VKontakteAuth,
+    'vkontakte-oauth2': VKontakteOAuth2
 }