Reputation: 4935
I'm developing an iOS app and using Django for backend. There are two apps I'm using in Django
Django OAuth Toolkit
to support OAuth authenticationPython Social Auth
to support social authenticationThe social authentication process should be:
Then, I can use my server's access token to communicate with {application}.
But the client will see that the browser start with localhost/login/{application} and end with localhost/accounts/profile, and still don't know what is my server's access token, so my question is how to pass the access token to the client?
One solution is that redirect with access token as localhost/accounts/profile?token=MyServerToken, but how to add parameter when redirecting to profile url?
Upvotes: 4
Views: 3491
Reputation: 47906
You should not pass the access token in the query string like /?token=my_token
. Its not a secure way and definitely not recommended.
Some other approaches you can use are:
Approach-1: Setting server_access_token
in response headers
You can set the access token in the response headers and send it using HTTPS protocol.
The token will be sent once and consumed by the client. Since the response headers are not passed in the subsequent requests, the token will be passed only once to the client. Client will then use it to make further requests by setting the token in the request headers.
class MySocialApplicationRedirectView(View):
def get(self, request, *args, **kwargs):
# Here, write your code to fetch the {application}'s access token,
# creating a new user with your server's access token, and then
# associating it with {application}'s access token
# assign the response to a variable and set the access token as a header in the response
response = HttpResponseRedirect('/accounts/profile/')
response['X-Auth-Token'] = 'my_server_access_token'
# can also use the below name as 'X-' prefixed headers are deprecated
# response['Auth-Token'] = 'my_server_access_token'
return response
Client can then retrieve the token from the headers and use this token to make further requests. In further requests, he must send the access token in request headers.
Approach-2: Setting server_access_token
as a cookie
Another option is to set the server_access_token
cookie in your response as @Ben mentioned.
response.set_cookie()
would set the server_access_token
cookie in the response and then the client can read the cookie and send this in further requests in the request headers.
class MySocialApplicationRedirectView(View):
def get(self, request, *args, **kwargs):
# Here, write your code to fetch the {application}'s access token,
# creating a new user with your server's access token, and then
# associating it with {application}'s access token
# assign the response to a variable and set the access token as a cookie in the response object
response = HttpResponseRedirect('/accounts/profile/')
response.set_cookie(key, value='my_server_access_token', ..other parameters )
return response
Note: For safety and security, all requests (both to obtain and use the tokens) must use HTTPS endpoints.
Upvotes: 1
Reputation: 15226
You likely already have what you need on the Django session for your user in question. That is, provided you are using the session middleware (auth of this type is nearly impossible without it), your identity provider specific tokens will usually be populated in the extra_data
dict on the SocialUser
model for the specific provider in question.
For example, assuming you have a reference to the Django user model (lets call it user
):
access_token = user.social_auth.get(provider='google-oauth2').extra_data['access_token']
Unfortunately the specifics will vary depending on the backend you're working with. Remember that these tools are designed to let users authenticate against your app rather than to let you perform arbitrary actions against the product-specific APIs exposed by the various identity providers.
As for passing these tokens to the client, I'd need to know more about your use case. Chances are the identity provider in question set some session cookies on the client during its authentication flow. For example, if you sign in with Facebook, they set a few cookies which are automatically retrieved by the Facebook client-side javascript API. As such, there's no explicit sharing of tokens necessary between the server and the client.
Otherwise, if you must do it yourself, store them on a secure session cookie as follows:
response.set_cookie(social_auth_tokens,
value=your_data_here,
max_age=None, #cookie will expire at end of user session
expires=None,
path='/',
domain=None, #only readable by this domain
secure=True, #only transmitted over https
httponly=False) #readable by scripts running on the page
Upvotes: 2