-
Notifications
You must be signed in to change notification settings - Fork 94
Open
Description
Good day!
I ran my test installation through this guide (https://docs.nginx.com/nginx/deployment-guides/single-sign-on/keycloak/)
And started to get infinite loop after access token expired.
It seems strange.
First step go the site https://main.example.com/
step 2 -> 302 redirect to https://keycloak.example.com/
step 3 -> auth in keycloak
step 4 -> 302 to https://main.example.com/
step 5 -> after 5 minutes (access token ttl) browser started return 302 from main.example.com to keycloak, keycloak send 302 to main.example and infinite loop....
server {
listen 443 ssl;
server_name main.example.com;
include conf.d/locations-openid;
location / {
include conf.d/locations-openid_auth_jwt;
proxy_pass https://upstream;
}
}
# conf.d/locations-openid_auth_jwt;
auth_jwt "" token=$session_jwt;
error_page 401 = @do_oidc_flow;
auth_jwt_key_request /_jwks_uri; # Enable when using URL
proxy_set_header username $jwt_claim_sub;
#conf.d/locations-openid
# Advanced configuration START
set $internal_error_message "NGINX / OpenID Connect login failure\n";
set $pkce_id "";
subrequest_output_buffer_size 32k; # To fit a complete tokenset response
gunzip on; # Decompress IdP responses if necessary
# Advanced configuration END
location = /_jwks_uri {
auth_jwt off;
internal;
proxy_cache jwk; # Cache the JWK Set recieved from IdP
proxy_cache_valid 200 12h; # How long to consider keys "fresh"
proxy_cache_use_stale error timeout updating; # Use old JWK Set if cannot reach IdP
proxy_ssl_server_name on; # For SNI to the IdP
proxy_method GET; # In case client request was non-GET
proxy_set_header Content-Length ""; # ''
proxy_set_header Accept-Encoding "gzip"; # fixed OIDC authorization code sent but token response is not JSON
proxy_pass $oidc_jwt_keyfile; # Expecting to find a URI here
proxy_ignore_headers Cache-Control Expires Set-Cookie; # Does not influence caching
}
location @do_oidc_flow {
auth_jwt off;
status_zone "OIDC start";
js_content oidc.auth;
default_type text/plain; # In case we throw an error
}
set $redir_location "/_codexch";
location = /_codexch {
# This location is called by the IdP after successful authentication
auth_jwt off;
status_zone "OIDC code exchange";
js_content oidc.codeExchange;
error_page 500 502 504 @oidc_error;
}
location = /_token {
# This location is called by oidcCodeExchange(). We use the proxy_ directives
# to construct the OpenID Connect token request, as per:
# http://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
auth_jwt off;
internal;
proxy_ssl_server_name on; # For SNI to the IdP
proxy_set_header Content-Type "application/x-www-form-urlencoded";
proxy_set_header Accept-Encoding "gzip"; # fixed OIDC authorization code sent but token response is not JSON
proxy_set_body "grant_type=authorization_code&client_id=$oidc_client&$args&redirect_uri=$redirect_base$redir_location";
proxy_method POST;
proxy_pass $oidc_token_endpoint;
}
location = /_refresh {
# This location is called by oidcAuth() when performing a token refresh. We
# use the proxy_ directives to construct the OpenID Connect token request, as per:
# https://openid.net/specs/openid-connect-core-1_0.html#RefreshingAccessToken
auth_jwt off;
internal;
proxy_ssl_server_name on; # For SNI to the IdP
proxy_set_header Content-Type "application/x-www-form-urlencoded";
proxy_set_body "grant_type=refresh_token&refresh_token=$arg_token&client_id=$oidc_client&client_secret=$oidc_client_secret";
proxy_method POST;
proxy_pass $oidc_token_endpoint;
}
location = /_id_token_validation {
# This location is called by oidcCodeExchange() and oidcRefreshRequest(). We use
# the auth_jwt_module to validate the OpenID Connect token response, as per:
# https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
internal;
auth_jwt "" token=$arg_token;
js_content oidc.validateIdToken;
error_page 500 502 504 @oidc_error;
}
location = /logout {
auth_jwt off;
status_zone "OIDC logout";
add_header Set-Cookie "auth_token=; $oidc_cookie_flags"; # Send empty cookie
add_header Set-Cookie "auth_redir=; $oidc_cookie_flags"; # Erase original cookie
js_content oidc.logout;
}
location = /_logout {
# This location is the default value of $oidc_logout_redirect (in case it wasn't configured)
auth_jwt off;
default_type text/plain;
return 200 "Logged out\n";
}
location @oidc_error {
# This location is called when oidcAuth() or oidcCodeExchange() returns an error
auth_jwt off;
status_zone "OIDC error";
default_type text/plain;
return 500 $internal_error_message;
}
# openid.conf
# OpenID Connect configuration
#
# Each map block allows multiple values so that multiple IdPs can be supported,
# the $host variable is used as the default input parameter but can be changed.
#
map $host $oidc_authz_endpoint {
default "https://keycloak/realms/main/protocol/openid-connect/auth";
#www.example.com "https://my-idp/oauth2/v1/authorize";
}
map $host $oidc_authz_extra_args {
# Extra arguments to include in the request to the IdP's authorization
# endpoint.
# Some IdPs provide extended capabilities controlled by extra arguments,
# for example Keycloak can select an IdP to delegate to via the
# "kc_idp_hint" argument.
# Arguments must be expressed as query string parameters and URL-encoded
# if required.
default "";
#www.example.com "kc_idp_hint=another_provider"
}
map $host $oidc_token_endpoint {
default "https://keycloak/realms/main/protocol/openid-connect/token";
}
map $host $oidc_jwt_keyfile {
default "https://keycloak/realms/main/protocol/openid-connect/certs";
}
map $host $oidc_client {
default "nginx-openid";
}
map $host $oidc_pkce_enable {
default 0;
}
map $host $oidc_client_secret {
default "secret";
}
map $host $oidc_scopes {
default "openid+profile+email+offline_access";
}
map $host $oidc_logout_redirect {
# Where to send browser after requesting /logout location. This can be
# replaced with a custom logout page, or complete URL.
default "/_logout"; # Built-in, simple logout page
}
map $host $oidc_hmac_key {
# This should be unique for every NGINX instance/cluster
default "key";
}
map $host $zone_sync_leeway {
# Specifies the maximum timeout for synchronizing ID tokens between cluster
# nodes when you use shared memory zone content sync. This option is only
# recommended for scenarios where cluster nodes can randomly process
# requests from user agents and there may be a situation where node "A"
# successfully received a token, and node "B" receives the next request in
# less than zone_sync_interval.
default 0; # Time in milliseconds, e.g. (zone_sync_interval * 2 * 1000)
}
map $proto $oidc_cookie_flags {
http "Path=/; SameSite=lax;"; # For HTTP/plaintext testing
https "Path=/; SameSite=lax; Max-Age=86400; HttpOnly; Secure;"; # Production recommendation
}
#map $http_x_forwarded_port $redirect_base {
# "" $proto://$host:$server_port;
# default $proto://$host:$http_x_forwarded_port;
#}
map $http_x_forwarded_port $redirect_base {
default $proto://$host;
}
map $http_x_forwarded_proto $proto {
"" $scheme;
default $http_x_forwarded_proto;
}
# ADVANCED CONFIGURATION BELOW THIS LINE
# Additional advanced configuration (server context) in openid_connect.server_conf
# JWK Set will be fetched from $oidc_jwks_uri and cached here - ensure writable by nginx user
proxy_cache_path /var/cache/nginx/jwk levels=1 keys_zone=jwk:100m max_size=512m;
# Change timeout values to at least the validity period of each token type
keyval_zone zone=oidc_id_tokens:100M timeout=4h;
keyval_zone zone=oidc_access_tokens:100M timeout=4h;
keyval_zone zone=refresh_tokens:10M timeout=1d;
keyval_zone zone=oidc_pkce:512K; # Temporary storage for PKCE code verifier.
keyval $cookie_auth_token $session_jwt zone=oidc_id_tokens; # Exchange cookie for JWT
keyval $cookie_auth_token $access_token zone=oidc_access_tokens; # Exchange cookie for access token
keyval $cookie_auth_token $refresh_token zone=refresh_tokens; # Exchange cookie for refresh token
keyval $request_id $new_session zone=oidc_id_tokens; # For initial session creation
keyval $request_id $new_access_token zone=oidc_access_tokens;
keyval $request_id $new_refresh zone=refresh_tokens; # ''
keyval $pkce_id $pkce_code_verifier zone=oidc_pkce;
auth_jwt_claim_set $jwt_audience aud; # In case aud is an array
js_import oidc from js/openid_connect.js;
and unmodified js/openid_connect.js; from main branch
3rgfbrgf
Metadata
Metadata
Assignees
Labels
No labels