Django-Rest-Auth authentication issue - python

I have created REST API using Django Rest Framework and used django-rest-auth for auth endpoints. These APIs are used in mobile apps. I've used TokenAuthentication to secure the API.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
The problem arises when using APIDOC. I've added apidoc using coreapi. The documentation needs to be protected too. I get below error when I access /docs/ with above settings:
'dict' object has no attribute 'data'
So I enabled SessionAuthentication.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
This resulted in login endpoint (/rest-auth/login) breaking with CSRF error.
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
So how do I protect the endpoints with just TokenAuth and the documentation with SessionAuth separately? Or can I completely bypass security for login endpoint?

Authentication classes can be defined separately while defining the URLs:
url(r'^docs/', include_docs_urls(title='PeySO API Doc', public=False,
authentication_classes=[SessionAuthentication])),
This allows us to enable SessionAuthentication just for docs and use TokenAuthentication for the API endpoints.

Related

Why does django rest framework app works locally, but can only do GET requests when deployed to heroku?

I cannot do methods other than GET when accessing the API on heroku. Else, I get a 500 internal server error.
I suspected that it had to do with permissions:
REST_FRAMEWORK = {
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
# Authentication Scheme
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
# Permission Policies
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
However, when I tried commenting out the DEFAULT_AUTHENTICATION_CLASSES, I still couldn't log in.
I am using django-rest-auth if that helps (https://django-rest-auth.readthedocs.io/en/latest/installation.html)
Again, it works on my local server (I haven't tried heroku local though). What else am I missing?

Django OAuth- Separate Resource and Authorization Server

I'm using Django Oauth Library.
I want to have different Auth and Resource Server.
On Auth Server, following is my setting.
INSTALLED_APPS = [
...
'oauth2_provider',
'rest_framework',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
# ############## OAUTH SETTINGS ###################
OAUTH2_PROVIDER = {
'SCOPES': {'users': 'user details', 'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups', 'introspection': 'introspection'},
'ACCESS_TOKEN_EXPIRE_SECONDS': 86400, # 1 Day.
}
On my Resource Server
INSTALLED_APPS = [
...
'oauth2_provider',
'rest_framework',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
# ############## OAUTH SETTINGS ###################
OAUTH2_PROVIDER = {
'RESOURCE_SERVER_INTROSPECTION_URL': 'http://localhost:8000/o/introspect/',
'RESOURCE_SERVER_AUTH_TOKEN': '3yUqsWtwKYKHnfivFcJu',
}
Question 1)
How do I obtain RESOURCE_SERVER_AUTH_TOKEN?
Question 2)
Upon introspecting the token, Auth Server returns 403 Forbidden Error in the console logs.
Following is the flow to obtain the access token.
I get the client_id, client_secret, grant_type and scopes from the client POST request onto the Resource Server. I call the AuthServer from the Resource Server and return the response back to the client.
What exactly am I missing over here?
According django-oauth-toolkit implementation, Resource server first tries to check whether access token is available in its db or not.
If access token is not present, it will check introspection URL and introspection token are available in settings. If introspection settings is available then resource server tries to validate the user token with an introspection endpoint.
So the issue seems to be that AUTH SERVER and DRF might be returing 403 Forbidden since the permission is set as IsAuthenticated. This could be either due to invalid token or invalid user.
So create a user for the resource server and then create an application for the resource server user.
creating the application,
client_type=Application.CLIENT_CONFIDENTIAL
authorization_grant_type=Application.GRANT_AUTHORIZATION_COD‌​E
And generate a token through the admin site and update the resource server INTROSPECTION setting with the newly created token. Make sure you put the appropriate scopes while creating the token.

Django rest - Custom authentication backend with browsable api

I am using Django 1.11 and Django rest framework 3.6.2
I created a custom authentication backend:
MyAuthBackend(rest_framework.authentication.BasicAuthentication):
# ...
and added it to the settings.py file:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES' : ('path.to.MyAuthBackend',)
}
I also tried to extend SessionAuthentication without success
My issue is that users are trying to log in via the browsable api and it looks like the authentication backend that the browsable api is using is not the default one.
Where can I change that? I have to use my own auth backend in the browsable api,
Thank you.
I don't think it's possible to use BasicAuthentication in the browseable api (without changing a whole bunch of its internals).
Consider keeping the SessionAuthentication alongside your new one, you can use basic authentication in your app and session authentication in the browsable api:
'DEFAULT_AUTHENTICATION_CLASSES': (
'path.to.MyAuthBackend',
'rest_framework.authentication.SessionAuthentication',
),

getting Oauth 2 Invalid Client error while checking the application created in django project

I have created a project in django rest framework and installed django auth provider and created a application and generated the client id and client secret and when i am testing the application using curl request
curl -X POST -d "grant_type=password&username=&password=" -u":" http://localhost:8000/o/token/
I tested by giving my username,password, client_id and client_request showing error like
{"error": "invalid_client"}
settings.py
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope',
'write': 'Write scope',
'groups': 'Access to your groups'}
}
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
)
}
You're using 'o'i n your url so your urs.py has to contain
url(r'^o/(?P<token>[\w-]+)/$', YourView.as_view()),
Looks like your url is not known to urls.py
For example having
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),)
would make
curl http://127.0.0.1:8000/users/1/
render normally.

Django - accessing Django Rest endpoint on AWS Elastic Beanstalk

Very new to AWS and deploying my own projects/services in general. I deployed my first Django Rest API on Beanstalk.
I can access the application URL in the browser (http://myappenv.someid.us-west-2.elasticbeanstalk.com/, no problem.
However when I use that base url in my application on localhost, I get a 403: Authentication credentials were not provided.
I am passing the DRF Token in the header, just like I normally would to access each endpoint. ie http://myappenv.someid.us-west-2.elasticbeanstalk.com/mentions.
When I switch back to a local version of the API in my application, I can access it normally.
My application is hitting the endpoint but, for some reason, even with the token passing, its returning the 403
my DRF is setup in settings.py as follows:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
#'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication'
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
) ,
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
}
Any ideas? Would appreciate any feedback.
After going through the DRF documentation, I have to adjust my DEFAULT_PERMISSION_CLASSES

Categories