How to include Django CSRF token in request through ngrok? - python

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!

Related

How to fetch a csrftoken from a django server?

I'm reconfiguring my CDN and I want to begin caching pages that use csrf tokens for form submission. Currently, I'm submitting the csrf token with javascript in a post request with:
axios.defaults.headers.post['X-CSRFToken'] = getCookie('csrftoken')
This works pretty well locally and allowed me to remove the csrf tokens from the templates.
This obviously will not work if I'm accessing cached pages from the CDN. So is it possible for me to fetch a csrf token from the server using Axios and subsequently set it in a post request? If so how do I do this?
An alternative approach would be to disable csrf which I tried already but I couldn't fully disable it. If you are signed into admin csrf protection is automatically enabled even on your frontend forms, I couldn't figure out how to remove this not sure if it's a wagtail or django thing.
I'm using Django 2.2 + Wagtail 2.11.

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.

django admin returns 403 csrf error

I am producing a django/angular project. Django being the backend administration and Angular being the frontend/public display. I have created a Django 1.11 app and loaded all files, installed dependencies, etc. Locally, the site works fine and as expected. Also, since forms will be Angular js I commented out the django.middleware.csrf.CsrfViewMiddleware in my settings.py which I thought would disable the csrf token even being needed, but apparently not.
After setting up server and installing files the admin login page appears but I get the following error when I try and login:
Forbidden (CSRF token missing or incorrect.): /admin/login/
Any ideas on why this is happening would be greatly appreciated.
You can't commented out the 'django.middleware.csrf.CsrfViewMiddleware' in your settings.py, The CSRF middleware provides easy-to-use protection against Cross Site Request Forgeries. Since you are using Augualr js instead of django forms and views, you can set the csrftoken cookie in your browser cookies. Check this for detail: https://docs.djangoproject.com/en/1.11/ref/csrf/#module-django.middleware.csrf

Flask login redirect behind Apache reverse proxy with subpath

My server admin is using Apache to provide a public address by reverse proxying my Flask backend server. Now I don't have much knowledge about ProxyPass but he's provided me with this address:
http://www.example.com/resources/myproject
My Flask server is using #login_required decorator to redirect the user to login page when the user hits home without any session. This works well in the local network where 192.168.1.10:5000 is redirected to 192.168.1.10:5000/login.
But when accessing through the above public address, the user get redirected to:
http://www.example.com/login
instead of
http://www.example.com/resources/myproject/login
which in turn, gives a 404 error.
I also logged to see if I was receiving any X-Forwarded-For headers so that I can use this to fix the problem, but I don't receive any such header from Apache.
I believe you should be using ProxyPassReverse
Also you wouldn't see an X-Forwarded-For header without setting it in Apache.

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

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...

Categories

Resources