Django OAuth 2 client setup - client isn't recognizing tokens - python

I attempting to use the Django OAuth Toolkit in a project I'm working on. I've set up two servers - one as the OAuth provider and another as a client service that is accessed only by authenticated users.
The OAuth provider seems to be working just fine. I'm able to create a link on the client service that directs to the OAuth provider. The user then logs in, and is prompted whether to allow/deny the application. If the user allows the application, the user is then redirected back to the client service, and the URI contains the access token. Because this service needs to be accessible from both a website and a mobile client, I'm using an implicit grant, and following this way of doing things: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#browser-based-apps.
Everything with the provider seems to work as expected, but I'm having issues with the client service app, which is also a Django application. It doesn't appear to recognize the token in the redirect URI, and as a result I'm unable to make any authenticated requests against the service.
I've made the following changes to the client service's settings.py:
I've added the AUTHENTICATION_BACKENDS section, as follows:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'oauth2_provider.backends.OAuth2Backend',
)
I've added oauth2_provider.middleware.OAuth2TokenMiddleware to the MIDDLEWARE_CLASSES section.
I've added oauth2_provider to the INSTALLED_APPS.
The REST_FRAMEWORK section now looks like:
REST_FRAMEWORK = {
'DEFAULT_MODEL_SERIALIZER_CLASS':
'rest_framework.serializers.HyperlinkedModelSerializer',
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
I've also added the OAUTH_PROVIDER section:
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}
}
As near as I can figure, there must be something else that I'm missing in my settings.py that will tell Django to look for the token, but I'm at a bit of a loss on what this might be.
Can someone point me in the right direction on what I might be missing here?
EDIT: I should clarify the results I'm getting when attempting to call something on the client service. When I make a curl request to the client service, like so (except with real values plugged in):
curl -H "Authorization: Bearer token_goes_here" https://service.com/api/some_api/call
I get a result of:
{"detail": "Authentication credentials were not provided."}
It's as if the client service isn't looking in the right place for the credentials, which makes me think that something isn't set up quite right.

DEFAULT_PERMISSION_CLASSES IsAuthenticated for REST_FRAMEWORK is blocked non auth requests.
If you planned using javascript to access your REST API see https://github.com/evonove/django-oauth-toolkit/blob/master/oauth2_provider/tests/test_implicit.py
For "Implicit Grant Flow" you must:
login via ModelBackend with user login and password.
create oauth2 application ( /o/applications/ )
or from django console, see test.
get auth token from "/o/authorize/" url with logged in user.
then you must add token to "'HTTP_AUTHORIZATION': 'Bearer ' + access_token," header, to access API resourses.
And, i think, at this workflow we do not need auth_backends and middleware because we have DEFAULT_AUTHENTICATION_CLASSES in REST_FRAMEWORK.
All grant types you can see in DOT based on lib
https://oauthlib.readthedocs.org/en/latest/oauth2/grants/grants.html
Or you can use more simplest "Resource owner password-based" as in DOT documentation described...

Related

social-app-django - Setup REDIRECT URL for GoogleOAuth2 not working?

I am using social-app-django GoogleOAuth2 backend and hit a problem with redirect_uri
I managed to setup INSTALLED_APP, AUTHENTICATION_BACKENDS, url.py and add below 3 in settings
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY='MY KEY'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET='MY SECRET'
LOGIN_REDIRECT_URL='http://localhost:8000/api/auth/complete/google-oauth2/'
I have http://localhost:8000/api/complete/google-oauth2/ added into my google Authorised redirect URIs.
I triggered auth login by accessing http://127.0.0.1:8000/login/google-oauth2/ (yes, my project use react on frontend, so not using Django templates).
Problem is I always get this error
Error: redirect_uri_mismatch
The redirect URI in the request, http://127.0.0.1:8000/complete/google-oauth2/, does not match the ones authorized for the OAuth client. To update the authorized redirect URIs, visit: ....
The redirect_url in generated auth url is always http://127.0.0.1:8000/complete/google-oauth2/ and if I replace it with the on I configured in Google console, then it works. So I am guessing it must be something settings related.
It looks like redirect url settings does work, any idea what's wrong? Please help!
You can add redirect_uri inside the auth_params along with access_type in settings file.
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
],
'AUTH_PARAMS': {
'access_type': 'online',
'redirect_uri': 'http://127.0.0.1:8000/<custom-url>'
}
}
}

