Authentication with Django channels using Tokens - How do I use this mixin - python

My website hosts a lot of APIs(CRUDs) using DJR. I am using DJR Token based authentication and for testing I would add this header to postman
Key : Authorization
value : Token 826fdf3067b07afdf9edd89a6c9facd9920de8b8
and Django Rest Framework would easily be able to authenticate the user.
Now I inlcuded Django channels constantly 1.1.5 and wanted to know how I could do token based authentication. I read this post and it suggests that I copy this mixin to the project. I just started with Django-channels and am not sure how to include that mixin to my code. Currently I have something like this
#channel_session_user_from_http
def ws_connect(message):
user = message.user
message.reply_channel.send({"accept": True}) #Send back Acceptance response.
#channel_session_user
def chat_join(message):
user = message.user #Get authenticated user
I have the following two questions
1-How do I include that mixin in my current project ? I know you include mixins in classes using class classname(SomeMixin). How would I go about including this mixin into my code ?
2-Will I need to include an authentication token in my json message that I send to the websocket ?
Any suggestions would be great.
`

Related

Custom Authentication in Django Rest Framework

I have a django rest framework application with custom authentication scheme implemented. Now I want to allow external app call some methods of my application.
There's an endpoint for external app to login /external-app-login which implemented like this:
class ExternalAppLoginView(views.APIView):
def post(self, request):
if request.data.get('username') == EXTERNAL_APP_USER_NAME and request.data.get('password') == EXTERNAL_APP_PASSWORD:
user = models.User.objects.get(username=username)
login(request, user)
return http.HttpResponse(status=200)
return http.HttpResponse(status=401)
Now I want to add authentication. I implemented it like this:
class ExternalAppAuthentication(authentication.SessionAuthentication):
def authenticate(self, request):
return super().authenticate(request)
But authentication fails all the time. What is the correct way to do it? I want to store login/password of external app in variables in application, not in database.
The authentication fails, because it needs to return a registered user in your database to authenticate. However as the user info is all in variables instead of database, the issue arises.
There are more than one ways to overcome this issue. Firstly i would suggest you write the authentication code instead of using
return super().authenticate(request) as this would lead you to the real reason of the issue.
Also must give a read to this documentation link, it clears a lot of things regarding authentication.
https://www.django-rest-framework.org/api-guide/authentication/
Now after you have done all that, and you seek ways how to authenticate, then you can try either remote user authentication, or you can check for existing users in your variables and use anonymous user for authentication which resolves the issue.

How to get oauth2 client app from Django request

I'm using oauth2_provider + rest_framework. I have configured several client applications, and they successfully authenticate and receive access tokens.
I would like to have the client app in the request (Eg. request.client). Perhaps I should create some kind of middleware, which sets it, but I'm not sure what is the proper way to do it. Or maybe this functionality is already provided by the oauth2_provider/oauthlib, and I have overlooked it?
The client should be set when:
a valid access token is provided
valid app credentials are provided (like when requesting access token)
Python v3.5.3, Django v1.10.6
oauth2_provider AccessToken has a foreign key
to the application issued that token
You can get the application form the access token like this: application = request.auth.application
AbstractApplication class has foreign key to settings.AUTH_USER_MODEL https://github.com/evonove/django-oauth-toolkit/blob/0.12.0/oauth2_provider/models.py#L62
So if you are using default Application class you could get the clients by request.user.oauth2_providers_applications

Passing values from HTML to python using EVE rest framework

I am creating a website using html as a frontend and python as a backend using EVE framework. I have enabled token authentication for my usersRESTful Account Management. But when I pass the values to the EVE framework it gives me a 401.
var login = function (loginData) {
var deferred = $q.defer();
$http.post(appConfig.serviceUrl + 'user',{data:loginData})
here the loginData holds the username and password of my user from the html page this piece of code is inside a .js file.
My api.py holds the following authentication code.
class RolesAuth(TokenAuth):
def check_auth(self, token, allowed_roles, resource, method):
# use Eve's own db driver; no additional connections/resources are used
accounts = app.data.driver.db['user']
lookup = {'token': token}
if allowed_roles:
lookup['roles'] = {'$in': allowed_roles}
account = accounts.find_one(lookup)
return account
def add_token(documents):
# Don't use this in production:
# You should at least make sure that the token is unique.
for document in documents:
document["token"] = (''.join(random.choice(string.ascii_uppercase)
for x in range(10)))
My problem is as soon as the api.py is run it asks to provide proper credentials. How can i send the token directly to the auth mechanism so that it lets me access the db.
How will you suggest me to get rid of the authentication alert box.
I want the token to be automatically sent to the api.
If suppose I use basic authentication how can I send the username and password values directly and validate it? Without having the browser pop-up box asking for username and password
Thanks in advance.
Does it work with curl ? Refer to this question
Also, refer to this and this thread on the mailing list.

django rest Framework authentications

I have developed an API using django rest framework and have used Token based authentication, Now I have trying to use it from separate project. How I can login using userid and password and get token in response and use token in header in all next url calls.
From Shell I have checked token for one of the user and tested api from terminal and it's working like,
http://127.0.0.1:8000/corporate/company/ -H 'Authorization: Token 9f4702dfddbf89e0346b2ffd10fd69173c178273'
But how to use this token in http calls?
I have included rest_framework.authtoken in installed app and included url in urls.py as:
url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token')
Now I have trying to get it accessed from another project, where I have made one of the login form? Now the Question is where to post form and what fields should be there in form. If I have posted form then token will be returned in response then how Can I parse and use in headers on next calls?
I have gone through tutorial and API guide but no help. On how to access api in my project while Api is ready and login is working through browser-able api url.
Django rest framerwork supports many auth options. You can use Basic Auth if you want.
If you want to use the token you will need to set an http header with the correct token for your user.
From the docs you need to set it as (replace 99... with yours)
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

Django rest-framework does not store authenticated user between calls

For the project I'm currently working on, I decided to write a custom authentication model. I'm using both the rest-framework and all-access. The local authentication is not implemented yet (it is, but in a different version, so no issue there).
The User model registers properly and OAuth authentication works. Users get logged alright.
When working with views, authentication works properly if I use django's View as base class. Not so much if I use rest-framework's APIView.
In my ProfileView (LOGIN_REDIRECT_URL redirects here) I receice a rest_framework.request.Request instance, which is OK by me. The problem is:
request.user is an instance of AnonymousUser (even after login)
I would guess the problem lies with my implementation, but then:
request._request.user is an authenticated user
(Note that request._request is the original django request)
I tend to think this is a rest-framework bug, but maybe one of you knows of a workaround?
Edit
Just to note that the login is made in a non-APIView class, but instead in a class that inherits from View. That's probably the reason the User instance is not passed to the APIView instance.
You need to set the DEFAULT_AUTHENTICATION_CLASSES in your settings.py. Else DRF will default to None as request.auth and AnonymousUser as request.user
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
)
}
Once you set that and the user is logged in, ensure that the session_id is available in the request headers. Browsers typically store the session information and pass it in the headers of all requests.
If you are using a non-browser client (Eg. a mobile app), you will need to set the session id manually in the header.
Also since you mentioned you use oauth to sign-in the user, for oauth2 you need to specify the oauth2 authorization header instead of the session id.
"Authorization: Bearer <your-access-token>"
Refer to Authenticating in Django Rest Framework

Categories