django REST facebook authentication - django

I have a site that allows Facebook authentication using django-social-auth
Now I also need to authenticate using a non-cookie-based API. My idea is to include a "sessionid=" as a POST field (it will be using HTTPS). So far I managed to "fool" django to access this sessionid as if it were a cookie (I basically do something like request.COOKIES['sessionid'] = request.POST['sessionid'] in a middleware).
My problem is how to give the sessionid to the user right after he authenticated.
From what I could find out, facebook gives the user an "access token" which is then sent to /complete/facebook/ , which is processed by django-social-auth and returns a "Set-cookie" header containing the "sessionid" key. But instead of that, I'd need it to return the sessionid key as a json in the page content (the API client can't read http response header).

Seems like a challenge. But perhaps you can make use of a save signal that fires a Comet event with the required JSON. As a starting point an old version of the django-social-auth doc seems to mention signals.
https://django-social-auth.readthedocs.org/en/v0.7.1/signals.html
However a better approach may be to skip django-social-auth all together and go for a python social auth. The documentation itselfs says:
"NOTE: THIS LIBRARY IS DEPRECATED IN FAVOR OF python-social-auth."

Related

Secure authentication between ReactJS and Django

Been reading and watching quite a bit, and asking a lot of questions regarding ReactJS and Django.
This particularly helped me to understand the the flow of data from Django REST Framework to ReactJS and from ReactJS to Django REST Framework.
Django Forms and Authentication with Front-end Framework (AngularJS/ReactJS)
However, the one thing I am trying to understand is authentication to the Django REST Framework. I understand from the documentation that it has built in authentication. Since this is sensitive data, I would obviously want it protected people retrieving it just by going to http://www.my_site.com/info/api.
I would need to setup ReactJS to be the only thing that can request data from the API whether that is through a key or username/password credentials. I am just curious how this is handled? Obviously I don't want that hard coded in ReactJS because it will compile with the rest of ReactJS.
Here's how I'd approach it: I'd use a JSON Web Token (JWT) for authentication and authorization.
You'd use your back-end to protect ALL API requests from invalid JWT's except for routes where a user won't have a token (ie, registration/log-in pages).
Here's how the flow of the application will go:
A new user registers to your app with standard credentials such as email and password.
Your back-end will create a new user, sign a new JWT token (usually with the user's ID). You'll probably use a third-party library to sign/verify tokens (I don't have experience in the Django community but I am sure a quick Google search will give you answers). Your back-end will send back this token. This is the only time the back-end will receive email, passwords or any other sensitive information on registration.
From this point on React will only use this token for authorization. React will save this token somewhere (ie, localStorage) and send this token along with the other parts of a request to the API routes you created with your back-end. You'll send this token in the authorization headers in the request.
Your back-end will validate this token using a third-party library. If it's invalid the request stops and an unauthorized error is returned. If it's valid the request continues.
This achieves the following:
Your API routes are protected against unauthenticated users
Each request to your API is verified for authorized users which protects anyone from requesting any part of your API.
You can further solidify this by only allowing requests for users to modify their own data. For example, protect Suzy's profile from being modified by people other than herself by only allowing her token with her ID to modify her account/data.
Important Note- Your backend will never save these tokens in storage. It will verify the token on each request. Read more about JSON Web Tokens (JWT) and how it works.
Django Rest Framework has built-in token authentication and a third party package for JWT Token Auth.
If you the standard token auth would work for you, then it could be pretty simple with drf-redux-auth. If you need JWT for some reason, as suggested by Keith above, you could easily fork the above...

Oauth2 workflow of creating and returning access tokens (using Django)

After reading a lot about Oauth2.0, I am still confused regarding following points:
When to create access token? When a user tries to log in or when a user tries to register? Is this token to be sent in HTTP response after logging in?
The client has to store access token somewhere so that it can be sent in every HTTP request by the client. Where should it store it?
Note: I am not doing any third party authentication, just authentication for my own app. I am using Django as the web framework, Django-tastypie for REST API and Django-oauth-provider for Oauth. I followed this excellent tutorial but still have certain doubts. It will be appreciated if the answer is given in the context of these frameworks.

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.

How do I log into django? (Rant warning)

Given:
A default-configured django service, and;
A default-configured django rest framework:
How do I log in?
By "default-configured", I mean that I followed the suggested tutorials of both websites.
However, neither django nor the django rest framework discusses how to use the authentication system as a user. They often seem to discuss authentication from the point of view of the python code running within the django framework.
Where can I read concise, clear documentation that tells me how the user requests the website with correct authentication?
I know that my DEFAULT_PERMISSION_CLASSES in 'REST_FRAMEWORK' is set to: rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly
Which implies that I am probably using whatever authentication is set in the django webservice by default.
And I know that my django instance has "Authenticationmiddleware" and "CsrfViewMiddleware" and the like, whatever they mean. (Ok, CSRF is easy to google, but that's besides the point)
The relevant django documentation seems to be https://docs.djangoproject.com/en/1.5/topics/auth/default/
However, that doesn't tell me how to actually log INTO the website so that I can POST some data.
Where can I find simple, concise instructions that tell me how to:
GET some data as a particular user, and.
POST some data as a particular user.
In the mean time, I will continue perusing the documentation.
So far I have attempted to do:
Obtain the csrf cookie by using GET /api-auth/login/
Perform the login by using POST /api-auth/login/ and providing the cookie obtained in the previous step.
However, Django still detects forgery.
Here is how to do it:
django-rest-framework provides a login page for you if you follow the documentation at http://django-rest-framework.org/
django by default, at least in version 1.5, uses CSRF tokens for security.
In order to login, you need to:
Obtain the cookies by visiting the login page, at /api-auth/login/, including the csrftoken and sessionid. This will be something like: csrftoken=123411231234123; sessionid=143212341234123412
Send the login page as a http POST using the above cookies, and setting the POST as a form with username, password, and csrfmiddlewaretoken as the form elements.
** The value of the csrfmiddleware should be that of the csrftoken value.
So, to re-iterate, the following must be set:
All the original cookies must be set in the POST headers.
The username in the POST form.
The password in the POST form.
The csrfmiddlewaretoken in the POST form.

How to login a Django account from an iOS App?

In my App I need to communicate with my Django website. Some resources require authentication so I need user login.
But this does not happen in a browser or a web view. I need to use Object-C to issue a login request and handle the response - basically to store the session ID I guess.
On the web server side, how should I do this in Django? To have a stand-alone view for that and return JSON maybe? How can I get the newly generated session ID though?
I wouldn't get the session ID. I believe logging in a user is more geared toward a web interface. I would create an API that serves the resources you need in your app. http://en.wikipedia.org/wiki/Representational_state_transfer Authentication would probably be best suited for a private/public key pair or some other similar popular api authentication system.
You don't need to make any changes to your authentication system, save for maybe making sure the login form is usable on the smaller screen. Cookies work the same on iOS as they do on the web. You can display a modal UIWebView with your login form. After the user logs in, presumably you are setting a session cookie. If you make a subsequent request to the domain the cookie matches, the cookie should be sent along. You want to look into the HTTP 'Accept' header field, which specifies the content type the client expects to receive. In your controller (view?), you'll want to check the 'Accept' header, and return the appropriate content type, probably 'application/json' (or a custom type for your API).