mozilla / mozilla-django-oidc

A django OpenID Connect library
https://mozilla-django-oidc.readthedocs.io
Mozilla Public License 2.0
451 stars 168 forks source link

"redirect_uri" calls "http...callback" instead of "https...callback" in Nginx #417

Open ViktorVikom opened 3 years ago

ViktorVikom commented 3 years ago

Hi! I'm getting helpless, the deadline for the bachelor project is within a week and this unexpected complication is worse than the Spanish inquisition, it took me almost a week of an headache already, which was supposed to be filled with final enhacements of the project.

So, my website uses OIDC to let people from my university to log into it. In localhost/within my LAN everything works fine: "http://localhost(or local IP)/oidc/callback/" - no problem. In the production server it runs in a Docker container and it uses Nginx reverse proxy. When I authenticate myself, I get an "invalid_grant" error because it redirects to "http" instead of "https". In the address bar there's redirect_uri with "http" instead of "https". When I manually change it into "https" it asks me to accept the claims but then I obviously get error 400.

I suppose the the "redirect_uri" takes the "http" because of the proxy and forcing it into "https" causes error because the edit breaks the payload. Do you think the proxy is the reason? If yes, I admit I'm not really sure how to fix it. Setup the proxy in the Django Settings? Or am I completely wrong?

Thank you in advance for any help I apologise if this is not the right place for such question or it's silly or something, the situation starts feeling desperate to me and I don't know where else to ask.

matosmatheus7 commented 3 years ago

The same is happening here, did you get a solution for this problem?

matosmatheus7 commented 3 years ago

Actually, just figured it out, set these parameters on your settings.py file This way everything will process through https

SESSION_COOKIE_SECURE = True
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True
asrozar commented 3 years ago

@matosmts - Where did you find this? I don't see it documented anywhere, and I'm having the same issue where the redirect_uri is being generated with HTTP vs HTTPS. These did not change anything with my situation.

ecogels commented 3 years ago

matosmts's answer is for another package. This package uses django's request.build_absolute_uri to build the various urls.

My setup is nginx -> proxy_pass gunicorn.

What I did was:

Please read the security implication in the documentation. You can also specify individual hosts.

USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Please also read the security implications in the documentation .

sagarguptay2j commented 1 year ago

I was runnning into similar issue i override this function in my custom authentication backend and was able to resolve this: def get_token(self, payload): if not settings.ENV == settings.ENV_LOCAL: payload.update({"redirect_uri": payload.get("redirect_uri").replace("http:", "https:")}) return super().get_token(payload)

   Note: mozilla-django-oidc build logout redirect url also in "http" you may also run into invalid redirect url error while logging out so add http and https both in  keycloak settings -> valid redirect urls or you can change this redirect url to https from code as well
x0lani commented 1 year ago

I'm having the same problem in Azure where Django runs in containers running gunicorn HTTP server behind the proxy. It's not well documented but the solution is to subclass the default OIDCAuthenticationRequestView, override .get() and manually set params['redirect_uri'] to start with 'https://'

Then in settings.py

OIDC_AUTHENTICATE_CLASS='NewOIDCAuthenticationRequestView'

For reference - OIDC_AUTHENTICATE_CLASS

x0lani commented 1 year ago

Just wanted to walk back my previous answer, which will work but is unnecessary. @ecogels solution is the "Django way" to resolve this issue. Just set SECURE_PROXY_SSL_HEADER

For Azure, all I needed was the following in settings.py where IN_PRODUCTION is a flag that detects where the solution is deployed.

SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") if IN_PRODUCTION else None