LDAP authentication isnt happening over django rest API

I am authenticating users who login against through django REST framework against NIS using pythonPAM . But when I make the changes to settings.py as mentioned below, user credentials isnt being verified against LDAP.
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
)
This along with ldap credentials for binding is used.
Note: I can connect to LDAP server and get all teh details. Its only a problem with django restframework.
I also tried
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.RemoteUserBackend',]
and it did not work.
Currently in my urls.py, I call url(/login,) endpoint and authenticate against NIS server. How do I change it to LDAP?
I am new to django and need help on this.

Django and React getting 403 forbidden

I've used create-react-app combined with Django Rest Framework to make a small site. Everything works perfectly when I use npm start and hit the Django API from one port to another. When I npm build the static react files and serve them from within the Django app, however, I get 403 forbidden when hitting a number of endpoints. I think it has something to do with CSRF, but I can't figure out what.
I serve the static files from views.py:
#api_view(['GET'])
def serve_html(request):
try:
with open(os.path.join(REACT_APP_DIR, 'build', 'index.html')) as f:
return HttpResponse(f.read())
except FileNotFoundError:
return HttpResponse(
"""
This URL is only used when you have built the production
version of the app. Visit http://localhost:3000/ instead, or
run `yarn run build` to test the production version.
""",
status=501,
)
My urls.py contains the catchall for the static files at the bottom:
urlpatterns = [
# ..all api paths
url(r'^', serve_html, name='serve_html'),
]
I use TokenAuthentication and SessionAuthentication:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
)
}
And the api requests that require users to be logged in have the following decorators:
#authentication_classes((SessionAuthentication, TokenAuthentication))
#permission_classes((IsAuthenticated,))
Addendum: I notice that when running it cross-origin, there is no sessionid cookie (and things work), but when I try to host react files on same-origin, there is a sessionid cookie (and 403 Forbidden is returned).
Sorry for the open-endedquestion, but I'm at my wit's end here; I really don't know why it's not working.
You do not require the SessionAuthentication class since you are using a token-based HTTP Authentication scheme. This should do the trick:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
Hope this helps.

How to include Django CSRF token in request through ngrok?

I am building a Django app that will be hosted on a local network and perform authentication using Facebook Login. Since Facebook Login requires the callback address for a login to either be localhost or publicly-addressable, I'm using ngrok to create an address for Facebook to return data to.
After the user logs in with Facebook, I perform a POST with AJAX from the template with their data to a local view (/fb_login) which saves to my database in Django. Since authentication is based on this database, I don't think it's wise to avoid the CSRF checks Django performs on this view.
To include the CSRF token in the POST to /fb_login, I'm using the following which a few forums suggested:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
This should only include the CSRF token to relative URLs (which I understand to be the best practice). When I run the server on localhost and perform the Facebook Login from the same machine, this works fine. However, when I run the system on localhost and access it through ngrok from another machine on the local network and perform the Facebook Login, I get a 403 and a message saying the CSRF check failed. This leads me to believe that the ngrok URL isn't considered "local", so the CSRF token isn't being set.
Assuming I know what my ngrok URL is at the time my Django server starts, can I include it in what's considered a "local" address for the purposes of including the CSRF token? Is there another way to do this securely? As a note, web development is not my area, so please let me know if I'm misunderstanding something here. Thanks!

Django_hosts Not Working With Django's Default Authentication

I'm using this package called django_hosts to re-route urls for some apps.
Everything is working fine except for the fact that django_hosts is not working with Django Authentication.
I hosted this url api.example.com, so on this page with the url api.example.com:8000/add_post, I want users to add post but before doing that you must be authenticated. So after I logged in, I still can't submit post via the form talkless of posting. But when I go back to example.com, it shows that I'm logged in but api.example.com is telling me otherwise.
How do I make django authentication work with this package?
The problem is that the authentication token is hooked to the domain. Using Django's default configuration, the api.example.com can't access the example.com auth token.
You can change this behaviour by setting the SESSION_COOKIE_DOMAIN configuration in your settings.py module:
SESSION_COOKIE_DOMAIN = 'example.com'
But not too fast! Do it carefully, otherwise you can break your application:
Be cautious when updating this setting on a production site. If you
update this setting to enable cross-domain cookies on a site that
previously used standard domain cookies, existing user cookies will be
set to the old domain. This may result in them being unable to log in
as long as these cookies persist.
More info on the official documentation.

Categories

Resources