How to make REST api calls that needs auth_token? - django

I'm working on a Django-REST application that contains APIs that work with login mechanism.
I'm able to create API endpoints for login and logouts.
Login takes username, password and returns auth_token which is around 30 characters.
Logout takes auth_token and destroys it.
In between these login and logouts, there are few API calls that make use of auth_token.
How is it generally implemented ? How are the requests made with auth_token in general?
Where are those tokens stored? How do the backend validates it?
Can someone please explain me how it is done basically?

store the token in browser storage. and remove the token form browser storage on logout logic.
make sure you drf setting DEFAULT_AUTHENTICATION_CLASSES list contain TokenAuthentication class before SessionAuthentication , rest_framework.authtoken in you setting install app.
for any api call just attach the token like (Token your_toke) I mean "Toke" then space the your token and attach it to your request authentication header of the ajax request

Related

Django rest framework json web token logout function

First of all, i am still new to django rest framework jwt so pls excuse my stupidity if im wrong.
Im wondering about how to create a logout function for jwt as when user want to logout and switch account, they will need this function.
Based on the what i seen in many other logout post,
- there is no need for logout function as the token isnt save on server side so closing and opening will result in having to login again.
- jwt is using expire time for it so it will logout when the token has been expire , provided if the verify token is set to True
But what i want is to have like a remember me function where user will stay login when they close and open again, as one of the suggestion is turn the verify token to false or set expire time to weeks. But then how does the user logout if the token expire time hasnt reach yet ?
As i am using jwt and djoser, the logout function of djoser is for drf only and not for jwt. Since i am also using the api for mobile devices, so the user will stay login whenever they open the app (provided they did the first login) like facebook and many other apps.
Please give me guidance on this. Thank you
Ideally, you should be using JWT in a stateless manner, which means the there is no session(The JWT token has an expiration time and will be invalid after that time, clients need to implement some mechanism to re-authenticate or extend the token). Given that, you don't need a log out at all.

Working with django rest framework to authenticate a user with new token for every login

I would like to use django-rest-framework token to authenticate users. My workflow would be:
User requests a page
If auth token is present, respond with the requested data.
If auth token is not present, redirect to the login page (with the request page).
Inside the login page, user submit their credentials
If credentials were correctly authenticated, get or create a token for that user and redirect back to the requested page with the token.
Else, respond with error.
Lastly,
When the user logs out, delete the token for that user.
So my question is, is it okay to delete and create a new token for every login if the user has already logged out? Also I assume the token will be unique, am I correct? Your help and guidance is very much appreciated. Thank you.
A REST API should be stateless, that means that there should not be a "session" hence no login and no logout, and no redirections to a login page.
If the request doesn't have a token then the API should return (probably) a 401 Unauthorized HTTP status code and not a redirection. You're making an API so there won't be human interaction. Django rest framework offers a human-friendly interface that does have sessions, login/logout, and if that's all you need the go for it, you can do whatever you want. But It'd be hard for another program to use your API.
why not using tokens with expiration dates or using another well known authentication method ?? :P
Hope this helps :)

Django REST framework: token authentication with HTML frontend

