Skip to content

Commit c0a1b61

Browse files
committed
OIDC logout endpoint support
1 parent 6ad8ec6 commit c0a1b61

5 files changed

+58
-15
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ If a [refresh token](https://openid.net/specs/openid-connect-core-1_0.html#Refre
3636

3737
### Logout
3838

39-
Requests made to the `/logout` location invalidate both the ID token and refresh token by erasing them from the key-value store. Therefore, subsequent requests to protected resources will be treated as a first-time request and send the client to the IdP for authentication. Note that the IdP may issue cookies such that an authenticated session still exists at the IdP.
39+
Requests made to the `/logout` location invalidate both the ID token and refresh token by erasing them from the key-value store. Therefore, subsequent requests to protected resources will be treated as a first-time request and send the client to the IdP for authentication. By interacting with `$oidc_logout_endpoint` which is the end session endpoint of IdP, the authenticated session is ended at the IdP.
4040

4141
### Multiple IdPs
4242

@@ -105,7 +105,7 @@ Manual configuration involves reviewing the following files so that they match y
105105

106106
* **openid_connect_configuration.conf** - this contains the primary configuration for one or more IdPs in `map{}` blocks
107107
* Modify all of the `map…$oidc_` blocks to match your IdP configuration
108-
* Modify the URI defined in `map…$oidc_logout_redirect` to specify an unprotected resource to be displayed after requesting the `/logout` location
108+
* Modify the URI defined in `map…$oidc_logout_landing_page` to redirect browser after successful logout
109109
* Set a unique value for `$oidc_hmac_key` to ensure nonce values are unpredictable
110110
* If NGINX Plus is deployed behind another proxy or load balancer, modify the `map…$redirect_base` and `map…$proto` blocks to define how to obtain the original protocol and port number.
111111

configure.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ fi
120120
# Build an intermediate configuration file
121121
# File format is: <NGINX variable name><space><IdP value>
122122
#
123-
jq -r '. | "$oidc_authz_endpoint \(.authorization_endpoint)\n$oidc_token_endpoint \(.token_endpoint)\n$oidc_jwks_uri \(.jwks_uri)"' < /tmp/${COMMAND}_$$_json > /tmp/${COMMAND}_$$_conf
123+
jq -r '. | "$oidc_authz_endpoint \(.authorization_endpoint)\n$oidc_token_endpoint \(.token_endpoint)\n$oidc_jwks_uri \(.jwks_uri)\n$oidc_end_session_endpoint \(.end_session_endpoint)"' < /tmp/${COMMAND}_$$_json > /tmp/${COMMAND}_$$_conf
124124

125125
# Create a random value for HMAC key, adding to the intermediate configuration file
126126
echo "\$oidc_hmac_key `openssl rand -base64 18`" >> /tmp/${COMMAND}_$$_conf
@@ -178,7 +178,7 @@ fi
178178

179179
# Loop through each configuration variable
180180
echo "$COMMAND: NOTICE: Configuring $CONFDIR/openid_connect_configuration.conf"
181-
for OIDC_VAR in \$oidc_authz_endpoint \$oidc_token_endpoint \$oidc_jwt_keyfile \$oidc_hmac_key $CLIENT_ID_VAR $CLIENT_SECRET_VAR $PKCE_ENABLE_VAR; do
181+
for OIDC_VAR in \$oidc_authz_endpoint \$oidc_token_endpoint \$oidc_jwt_keyfile \$oidc_end_session_endpoint \$oidc_hmac_key $CLIENT_ID_VAR $CLIENT_SECRET_VAR $PKCE_ENABLE_VAR; do
182182
# Pull the configuration value from the intermediate file
183183
VALUE=`grep "^$OIDC_VAR " /tmp/${COMMAND}_$$_conf | cut -f2 -d' '`
184184
echo -n "$COMMAND: NOTICE: - $OIDC_VAR ..."

openid_connect.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
var newSession = false; // Used by oidcAuth() and validateIdToken()
77

8-
export default {auth, codeExchange, validateIdToken, logout};
8+
export default {auth, codeExchange, validateIdToken, logout, redirectPostLogout};
99

1010
function retryOriginalRequest(r) {
1111
delete r.headersOut["WWW-Authenticate"]; // Remove evidence of original failed auth_jwt
@@ -253,11 +253,26 @@ function validateIdToken(r) {
253253
}
254254
}
255255

256+
// Default RP-Initiated or Custom Logout w/ OP as per:
257+
// https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout
258+
// https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RedirectionAfterLogout
259+
// An RP requests that the OP log out the end-user by redirecting the end-user's
260+
// User Agent to the OP's Logout endpoint.
256261
function logout(r) {
257262
r.log("OIDC logout for " + r.variables.cookie_auth_token);
258-
r.variables.session_jwt = "-";
259-
r.variables.refresh_token = "-";
260-
r.return(302, r.variables.oidc_logout_redirect);
263+
var queryParams = '';
264+
if (r.variables.oidc_logout_extra_query_params) {
265+
queryParams = '?' + r.variables.oidc_logout_extra_query_params;
266+
}
267+
r.variables.session_jwt = '-';
268+
r.variables.access_token = '-';
269+
r.variables.refresh_token = '-';
270+
r.return(302, r.variables.oidc_end_session_endpoint + queryParams);
271+
}
272+
273+
// Redirect URI after logged-out from the OP.
274+
function redirectPostLogout(r) {
275+
r.return(302, r.variables.oidc_logout_landing_page);
261276
}
262277

263278
function getAuthZArgs(r) {

openid_connect.server_conf

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Advanced configuration START
22
set $internal_error_message "NGINX / OpenID Connect login failure\n";
33
set $pkce_id "";
4+
set $oidc_logout_callback_uri "$redirect_base/_logout";
5+
set $oidc_builtin_logout_query_params "post_logout_redirect_uri=$oidc_logout_callback_uri&id_token_hint=$session_jwt";
46
resolver 8.8.8.8; # For DNS lookup of IdP endpoints;
57
subrequest_output_buffer_size 32k; # To fit a complete tokenset response
68
gunzip on; # Decompress IdP responses if necessary
@@ -67,14 +69,27 @@
6769
}
6870

6971
location = /logout {
72+
# RP-Initiated Logout to interact with $oidc_end_session_endpoint as per:
73+
# https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout
7074
status_zone "OIDC logout";
71-
add_header Set-Cookie "auth_token=; $oidc_cookie_flags"; # Send empty cookie
72-
add_header Set-Cookie "auth_redir=; $oidc_cookie_flags"; # Erase original cookie
7375
js_content oidc.logout;
7476
}
7577

7678
location = /_logout {
77-
# This location is the default value of $oidc_logout_redirect (in case it wasn't configured)
79+
# This location is a RP's callback URI which is called by the IdP after
80+
# successful logout from the IdP by calling $oidc_logout_endpoint.
81+
82+
# Clean cookies
83+
add_header Set-Cookie "auth_token=; $oidc_cookie_flags"; # Send empty cookie
84+
add_header Set-Cookie "auth_redir=; $oidc_cookie_flags"; # Erase original cookie
85+
add_header Set-Cookie "auth_nonce=; $oidc_cookie_flags";
86+
87+
js_content oidc.redirectPostLogout;
88+
}
89+
90+
location = /logout_page {
91+
# This location is a default value of $oidc_logout_landing_page as a
92+
# Built-in, simple logout page in case it wasn't configured.
7893
default_type text/plain;
7994
return 200 "Logged out\n";
8095
}

openid_connect_configuration.conf

+17-4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ map $host $oidc_jwt_keyfile {
2828
default "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs";
2929
}
3030

31+
map $host $oidc_end_session_endpoint {
32+
default "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/logout";
33+
}
34+
35+
map $host $oidc_logout_extra_query_params {
36+
# Each IdP may use different query params of the $oidc_end_session_endpoint.
37+
# For example, Amazon Cognito requires `logout_uri`, and Auth0 requires
38+
# `returnTo` instead of $oidc_default_logout_query_params.
39+
# Define custom params without $oidc_builtin_logout_query_params if necessary.
40+
default $oidc_builtin_logout_query_params;
41+
#www.example.com "client_id=$oidc_client&logout_uri=$oidc_logout_callback_uri";
42+
}
43+
3144
map $host $oidc_client {
3245
default "my-client-id";
3346
}
@@ -44,10 +57,10 @@ map $host $oidc_scopes {
4457
default "openid+profile+email+offline_access";
4558
}
4659

47-
map $host $oidc_logout_redirect {
48-
# Where to send browser after requesting /logout location. This can be
49-
# replaced with a custom logout page, or complete URL.
50-
default "/_logout"; # Built-in, simple logout page
60+
map $host $oidc_logout_landing_page {
61+
# Where to redirect browser after successful logout from the IdP.
62+
default "$redirect_base/logout_page"; # Built-in, simple logout page
63+
#www.example.com $redirect_base;
5164
}
5265

5366
map $host $oidc_hmac_key {

0 commit comments

Comments
 (0)