1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
Use Cases
=========
Some miscellaneous options and use cases for python-social-auth_.
Return the user to the original page
------------------------------------
There's a common scenario were it's desired to return the user back to the
original page from where it was requested to login. For that purpose, the usual
``next`` query-string argument is used, the value of this parameter will be
stored in the session and later used to redirect the user when login was
successful.
In order to use it just define it with your link, for instance, when using
Django::
<a href="{% url 'social:begin' 'facebook' %}?next={{ request.path }}">Login with Facebook</a>
Pass custom GET/POST parameters and retrieve them on authentication
-------------------------------------------------------------------
In some cases, you might need to send data over the URL, and retrieve it while
processing the after-effect. For example, for conditionally executing code in
custom pipelines.
In such cases, add it to ``FIELDS_STORED_IN_SESSION``.
In your settings::
FIELDS_STORED_IN_SESSION = ['key']
In template::
<a href="{% url 'social:begin' 'facebook' %}?key={{ value }}">Login with Facebook</a>
In your custom pipeline, retrieve it using::
strategy.session_get('key')
Retrieve Google+ Friends
------------------------
Google provides a `People API endpoint`_ to retrieve the people in your circles
on Google+. In order to access that API first we need to define the needed
scope::
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
'https://www.googleapis.com/auth/plus.login'
]
Once we have the ``access token`` we can call the API like this::
import requests
user = User.objects.get(...)
social = user.social_auth.get(provider='google-oauth2')
response = requests.get(
'https://www.googleapis.com/plus/v1/people/me/people/visible',
params={'access_token': social.extra_data['access_token']}
)
friends = response.json()['items']
Associate users by email
------------------------
Sometimes it's desirable that social accounts are automatically associated if
the email already matches a user account.
For example, if a user signed up with his Facebook account, then logged out and
next time tries to use Google OAuth2 to login, it could be nice (if both social
sites have the same email address configured) that the user gets into his
initial account created by Facebook backend.
This scenario is possible by enabling the ``associate_by_email`` pipeline
function, like this::
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',
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email', # <--- enable this one
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
)
This feature is disabled by default because it's not 100% secure to automate
this process with all the backends. Not all the providers will validate your
email account and others users could take advantage of that.
Take for instance User A registered in your site with the email
``foo@bar.com``. Then a malicious user registers into another provider that
doesn't validate his email with that same account. Finally this user will turn
to your site (which supports that provider) and sign up to it, since the email
is the same, the malicious user will take control over the User A account.
Signup by OAuth access_token
----------------------------
It's a common scenario that mobile applications will use an SDK to signup
a user within the app, but that signup won't be reflected by
python-social-auth_ unless the corresponding database entries are created. In
order to do so, it's possible to create a view / route that creates those
entries by a given ``access_token``. Take the following code for instance (the
code follows Django conventions, but versions for others frameworks can be
implemented easily)::
from django.contrib.auth import login
from social.apps.django_app.utils import strategy
# Define an URL entry to point to this view, call it passing the
# access_token parameter like ?access_token=<token>. The URL entry must
# contain the backend, like this:
#
# url(r'^register-by-token/(?P<backend>[^/]+)/$',
# 'register_by_access_token')
@strategy('social:complete')
def register_by_access_token(request, backend):
# This view expects an access_token GET parameter
token = request.GET.get('access_token')
backend = request.strategy.backend
user = backend.do_auth(request.GET.get('access_token'))
if user:
login(request, user)
return 'OK'
else:
return 'ERROR'
The snipped above is quite simple, it doesn't return JSON and usually this call
will be done by AJAX. It doesn't return the user information, but that's
something that can be extended and filled to suit the project where it's going
to be used.
Multiple scopes per provider
----------------------------
At the moment python-social-auth_ doesn't provide a method to define multiple
scopes for single backend, this is usually desired since it's recommended to
ask the user for the minimum scope possible and increase the access when it's
really needed. It's possible to add a new backend extending the original one to
accomplish that behavior, there are two ways to do it.
1. Overriding ``get_scope()`` method::
from social.backends.facebook import FacebookOAuth2
class CustomFacebookOAuth2(FacebookOauth2):
def get_scope(self):
scope = super(CustomFacebookOAuth2, self).get_scope()
if self.data.get('extrascope'):
scope += [('foo', 'bar')]
return scope
This method is quite simple, it overrides the method that returns the scope
value in a backend (``get_scope()``) and adds extra values tot he list if it
was indicated by a parameter in the ``GET`` or ``POST`` data
(``self.data``).
Put this new backend in some place in your project and replace the original
``FacebookOAuth2`` in ``AUTHENTICATION_BACKENDS`` with this new version.
2. It's possible to do the same by defining a second backend which extends from
the original but overrides the name, this will imply new URLs and also new
settings for the new backend (since the name is used to build the settings
names), it also implies a new application in the provider since not all
providers give you the option of defining multiple redirect URLs. To do it
just add a backend like::
from social.backends.facebook import FacebookOAuth2
class CustomFacebookOAuth2(FacebookOauth2):
name = 'facebook-custom'
Put this new backend in some place in your project keeping the original
``FacebookOAuth2`` in ``AUTHENTICATION_BACKENDS``. Now a new set of URLs
will be functional::
/login/facebook-custom
/complete/facebook-custom
/disconnect/facebook-custom
And also a new set of settings::
SOCIAL_AUTH_FACEBOOK_CUSTOM_KEY = '...'
SOCIAL_AUTH_FACEBOOK_CUSTOM_SECRET = '...'
SOCIAL_AUTH_FACEBOOK_CUSTOM_SCOPE = [...]
When the extra permissions are needed, just redirect the user to
``/login/facebook-custom`` and then get the social auth entry for this new
backend with ``user.social_auth.get(provider='facebook-custom')`` and use
the ``access_token`` in it.
.. _python-social-auth: https://github.com/omab/python-social-auth
.. _People API endpoint: https://developers.google.com/+/api/latest/people/list
|