I'm serving my django app behind a reverse proxy
The internet -> Nginx -> Gunicorn socket -> Django app
In the nginx config:
upstream my_server {
server unix:/webapps/my_app/run/gunicorn.sock fail_timeout=0;
}
The SSL is set up with certbot at the nginx level.
request.build_absolute_uri in views.py generates http links. How can I force it to generate https links?
By default Django ignore all X-Forwarded headers, base on Django docs.
Force read the X-Forwarded-Host header by setting USE_X_FORWARDED_HOST = True and set SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'). So in settings.py:
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
I use django behind apache2 so my solution was to put this on apache2
<VirtualHost *:443>
RequestHeader set X-Forwarded-Proto 'https' env=HTTPS
After adding headers mod:
a2enmod headers
And this on django setting.py:
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
With this all my build_absolute_uri started with https
There's a note in the django documentation here https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpRequest.build_absolute_uri:
Mixing HTTP and HTTPS on the same site is discouraged, therefore build_absolute_uri() will always generate an absolute URI with the same scheme the current request has. If you need to redirect users to HTTPS, it’s best to let your Web server redirect all HTTP traffic to HTTPS.
Related
My django Rest API return image URL path http://blah/media/blah.jpg.
But I want to return https://blahblah.
Is there any attribute in settings.py?
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
I Inserted this and tried
SECURE_SSL_REDIRECT = True
but it throws 301 code and nothing rendered.
Media setting
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
For serving media files there are two ways to do:
By serving media and static files using nginx, in that case you need
to enable ssl in nginx and it will come as https://
by returning media file path from rest framework like /media/image1.jpg and adding your domain at client side like
https://mydomainxyz.com/media.image1.jpg
When you activate SECURE_SSL_REDIRECT in django it redirect every request to https server django development server do not work on https you will need nginx or apache server for that and enable ssl settings. This is the reason nothing is getting rendered. For more read here in django documentation
I'm experimenting with an app running on Angular 2 in the frontend and Django as API and I can't access the CSRF cookie sent from Django.
As you can see, I am getting back the cookie from the server but I cannot access it from the browser (document.cookie) or Angular 2 (using the ng2-cookies module).
Everything was working while testing on localhost, now client and server are running on different hosts and this might be the reason of the problem.
Client running on https://django-angular2-movies.firebaseapp.com/
Server running on https://glacial-shore-18891.herokuapp.com
This is part of the settings I'm using on Django:
settings.py
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CSRF_COOKIE_SECURE = False
CSRF_TRUSTED_ORIGINS = ['django-angular2-movies.firebaseapp.com']
ALLOWED_HOSTS = ['*']
Other things that I have tried, but didn't help:
Removing the CSRF_TRUSTED_ORIGINS setting
Adding CSRF_COOKIE_DOMAIN = 'django-angular2-movies.firebaseapp.com'
Using { withCredentials: true } in the request sent from the client
Using the #ensure_csrf_cookie decorator on Django views
What am I doing wrong?
Thanks
Previously I was working on my Django app on a local server and all my settings work with django-allauth (I was using manage.py runserver rather than nginx + gunicorn for staging/production)
Now, I'm implementing django-allauth to my staging website, but I can't make it work on my staging server (Note: In this example I've replaced my domain name to mydomain.com).
Basically after I clicked the link to login with Facebook at http://staging.mydomain.com/accounts/login/, it redirects to https://www.facebook.com/dialog/oauth?response_type=code&state=YXdAxg2WiIBo&redirect_uri=http%3A%2F%2Fstaging.mydomain.com%2Faccounts%2Ffacebook%2Flogin%2Fcallback%2F&client_id=1600059933550804&scope=email&auth_type=reauthenticate and I get the following errors:
Given URL is not allowed by the Application configuration.: One or
more of the given URLs is not allowed by the App's settings. It must
match the Website URL or Canvas URL, or the domain must be a subdomain
of one of the App's domains.
Here are my setting files:
nginx conf file
server {
listen 80;
server_name staging.mydomain.me;
location /static {
alias /home/myusername/sites/staging.mydomain.me/static;
}
location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/staging.mydomain.me.socket;
}
}
settings.py
...
SITE_ID = 1
LOGIN_REDIRECT_URL = '/'
ACCOUNT_EMAIL_REQUIRED = True
SOCIALACCOUNT_PROVIDERS = {
'facebook': {
'SCOPE': ['email'],
'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
'METHOD': 'oauth2',
'VERIFIED_EMAIL': False,
}
}
AUTH_USER_MODEL = 'users.User'
ACCOUNT_ADAPTER = 'users.adapters.AccountAdapter'
ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.UserApplicationForm'
ACCOUNT_LOGOUT_ON_GET = True
...
Settings in Facebook app
Settings in Sites [http://staging.mydomain.com/admin/sites/site/1/]
Settings in Social application [http://staging.mydomain.com/admin/socialaccount/socialapp/2/]
Try one of theese 2 things:
create a test app for your facebook app, and set the staging.mydomain.com domain for it, configure a brand new social app (allauth) with the new api key and secret (for your new test app), a new django site, and so on...
change your facebook app settings to have staging.mydomain.com as its app domain.
I think both solutions will work, but I prefer the first one, as your staging app perfectly fits in definition of 'test app' and therefore, I think is a more elegant solution.
Hope this helps you.
When using nginx as a proxy to the request, django continue to believe that my site url is 127.0.0.1:myport.
Add this to your settings.py:
USE_X_FORWARDED_HOST = True
It will tell django to use the X-FORWARDED-HOST header that nginx pass.
I created a Client ID and Client Secret from the google cloud api console and added a record in the Social apps table for django-allauth
I also added WEB ORIGIN:
mysite.com (prod)
http://localhost:8000 (dev)
and REDIRECT URI
http:mysite.com/accounts/google/login/callback/ (prod)
localhost:8000/accounts/google/login/callback/ (dev)
in the google api console.
Sign in with Google works great in development and redirects to the localhost callback url on successful sign-in. But I'm getting a redirect_uri_mismatch error in prod.
These are the error details from the google error page:
Request Details
cookie_policy_enforce=false
scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
response_type=code
access_type=online
redirect_uri=http://127.0.0.1:8000/accounts/google/login/callback/
state=SOME_RANDOM_NUMBER
display=page
client_id=MY_CLIENT_ID
The redirect_uri is still set to 127.0.0.1 instead of http:mysite.com/accounts/google/login/callback/
So how do I set the proper redirect_uri?
This is my settings.py pertaining to django-allauth
INSTALLED_APPS = (
#the usual stuff
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
)
import django.conf.global_settings as DEFAULT_SETTINGS
TEMPLATE_CONTEXT_PROCESSORS = DEFAULT_SETTINGS.TEMPLATE_CONTEXT_PROCESSORS + (
"allauth.account.context_processors.account",
"allauth.socialaccount.context_processors.socialaccount",
)
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
)
ACCOUNT_EMAIL_REQUIRED = True
LOGIN_REDIRECT_URL = "/"
Here's urls.py
urlpatterns = patterns('',
url(r'^accounts/', include('allauth.urls')),
)
I haven't made any other django-allauth settings.
I saw the docs and couldn't find where to make the change.
I found that the issue occurs because the nginx proxy, which sits in front of the python app server, sets the HTTP Host header to localhost.
So when allauth tries to do request.build_absolute_uri, HTTP_HOST is localhost.
So I set the Setting proxy_set_header in the nginx configuration file which fixed the issue.
proxy_set_header Host $http_host;
Also see Facebook oauth authentication is redirecting to localhost instead of to my domain for the same issue in a different avatar.