From d03ccd9fb351386d9682a1048b91a19ccb6ab7d1 Mon Sep 17 00:00:00 2001 From: Stas Kravets Date: Thu, 28 Apr 2011 15:52:57 +0400 Subject: [PATCH] VKontakte OAuth2 authentication support added. --- example/settings.py | 1 + example/templates/done.html | 3 + example/templates/home.html | 1 + social_auth/backends/contrib/vkontakte.py | 72 +++++++++++++++++++++-- 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/example/settings.py b/example/settings.py index 4fd4c14..06d3e89 100644 --- a/example/settings.py +++ b/example/settings.py @@ -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', ) diff --git a/example/templates/done.html b/example/templates/done.html index 6dab979..cc84635 100644 --- a/example/templates/done.html +++ b/example/templates/done.html @@ -46,6 +46,9 @@ {% if google_oauth2 %}(disconnect){% endif %}
  • Odnoklassniki OAuth 2.0
  • {% if odnoklassniki %}(disconnect){% endif %} +
  • VKontakte OAuth 2.0
  • + {% if vkontakte_oauth2 %}(disconnect){% endif %} + diff --git a/example/templates/home.html b/example/templates/home.html index f5b3360..46c03a6 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -19,6 +19,7 @@ diff --git a/social_auth/backends/contrib/vkontakte.py b/social_auth/backends/contrib/vkontakte.py index ee830df..0c54773 100644 --- a/social_auth/backends/contrib/vkontakte.py +++ b/social_auth/backends/contrib/vkontakte.py @@ -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 } -- 2.39.5