File: use_cases.rst

package info (click to toggle)
python-social-auth 0.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 2,828 kB
  • ctags: 3,245
  • sloc: python: 12,867; makefile: 119; sh: 3
file content (209 lines) | stat: -rw-r--r-- 7,849 bytes parent folder | download
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