There are times when you want to link your own service account with an external service account such as facebook or Twitter using OAuth. For Python3, you can easily add an external account linkage screen for Web services by using python-social-auth. However, if you want to do the same with a smartphone app, you need to provide a link function with API, so a memo about how to handle it.
This time, we assume the user takeover function in the smartphone app. The external services I want to use are facebook and Twitter. The following two functions are implemented.
[Social Auth with Django REST Framework] (https://yeti.co/blog/social-auth-with-django-rest-framework/)
Python 3.4.3 Django 1.8
As the flow of authentication processing, the following usage using OAuth is assumed.
Install python-social-auth
python
$ pip install python-social-auth
Settings for python-social-auth
settings.py
INSTALLED_APPS = (
...
'social.apps.django_app.default',
...
)
TEMPLATE_CONTEXT_PROCESSORS = (
...
'social.apps.django_app.context_processors.backends',
'social.apps.django_app.context_processors.login_redirect',
...
)
AUTHENTICATION_BACKENDS = (
'social.backends.facebook.FacebookOAuth2',
'social.backends.twitter.TwitterOAuth',
'django.contrib.auth.backends.ModelBackend',
)
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
#Remove the user so that it will not be created when checking the credentials.
#'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details',
)
SOCIAL_AUTH_TWITTER_KEY = "MY_TWITTER_APP_KEY "
SOCIAL_AUTH_TWITTER_SECRET = "MY_TWITTER_APP_SECRET"
SOCIAL_AUTH_FACEBOOK_KEY = "MY_FACEBOOK_APP_ID"
SOCIAL_AUTH_FACEBOOK_SECRET = "MY_FACEBOOK_APP_SECRET"
Creating a table for authentication information
python
$ ./manage.py migrate
Project-wide url settings
myproject/urls.py
from django.conf.urls import url
urlpatterns = [
...
url('', include('social.apps.django_app.urls', namespace='social'))
...
]
URL setting of the app you want to use the linkage function
myapp/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
# 1.API to link an external account to an existing user
url(r'api/associate/(?P<backend>[^/]+)/$', views.associate_account, name='associate_account'),
# 2.API to get linked user information from external account information
url(r'api/auth/(?P<backend>[^/]+)/$', views.auth_account, name='auth_account'),
]
View of the app you want to use the linkage function
myapp/views.py
from django.contrib.auth import login
from rest_framework import status
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, permission_classes
from social.backends.oauth import BaseOAuth1, BaseOAuth2
from social.apps.django_app.utils import psa
# 1.API to link an external account to an existing user
@api_view(('POST',))
@permission_classes((IsAuthenticated,))
@psa('social:complete')
def associate_account(request, backend):
backend = request.backend
token = _make_token(request, backend)
#User is returned only when authentication with OAuth is successful
user = backend.do_auth(token, user=request.user)
if user:
login(request, user)
return Response({'success': True})
else:
return Response({"errors": "Error with social authentication"},
status=status.HTTP_400_BAD_REQUEST)
# 2.API to get linked user information from external account information
@api_view(('POST',))
@psa('social:complete')
def auth_account(request, backend):
backend = request.backend
token = _make_token(request, backend)
#User is returned only when authentication with OAuth is successful and there is a user associated with that information
user = backend.do_auth(token)
if user:
return Response({'id': user.id, 'username': user.username})
else:
return Response({"errors": "User Not Found"},
status=status.HTTP_404_NOT_FOUND)
#The shape of the token used is different between OAuth1 and OAuth2
def _make_token(request, backend):
if isinstance(backend, BaseOAuth1):
token = {
'oauth_token': request.data.get('access_token'),
'oauth_token_secret': request.data.get('access_token_secret'),
}
elif isinstance(backend, BaseOAuth2):
token = request.data.get('access_token')
return token
Access the URL (ex. Http://myserver/myapp/api/associate/twitter/) with associate_account set with a browser.
As shown in the screen above, enter access_token and access_token_secret in json format in content and press [POST].
{
"access_token": "my_access_token",
"access_token_secret": "my_access_token_secret"
}
If {" success ": true}
is returned, authentication is successful.
Access the URL (ex. Http://myserver/myapp/api/auth/twitter/) for which auth_account is set with a browser, and perform the same procedure as in the previous section.
Success if the ID of the user who linked earlier is returned.
You can check it with almost the same procedure as Twitter, but the following two points are different.
twitter
to facebook
.. (OAuth2 does not have ʻaccess_token_secret
)python-social-auth Convenient! I was able to write the code required for authentication in just a few lines!
However, this implementation seems to have finally been realized by gathering various scattered English information, and I got the impression that Python has little information in Japanese.
I want to log in on Twitter and Facebook with Python 3.4 and Django 1.6.5-Today's Hack http://narusemotoki.tumblr.com/post/90525892180/python-34%E3%81%A8django-165%E3%81%A7twitter%E3%82%84facebook%E3%81%A7%E3%81%AE%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%92%E3%81%97%E3%81%9F%E3%81%84
omab/python-social-auth https://github.com/omab/python-social-auth
Django Framework — Python Social Auth documentation https://python-social-auth.readthedocs.org/en/latest/configuration/django.html
Pipeline — Python Social Auth documentation https://python-social-auth.readthedocs.org/en/latest/pipeline.html#authentication-pipeline
Use Cases — Python Social Auth documentation http://psa.matiasaguirre.net/docs/use_cases.html#signup-by-oauth-access-token
Twitter OAuth using access_token · Issue #272 · omab/python-social-auth https://github.com/omab/python-social-auth/issues/272
Social Auth with Django REST Framework - Yeti https://yeti.co/blog/social-auth-with-django-rest-framework/
Recommended Posts