Django OAuth- Separate Resource and Authorization Server - python

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.

Related

Django Rest Framework and AWS Cognito

Currently, I am using django-warrant to utilize cognito (JWT) based authentication to access APIs. After creating pool and app, I have set up following in my settings file:
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'django_warrant.backend.CognitoBackend',
]
COGNITO_USER_POOL_ID = 'poolid'
COGNITO_APP_ID = 'app id'
COGNITO_ATTR_MAPPING = {
'email': 'email',
'given_name': 'name',
'family_name': 'last name',
}
COGNITO_CREATE_UNKNOWN_USERS = False
AWS_ACCESS_KEY_ID = 'access_key'
AWS_SECRET_ACCESS_KEY = 'access_key_secret'
In Midddleware, I have added:
MIDDLEWARE = [
.............,
'warrant.django.middleware.APIKeyMiddleware',
..............,
]
In Installed apps, I have added,
INSTALLED_APPS = [
............,
'django_warrant',
............,
]
In urls.py, I have added:
path('accounts/', include('django_warrant.urls'))
When I try to hit accounts/login url, it is throwing the error of missing templates.
As I am using it for the first time, I am clueless how to proceed further with it to map django users with cognito users. I have searched tutorials related to this but found None. Please provide me guidance so that I can manage to proceed further.

Django Rest Framework HTTP Post Calls and Authentication with Ionic Framework

I implemented the Django Rest Framework into my Django project so I could use Django as a backend to my Ionic Framework app while maintaining the web app that I can make with Django. I went through the process to OAuth2, using the oauth toolkit, but now I am unsure on how to make the http request calls from the ionic framework side to authenticate a user and get a token. So far on the Ionic side I have the http request as:
login(username, password, url) {
let headers = new Headers()
headers.append("Content-Type", "application/x-www-form-urlencoded");
return this.http.post(url,
{"username": username,
"password": password,
}, {headers: headers})
.map(res => res.json());
}
But when I run it in my browser, I get No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 500.
On the server side the curl command curl -X POST -d "grant_type=password&username=USERNAME&password=PASSWORD" -u "CLIENT ID:CLIENT SECRET" https://www.example.com/o/token/ works perfectly fine and returns a token, where USERNAME, PASSWORD, CLIENT ID, and CLIENT SECRET are all the respective values.
I'm not sure if this is the right question, but how do I turn the cURL command into something I can use in my Ionic app?
These are my Rest Framework and CORS Settings:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated'
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
]
}
CORS_ORIGIN_WHITELIST = [
'localhost:8100',
]
CORS_ALLOW_CREDENTIALS = True
So it turns out that if you are sending requests with the origin being localhost or 127.0.0.1, which is the same thing, most browsers send the origin as Null, so it is better to add CORS_ORIGIN_ALLOW_ALL = True to the settings.py file of the main Django project.
Once that was there, I was getting errors about the grant_type being invalid, so in my request I had to add "grant_type": "password", and I also had to add "client_id": <your client id here> where the <your client id here> is your client id without the <>.
I also found that Postman is a great application to help with api creation and translating cURL commands into HTTP requests that work.

Django-Rest-Auth authentication issue

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.

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