I want to use token authentication with HTML frontend (like in this tutorial http://www.django-rest-framework.org/topics/html-and-forms/ where they show how to render login form, but not how to actually login).
I have already a login function that returns token, but I don't know how to make web browser remember it and redirect somewhere else.
It is probably possible to pass the token to every template, but it seems a terrible practice
I have taken the help of Sessions in the browsers. You can store your token in the session of the browser and whenever you need it just fetch it.
$window.sessionStorage["token"] = response.data.token;
this is how I am storing it after my LOGIN API and store the token into session. To retrieve I use something like below:
headers: {
'Authorization': 'Token ' + $window.sessionStorage['token']
}
You can look into how to secure your sessions into the browser, also when logging out you can just destroy the session values.

Generate an OAuth2 token in a view

Let's say I have an AngularJS application that consumes the REST API of a Django application.
The Django application has got a built-in OAuth2 provider that can be called to retrieve an access token and use the protected endpoints of the API. This provider is using django-oauth-toolkit.
Let's assume there is a registered client with "password" grant type, so that the end users only need to provide their credentials in the front-end in order to get an access token from the back-end.
At some point we want to add some support for social networks login and we decide to use python-social-auth (PSA) to that end. Here is the workflow I want to achieve:
The user logs in on Facebook from the front-end (via the Facebook SDK) and we get an access token back from the OAuth2 provider of Facebook.
We send the Facebook token to an endpoint of our REST API. This endpoint uses the Facebook token and django-social-auth to authenticate the user in our Django application (basically matching a Facebook account to a standard account within the app).
If the authentication succeeds, the API endpoint requests an access token from the OAuth2 provider for this newly authenticated user.
The Django access token is sent back to the front-end and can be used to access the REST API in exactly the same way that a regular user (i.e. logged in with his credentials) would do.
Now my problem is: how do I achieve step 3? I first thought I would register a separate OAuth2 client with Client Credentials Grant but then the generated token is not user-specific so it does not make sense. Another option is to use the TokenAuthentication from DRF but that would add too much complexity to my project. I already have an OAuth server and I don't want to set up a second token provider to circumvent my problem, unless this is the only solution.
I think my understanding of PSA and django-oauth-toolkit is not deep enough to find the best way of reaching my goal, but there must be a way. Help!
I managed to get something working using urllib2. I can't speak towards whether or not this is good practice, but I can successfully generate an OAuth2 token within a view.
Normally when I'd generate an access token with cURL, it'd look like this:
curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u"<client_id>:<client_secret>" http://localhost:8000/o/token/
So we're tasked with making urllib2 accomplish this. After playing around for some bit, it is fairly straightforward.
import urllib, urlib2, base64, json
# Housekeeping
token_url = 'http://localhost:8000/auth/token/'
data = urllib.urlencode({'grant_type':'password', 'username':<username>, 'password':<password>})
authentication = base64.b64encode('%s:%s' % (<client_id>, <client_secret>))
# Down to Business
request = urllib2.Request(token_url, data)
request.add_header("Authorization", "Basic %s" % authentication)
access_credentials = urllib2.urlopen(request)
json_credentials = json.load(access_credentials)
I reiterate, I do not know if this is in bad practice and I have not looked into whether or not this causes any issues with Django. AFAIK this will do this trick (as it did for me).

Django-allauth, JWT, Oauth

I have an AngularJS Single Page Application that uses a Django backend API based on the Django Rest Framework. The API is protected via django-rest-framework-jwt. I would like to use django-allauth for account management and authentication on the server side.
I am just missing one single piece in the flow: How does my Oauth-Token from the client get transferred into a JWT-token? Basically, I would like to do as described here http://blog.wizer.fr/2013/11/angularjs-facebook-with-a-django-rest-api/ based on python-social-auth.
So my question is, how do I implement the ObtainAuthToken class from the link with django-allauth?
There are usually two login flows with social login: client-side ("Javascript SDK") and server-side. If your server needs to be authorised, it's usually a lot easier to go through the server-side flow. And that's also what all-auth does I think (and you didn't mention you use a frontend library like the blogpost you mentioned does).
Now the challenge is to provide the token from the server to the frontend. You would probably load the token in the HTML of the initialisation of the SPA, and then from Angular save the token client side (cookie, localStorage, etc.) so the session isn't lost on a refresh.
If you don't want the user to leave your app, you can open your /accounts/login/ or /accounts/signup/ url in a new window. In that new window they authorise your app, and your server receives the token upon return. There, you will have to generate a JWT token manually, and render that into the template so that javascript can access it. With js in that popup window, you can then communicate with your app that opened the popup and pass it the token – see this SO answer for an example – so it can save it.
Django-allauth provides signals that let you hook into the social login process. In your case, I would recommend subscribing to the allauth.socialaccount.signals.pre_social_login signal. The code will look something like this:
from allauth.socialaccount.signals import pre_social_login
#receiver(pre_social_login)
def create_jwt_token(sender, request, sociallogin, **kwargs):
# dig into the sociallogin object to find the new access token.
We used hello.js for O-Auth at the company I worked at.
You provide a shim on the Python end and get the refresh token and whatever other data needed once the user connects their social account.
We redirect them via Django to the page they attempted to access from their OAuth provider's page.
Each user still has their own email account which is needed for the JWT, but you could assume that whatever email is in the scope of their social account is their email then use django's functionality to create new users: User.objects.create(email=emailStringFromOauthData) etc.