在过去的三天里,我花了很大一部分时间尝试互联网上的每一个解决方案,但感到绝望。这是问题陈述:
我有一个包含三个服务的 Dockerized 应用程序:
- 带有gunicorn的django应用程序(
web
)
- Nginx 服务器(
nginx
)
- PostgreSQL (
db
)
我的 Web 应用程序要求用户通过相当标准的 OAuth 流程使用其 GitHub 帐户登录。这一直有效,无需nginx
。用户单击“使用 github 登录”按钮,将其发送到 GitHub 来授权应用程序,并将其重定向回完成页面。
我将“授权回调 URL”填写为http://本地主机:8000 http://localhost:8000。如果没有 Nginx,我可以导航到本地主机上的应用程序,单击按钮,并在授权后重定向回本地主机上的应用程序。
使用 Nginx,我总是会失败并出现错误(控制台中的 nginx):
GET /auth/complete/github/?error=redirect_uri_mismatch&error_description=The+redirect_uri+必须+match+the+registered+callback+URL+for+this+application.&error_uri=https%3A%2F%2Fdeveloper.github.com%2Fapps %2F管理-oauth-apps%2F故障排除-授权-请求-错误%2F%23重定向-uri-不匹配&状态=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 的文档明确指出,重定向 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 的情况下十有八九会出错)是:
作为附加细节,我正在使用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_REFERER and 服务器名称。我还感兴趣的是错误消息:
哪里代替http://localhost:8000
它只有http://localhost
,这看起来像是一个很大的暗示,表明我没有正确配置。任何线索或帮助都会有所帮助!
我尝试过的资源
StackOverflow 线程如this https://stackoverflow.com/questions/17518598/nginx-intercepting-google-oauth-redirect看起来很有希望但类似的问题像这样 https://stackoverflow.com/questions/54912724/using-oauth-in-laravel-gives-error-redirect-uri-mismatch除了解释错误之外,没有收到任何有意义的响应。