Reputation: 349
I'm thinking about architecture of application and we've chosen django-rest-framework + backbone. So I've found token authentication on DRF Tutorial and i have question.
Is it okay if I use token authentication on server side (without auth2) and on the client side there will be frameworks (like oauth.io) for getting token and sending it to server side?
So the problem is i don't know what type of auth to do on server side Token or Oauth2. http://www.django-rest-framework.org/api-guide/authentication#tokenauthentication
vs
http://www.django-rest-framework.org/api-guide/authentication#oauth2authentication
And are there any tutorials for doing that for backbone? Can you advice something.
Thanks in advance.
Upvotes: 1
Views: 512
Reputation: 21
9 years ago is a long time, but this might be useful for anyone looking for a good way to implement token and oAuth2 authentication using a Django backend ,this approach would work for any backend at all (Node.js, Laravel etc). Also, I'm using Google as the oAuth provider but, others like Facebook can be implemented in a similar way.
I recommend using a 3rd-party token authentication package to help do some heavy lifting, for DRF, drf-jwt works very fine. While for a node.js API, jsonwebtoken does the work.
Is it okay if I use token authentication on server side (without auth2) and on the client side there will be frameworks (like oauth.io) for getting token and sending it to server side?
This is the client-side flow, and is very much okay. Here's the full flow:
The user clicks on Signup/Login button
Google returns ID token and user data
On success (from step 2): Expose an endpoint on your backend, and send the user data and ID token (a typical POST request)
On failure (from step 2): Notify error
Backend validates ID token by sending to https://www.googleapis.com/oauth2/v3/tokeninfo
On success (from 5): Using the user data, we check if user exists in our database then we sign user up otherwise we log user in. More on this step later.
On failure (from 5): Notify error
Now, Checking user data in step 6 is just to differentiate a sign-up attempt from a login attempt, and we can do this using django’s <model>.objects.get_or_create()
, for example:
from .models import User
test_user = User.obejcts.get_or_create(email=user_data.email) # user_data is the data sent to the backend
Finally, we sign up for log user in by generating a token for the user, using DRF token auth for example:
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=test_user)
In case, you're using 3rd-party token authentication or you're using other backends like node.js
, generating a token entails:
A) Creating a payload (a using user_data), here's an example of a typical payload:
from calendar import timegm
from datetime import datetime
def unix_epoch(datetime_object):
return timegm(datetime_object.utctimetuple())
issued_at_time = datetime.utcnow()
payload = {
'email': test_user.email,
'iat': unix_epoch(issued_at_time), # issued_at_time in unix epoch (seconds passed since January 1, 1970 00:00:00 UTC)
'exp': issued_at_time + datetime.timedelta(seconds=300) # token expires in 300 seconds or 5 minutes.
}
B) Encoding payload into a token (token generation). This is a somewhat complex thing to do manually, it involves using a signing algorithm like HS256 and a secret key to encode the payload but is usually built into 3rd party auth packages, you'll have to find the function exposed by package you're using to do this. For example, using drf-jwt, we can do:
from rest_framework_jwt.settings import api_settings
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
token = jwt_encode_handler(payload)
drf-jwt uses the HS256 algorithm and the secret key in settings.py
by default.
Using a node-express backend, we can use the jsonwebtoken
library and do:
const jwt = require('jsonwebtoken')
const SECRET_KEY = 'abcdef123456' // You usually want a more secure string and to save this secret key in a .env file so it's accessible using process.env.SECRET_KEY
token = jwt.sign(payload, SECRET_KEY, {"expiresIn”: “5m”) // uses HS256 algorithm by default
Now that we have the token, we can do two things:
Authorization: Bearer <token>
To do this with React.js, Axios interceptor can be used. In Angular.js, we can use the HttpInterceptor. However, I'm not sure how this is done with backbone.js.
Since, the token is saved on the browser (either as cookie or in local storage), it's not completely safe from being hijacked, even with some strict cookie settings.
To do this with DRF:
from rest_framework impart status
from rest_framework.response import Response
response = Response(user_data, status=status.HTTP_201_CREATED)
cookie_param = {
"samesite": "Lax",
"secure": True,
"domain": None, # defaults to server’s IP address
"httponly": True,
"path": "/"
}
cookie_name = 'test_cookie'
response.set_cookie(cookie_name, token, **cookie_param)
To log the user out, all we need to do is hit an exposed endpoint on the backend and delete the cookie.
response = Response(status=status.HTTP_204_NO_CONTENT)
response.delete_cookie(cookie_name)
This second approach of handling our token, I feel is safer than the first.
THAT'S THE END OF THE CLIENT-SIDE FLOW, and yeah, there's a server-side flow too.
Upvotes: 0