使用Keycloak通过Twitter登录Nginx应用时遇Error 504/404问题
问题描述
点击Twitter登录按钮后,出现504/404错误,请求地址为GET https://******.com/realms/fm-users/broker/twitter/,返回404 (Not Found)。已完成Keycloak Twitter身份提供商配置,以及Twitter开发者平台OAuth 2.0的ID和密钥设置。
前端Nginx配置
server { listen 80; server_name frontend; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location /manifest.json { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /manifest.json; } location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; auth_basic "Restricted Content"; auth_basic_user_file /etc/nginx/.htpasswd; } #--------keycloak--------- location /realms/fm-users/ { proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Scheme $scheme; client_max_body_size 30m; } location /resources/ { proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Scheme $scheme; client_max_body_size 30m; } #--------fm-ms-image-provider--------- location \/api\/save-image(.*)$ { proxy_pass http://app-fm-image-provider-users:9205; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; } location \/api\/remove-image\/(.*)$ { proxy_pass http://app-fm-image-provider-users:9205; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; } location \/public\/api\/image(.*)$ { proxy_pass http://app-fm-image-provider-users:9205; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; } #--------fm-ms-system--------- location \/public\/api\/module-types\/program\/(.*)$ { proxy_pass http://app-fm-system:9202; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; } #--------fm-ms-users--------- location \/api\/user\/(.*)$ { proxy_pass http://app-fm-users:9203; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; } location \/public\/api\/(.*)$ { proxy_pass http://app-fm-users:9203; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; } location \/api\/(.*)$ { proxy_pass http://app-fm-users:9203; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; } }
上层负载均衡Nginx配置
server { listen 80; listen [::]:80; server_name ****.com; return 301 https://****.com; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; client_max_body_size 4M; } server { listen 443 ssl; server_name ****.com; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; client_max_body_size 30m; ssl_certificate /etc/nginx/certificate/fm/users/nginx-certificate.crt; ssl_certificate_key /etc/nginx/certificate/fm/users/nginx.key; #--------keycloak--------- location /realms/fm-users/ { include /etc/nginx/includes/proxy.conf; proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080; client_max_body_size 30m; } location /resources/ { include /etc/nginx/includes/proxy.conf; proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080; client_max_body_size 30m; } access_log /var/log/nginx/logs-fm.log main; error_log /var/log/nginx/error-fm.log error; location / { include /etc/nginx/includes/proxy.conf; proxy_pass http://app-fm-tower; } }
解决方案
你的Nginx配置里,Keycloak的代理规则只覆盖了/realms/fm-users/和/resources/,但Twitter登录的请求路径/realms/fm-users/broker/twitter/虽然匹配/realms/fm-users/,但Nginx的proxy_pass路径匹配规则会导致路径传递错误:当location路径以/结尾且proxy_pass不带路径时,Nginx会把匹配到的路径部分替换为空,将请求转发到http://fm-keycloak:8080/broker/twitter/,而Keycloak的实际端点是http://fm-keycloak:8080/realms/fm-users/broker/twitter/,这就引发了404。
修正步骤
修改两层Nginx中Keycloak相关的location配置,确保路径完整传递:
- 上层负载均衡Nginx修改:
location /realms/fm-users/ { include /etc/nginx/includes/proxy.conf; proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080/realms/fm-users/; # 添加完整路径后缀 client_max_body_size 30m; } location /resources/ { include /etc/nginx/includes/proxy.conf; proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080/resources/; # 添加完整路径后缀 client_max_body_size 30m; }
- 前端Nginx修改:
location /realms/fm-users/ { proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080/realms/fm-users/; # 添加完整路径后缀 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Scheme $scheme; client_max_body_size 30m; } location /resources/ { proxy_read_timeout 90; proxy_pass http://fm-keycloak:8080/resources/; # 添加完整路径后缀 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Scheme $scheme; client_max_body_size 30m; }
修改后,请求/realms/fm-users/broker/twitter/会被正确代理到Keycloak的对应端点,解决404问题。另外,504错误大概率是代理超时导致,当前proxy_read_timeout 90足够覆盖OAuth跳转流程,若仍出现可适当延长该值。
内容的提问来源于stack exchange,提问作者user22958704

