Flask JWT Token/ Payload - Return User Json - flask

I understand that Flask JWT gives us the /auth endpoint. Once a user successfully logs in, an access token is assigned and the logged in user can be stored in Flask JWT's current_identity. What I'm wondering is can I also return the User Json back to my client in the same /auth endpoint? Or does it have to be a separate request?
This is for a mobile rest-api, using Flask-Restful. Right now, I have a user log in. The login route (/auth) returns the access token to the client, and then I use the token to get the User Json in a separate request, but I feel like I should be able to condense this into the same request.
Any tips are appreciated :)
IDEA:
Can I create an auth resource via flask-restful and specify exactly what I want it to return? (the token for the server and the user json to the client?)

Flask-JWT has been abandoned for quiet a while now. I would suggest checking out Flask-JWT-Extended instead as an alternative that is still actively maintained (full disclosure, I'm the author of that extension).
In Flask-JWT-Extended you create your own endpoint instead of having the extension create one for you, so you can return whatever data you want there. Here is an example of this in action: http://flask-jwt-extended.readthedocs.io/en/latest/basic_usage.html

Related

How does Djoser JWT login flow works

So I've been trying to use Djoser JWT and I don't know how to login in it. As far as I know you create a request with your login credentials to this url /jwt/create/ and get the access and refresh token and maybe get the user object from /users/me/. This is where I got stuck, where do I go from here?
You correctly understood the first step of the process. Basically, you can now:
Add the access token in the header of your next requests.
This will transparently authenticate the user thanks to the Simple JWT plugin and you will be able to access him with the usual request.user in the views.
Refresh the access token each time you get a 401 response.
The access token is supposed to be short-living for security concerns and a 401 response from the server indicates that the one your are using is expired. So you have to get a new one by sending the refresh token to the token/refresh/ API and, then, make your request again.
You can read this article if you need more detailed explanations about this process or JWT.

Django Rest Framework JWT user register/login concept

I'm creating a Login/Register API with Django Rest Framework which is consumed by my frontend, using JWT to authenticate and there are some basic things I can't seem to understand and maybe someone can help me out.
I created an endpoint to register a user (a POST to /users/). At first I was getting a "Authentication credentials were not provided." if I tried sending a request using Postman (on Django API GUI it would work normally I guess because they already send the correct authentication). However, when I think about it, it comes to me that he doesn't have the credentials yet since he's not registered and logged in, so its JWT wasn't created, so I added permission_classes = (AllowAny, ) to my APIView. But then it allows anyone to use the API, therefore anyone would be able to send a PATCH request to update some info without sending the JWT in the request. Anyone have any idea on how to handle that?
I think somehow I'm lacking some kind of concept about authentication. Maybe I need one exclusively for communicating my backend and frontend that will be used to register a user and the users JWT will be used to perform the other actions?
If needed, I can provide other informations about my architecture or code.
First As per your description,
I created an endpoint to register a user (a POST to /users/). At first I was getting a "Authentication credentials were not provided." if I tried sending a request using Postman (on Django API GUI it would work normally I guess because they already send the correct authentication).
You have to understand that since the api is a user registraion api, the permission class should always be set as permission_class = (AllowAny,), but you set permission_class = (IsAuthenticated,) in your view, so django expecting a proper authentication credential(a JWT token as you are using JWT) to make sure the requested user is authenticated. Thats why you are getting a "Authentication credentials were not provided." exception in your POST /users/ api.
Second, as you said later,
However, when I think about it, it comes to me that he doesn't have the credentials yet since he's not registered and logged in, so its JWT wasn't created, so I added permission_classes = (AllowAny, ) to my APIView
its obvious when a user registering himself/herself, then he/she will not have any credentials(JWT token).
then you said,
But then it allows anyone to use the API, therefore anyone would be able to send a PATCH request to update some info without sending the JWT in the request.
From these lines it seems that you are using single api view to Create(POST) and partial update(PATCH) of user. What you have to do is to make separate api views. That is one api view for Create/Register(POST) user and set permission_classes = (AllowAny, ) and another api view to Update(PATCH) user and set permission_class = (IsAuthenticated,). I think this will solve your problem.
EDITION: Now for better understanding how permission works in django rest framework, lets check this the way permission works in django rest framework.

Firebase Token Authentication using Django

I am new to django and am trying to get the user authenticated using firebase admin sdk. I am trying to do token authentication and have setup the admin sdk in my django app. Also I have received the client id token in the android app.
Now I am unable to understand how to send this id to the backend and verify it as a user and create users accordingly.I did find this answer but couldn't really understand how to go about this.
Also if a user is verified how do I add and update its data. Do I pass the token again or is there any other way to do it?
Your Android App should send its ID token along with all requests sent to the backend server. You can decide how to include that (as a header, as part of a JSON payload etc). In the backend server, you should always call auth.verify_id_token() and return an error (e.g. 401 Unauthorized) if the token fails to validate.

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.