Django Social Auth и авторизация в приложениях для ВКонтакте: пример
Пример добавлен в мой fork и в главную ветку вот в этом pull request.
Пример добавлен в мой fork и в главную ветку вот в этом pull request.
Кроме авторизации в приложениях для Facebook в ходе работы над проектом была решена еще одна задача – авторизация в приложениях для ВКонтакте. Как и в случае с Facebook, у меня было сильное желание не делать два раза одну и ту же работу, а использовать одну и ту же базу пользователей и один и тот же механизм для авторизации через сайт ВКонтакте и для авторизации в iframe-приложении ВКонтакте. Это удалось решить без особых сложностей, и вот наконец пришло время сорвать покров тайны с некоторых загадочных настроек.
В отличие от Facebook, у ВКонтакте есть одна принципиальная особенность, которая несколько затрудняет решение этой задачи, а именно: вы не можете использовать одно и то же приложение для авторизации через OAuth и для авторизации в iframe-приложении. Вам необходимо зарегистрировать iframe-приложение для ВКонтакте отдельно и получить для него id и secret.
Другая особенность, которая, наоборот, упрощает работу, заключается в том, что ВКонтакте не делает POST-запрос при переходе на URL вашего приложения, а использует метод GET. То есть, минус одна заморочка с CSRF.
В целом для ВКонтакте используется тот же принцип, что и для Facebook, а именно:
Начнем по порядку.
Чтобы убедиться, что пользователь нашего view авторизован через нужный нам backend, используется функция is_complete_authorization
# Checks the completeness of current user authentication; complete = logged via VKontakte backend def is_complete_authentication(request): return request.user.is_authenticated() and VKontakteOAuth2Backend.__name__ in request.session.get(BACKEND_SESSION_KEY, '')
Декоратор выглядит чуть проще, чем для Facebook, так как не нужно разбирать signed_request.
def vkontakte_intro(func): def wrapper(request, *args, **kwargs): # User must me logged via VKontakte backend in order to ensure we talk about the same person if not is_complete_authentication(request): try: social_complete(request, VKontakteOAuth2Backend.name) except (ValueError, AttributeError): pass # Need to re-check the completion if is_complete_authentication(request): kwargs.update({'access_token': get_access_token(request.user)}) else: request.user = AnonymousUser() return func(request, *args, **kwargs) return wrapper
Назначение у функции get_access_token: вытащить из базы или из кэша access_token для указанного пользователя. Пример:
VK_AT_CACHE_PREFIX = 'VK_AT_%s' # Returns cached access token for the user; loads it from db if needed def get_access_token(user): key = VK_AT_CACHE_PREFIX % str(user.id) access_token = cache.get(key) # If cache is empty read the database if access_token is None: try: social_user = user.social_user if hasattr(user, 'social_user') else UserSocialAuth.objects.get(user=user.id, provider=VKontakteOAuth2Backend.name) except UserSocialAuth.DoesNotExist: return None if social_user.extra_data: access_token = social_user.extra_data.get('access_token') expires = social_user.extra_data.get('expires') cache.set(key, access_token, int(expires) if expires is not None else 0) return access_token
Для работы некоторых методов API вы должны запросить у пользователя установку вашего приложения и нужные вам права. Это две разные операции, первая из которых запускается при вызове функции startConnect, а вторая – следом за ней, в функции requestRights.
{% block head %} <script src="http://vkontakte.ru/js/api/xd_connection.js?2" type="text/javascript"></script> {% endblock %} {% block js %} <script type="text/javascript"> VK.init(function() { // any of your code here } ); function startConnect() { VK.callMethod('showInstallBox'); } function requestRights() { VK.callMethod('showSettingsBox', 1 + 2); // 1+2 is just an example } function onSettingsChanged(settings) { window.location.reload(); } $(document).ready( function(){ VK.addCallback("onApplicationAdded", requestRights); VK.addCallback("onSettingsChanged", onSettingsChanged); }); </script> {% endblock %}
Для того чтобы авторизация через приложение начала работать, нужно сделать следующие настройки:
VKONTAKTE_APP_AUTH={'key':'iframe_app_secret_key', 'user_mode': 2, 'id':'iframe_app_id'}
Параметр user_mode может принимать значения 0, 1 или 2, он влияет на проверку того, подключился пользователь к вашему приложению или нет. Если поставить user_mode в 0, то никакой проверки произведено не будет и авторизация успешно пройдет в любом случае. При user_mode=1 будет проведена проверка на значение параметра is_app_user. Этот параметр приходит в GET-запросе, который присылает ВКонтакте на URL вашего приложения при начале работы с ним. Авторизация будет успешной, только если пользователь подключен к вашему приложению. Однако может случиться так, что пользователь подключился к вашему приложению позже, а запрос уже был проанализирован, is_app_user был 0, а в браузере пользователь уже давно ушел на другую страницу. Для этого используется значение 2, которое делает запрос к API и проверяет, подключил пользователь ваше приложение или нет. Лично я пользуюсь последним вариантом.
Значение key используется для проверки авторизации, id – для выполнения запросов к API. Оно имеет более высокий приоритет по отношению к VKONTAKTE_APP_ID, потому что именно для него вы получаете права от пользователя в интерфейсе.
Если вы не хотите использовать авторизацию через приложение, просто не используйте VKONTAKTE_APP_AUTH совсем.
Пример использования добавлен в главную ветку 23 августа 2012.