django - OAuth 回调 URL 与 nginx 代理服务器行为不兼容
问题描述
在过去的 3 天里,我花了很大一部分时间尝试互联网上的所有解决方案,并感到绝望。这是问题陈述:
我有一个包含三个服务的 Dockerized 应用程序:
- 带有 gunicorn (
web
)的 django 应用程序 - Nginx 服务器 (
nginx
) - PostgreSQL (
db
)
我的 Web 应用程序要求用户通过相当标准的 OAuth 流程使用他们的 GitHub 帐户登录。这在没有nginx
. 用户单击“使用 github 登录”按钮,将他们发送到 GitHub 以授权应用程序,并将其重定向回完成页面。
我将“授权回调 URL”填写为http://localhost:8000。如果没有 Nginx,我可以导航到 localhost 上的应用程序,单击按钮,并在授权后重定向回我在 localhost 上的应用程序。
使用 Nginx,我总是会因错误而失败(控制台中的 nginx):
GET /auth/complete/github/?error=redirect_uri_mismatch&error_description=The+redirect_uri+MUST+match+the+registered+callback+URL+for+this+application.&error_uri=https%3A%2F%2Fdeveloper.github.com%2Fapps %2Fmanaging-oauth-apps%2Ftroubleshooting-authorization-request-errors%2F%23redirect-uri-mismatch&state=nmegLb41b959su31nRU4ugFOzAqE8Cbl HTTP/1.1
这是我的 Nginx 配置:
upstream webserver {
# docker will automatically resolve this to the correct address
# because we use the same name as the service: "web"
server web:8000;
}
# now we declare our main server
server {
listen 80;
server_name localhost;
location / {
# everything is passed to Gunicorn
proxy_pass http://webserver;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
}
location /static {
autoindex off;
alias /static_files/;
}
location /media {
alias /opt/services/starport/media;
}
}
这是我的 Dockerfile:
version: '3.7'
services:
web:
build: .
command: sh -c "cd starport && gunicorn starport.wsgi:application --bind 0.0.0.0:8000"
volumes:
- static_files:/static_files # <-- bind the static volume
networks:
- nginx_network
nginx:
image: nginx
ports:
- 8000:80
volumes:
- ./config/nginx/conf.d:/etc/nginx/conf.d
- static_files:/static_files # <-- bind the static volume
depends_on:
- web
networks:
- nginx_network
networks:
nginx_network:
driver: bridge
volumes:
static_files:
我的预感是它在没有 Nginx 的情况下工作但与 Nginx http 服务器无关的原因与重定向有关,因为 Nginx 正在侦听一个端口,然后将其转发到另一个端口。GitHub 的 doc 专门说重定向 URI 需要和注册的回调 url 完全一样。我还使用了检查器工具,这些是我的请求标头:
GET /accounts/login/ HTTP/1.1
Cookie: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Upgrade-Insecure-Requests: 1
Host: localhost:8000
User-Agent: Mozilla/5.0
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: keep-alive
我用 Nginx 得到的错误消息(再次强调它就像一个魅力,没有 nginx 10 次中的 10 次没有错误)是:
作为附加细节,我正在使用该social-auth-app-django
软件包,但这无关紧要。
进一步的故障排除
经过无数小时的探索,我在本地调试模式下运行它,这次密切监视我的请求信息。当使用点击链接通过 OAuth 向 GitHub 授权时,这是请求以及所有标头信息:
CSRF_COOKIE 'abc'
HTTP_ACCEPT 'text/html,application/xhtml+xml'
HTTP_ACCEPT_ENCODING 'gzip, deflate'
HTTP_ACCEPT_LANGUAGE 'en-us'
HTTP_CONNECTION 'close'
HTTP_COOKIE ('csrftoken=...; ')
HTTP_HOST 'localhost'
HTTP_REFERER 'http://localhost:8000/accounts/login/?next=/'
HTTP_USER_AGENT ('Mozilla/5.0')
HTTP_X_FORWARDED_FOR '172.26.0.1'
HTTP_X_FORWARDED_PROTO 'http'
PATH_INFO '/auth/complete/github/'
SERVER_NAME '0.0.0.0'
SERVER_PORT '8000'
QUERY_STRING
'error=redirect_uri_mismatch&error_description=The+redirect_uri+MUST+match+the+registered+callback+URL+for+this+application.&error_uri=https%3A%2F%2Fdeveloper.github.com%2Fapps%2Fmanaging-oauth-apps%2Ftroubleshooting-authorization-request-errors%2F%23redirect-uri-mismatch&state=NwUhVqfOCNb51zpvoFbXVvm1Cr7k3Fda'
RAW_URI
'/auth/complete/github/?error=redirect_uri_mismatch&error_description=The+redirect_uri+MUST+match+the+registered+callback+URL+for+this+application.&error_uri=https%3A%2F%2Fdeveloper.github.com%2Fapps%2Fmanaging-oauth-apps%2Ftroubleshooting-authorization-request-errors%2F%23redirect-uri-mismatch&state=NwUhVqfOCNb51zpvoFbXVvm1Cr7k3Fda'
立即让我印象深刻的是HTTP_HOST、HTTP_REFERRER和SERVER_NAME的值。对我来说也很有趣的是错误消息说:
where 而不是http://localhost:8000
只有http://localhost
,这看起来像是一个很大的暗示,表明我没有正确配置东西。任何线索或帮助都会有所帮助!
我试过的资源
解决方案
推荐阅读
- idl - 如何升级 REDHAWK SDR 框架以支持 SCA 4.1 规范(软件通信架构)
- bixby - 如何在 Bixby 中重置配置文件存储的数据
- excel - Datagrid 在 WPF 中使用 for 循环给出空值
- windows - 如何从 Windows 服务应用程序运行包含 OpenSSL 加密文件命令的 Windows 批处理文件
- java - 在 ios 真实设备中启动应用程序
- angular - Angular Router:将模块加载为延迟加载模块的子模块
- javascript - “客户端需要将 JSON 转换为 HTML”含义
- vue.js - 填充数据时添加行样式,鼠标悬停时删除
- typescript - 如何使用异步函数提供多种返回类型
- json - 如何将json数据从s3的字符串映射到雅典娜?