Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evolve oidc logout #4986

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/crd/bases/k8s.nginx.org_policies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ spec:
type: boolean
authEndpoint:
type: string
logoutEndpoint:
type: string
authExtraArgs:
items:
type: string
Expand All @@ -146,6 +148,8 @@ spec:
type: string
redirectURI:
type: string
redirectPostLogout:
type: string
scope:
type: string
tokenEndpoint:
Expand Down
4 changes: 4 additions & 0 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@ spec:
type: boolean
authEndpoint:
type: string
logoutEndpoint:
type: string
authExtraArgs:
items:
type: string
Expand All @@ -348,6 +350,8 @@ spec:
type: string
redirectURI:
type: string
redirectPostLogout:
type: string
scope:
type: string
tokenEndpoint:
Expand Down
4 changes: 4 additions & 0 deletions docs/content/configuration/policy-resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,8 @@ spec:
authEndpoint: https://idp.example.com/openid-connect/auth
tokenEndpoint: https://idp.example.com/openid-connect/token
jwksURI: https://idp.example.com/openid-connect/certs
logoutEndpoint: https://idp.example.com/openid-connect/logout
redirectPostLogout: https://cafe.example.com
accessTokenEnable: true
```

Expand Down Expand Up @@ -475,6 +477,8 @@ The OIDC policy defines a few internal locations that can't be customized: `/_jw
|``authExtraArgs`` | A list of extra URL arguments to pass to the authorization endpoint provided by your OpenID Connect provider. Arguments must be URL encoded, multiple arguments may be included in the list, for example ``[ arg1=value1, arg2=value2 ]`` | ``string[]`` | No |
|``tokenEndpoint`` | URL for the token endpoint provided by your OpenID Connect provider. | ``string`` | Yes |
|``jwksURI`` | URL for the JSON Web Key Set (JWK) document provided by your OpenID Connect provider. | ``string`` | Yes |
|``logoutEndpoint`` | URL for the logout endpoint provided by your OpenID Connect provider. | ``string`` | Yes |
|``redirectPostLogout`` | URL to redirect after a successful logout. | ``string`` | Yes |
|``scope`` | List of OpenID Connect scopes. The scope ``openid`` always needs to be present and others can be added concatenating them with a ``+`` sign, for example ``openid+profile+email``, ``openid+email+userDefinedScope``. The default is ``openid``. | ``string`` | No |
|``redirectURI`` | Allows overriding the default redirect URI. The default is ``/_codexch``. | ``string`` | No |
|``zoneSyncLeeway`` | Specifies the maximum timeout in milliseconds for synchronizing ID/access tokens and shared values between Ingress Controller pods. The default is ``200``. | ``int`` | No |
Expand Down
15 changes: 10 additions & 5 deletions internal/configs/oidc/oidc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,21 @@
}

location = /logout {
# This location is called by UI to handle OIDC logout with IDP
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)
default_type text/plain;
return 200 "Logged out\n";
# This location is a default value of $oidc_logout_redirect called by the
# IDP after closing user ssion in the IDP.

# Clean cookies
add_header Set-Cookie "auth_nonce=; $oidc_cookie_flags"; # Send empty cookie
add_header Set-Cookie "auth_token=; $oidc_cookie_flags"; # Erase original cookie
add_header Set-Cookie "auth_redir=; $oidc_cookie_flags";

js_content oidc.redirectPostLogout;
}

location @oidc_error {
Expand Down
17 changes: 12 additions & 5 deletions internal/configs/oidc/openid_connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
var newSession = false; // Used by oidcAuth() and validateIdToken()

export default {auth, codeExchange, validateIdToken, logout};
export default {auth, codeExchange, validateIdToken, logout, redirectPostLogout};

function retryOriginalRequest(r) {
delete r.headersOut["WWW-Authenticate"]; // Remove evidence of original failed auth_jwt
Expand Down Expand Up @@ -265,10 +265,17 @@ function validateIdToken(r) {

function logout(r) {
r.log("OIDC logout for " + r.variables.cookie_auth_token);
r.variables.session_jwt = "-";
r.variables.access_token = "-";
r.variables.refresh_token = "-";
r.return(302, r.variables.oidc_logout_redirect);
var logoutArgs = "?post_logout_redirect_uri=" + r.variables.redirect_base + r.variables.oidc_logout_redirect + "&id_token_hint=" + r.variables.session_jwt;

r.variables.session_jwt = '-';
r.variables.access_token = '-';
r.variables.refresh_token = '-';
r.return(302, r.variables.oidc_logout_endpoint + logoutArgs);
}

// Redirect URL after logged-out from the IDP.
function redirectPostLogout(r) {
r.return(302, r.variables.redir_post_logout);
}

function getAuthZArgs(r) {
Expand Down
22 changes: 12 additions & 10 deletions internal/configs/version2/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,18 @@ type EgressMTLS struct {

// OIDC holds OIDC configuration data.
type OIDC struct {
AuthEndpoint string
ClientID string
ClientSecret string
JwksURI string
Scope string
TokenEndpoint string
RedirectURI string
ZoneSyncLeeway int
AuthExtraArgs string
AccessTokenEnable bool
AuthEndpoint string
LogoutEndpoint string
ClientID string
ClientSecret string
JwksURI string
Scope string
TokenEndpoint string
RedirectURI string
RedirectPostLogout string
ZoneSyncLeeway int
AuthExtraArgs string
AccessTokenEnable bool
}

// WAF defines WAF configuration.
Expand Down
2 changes: 2 additions & 0 deletions internal/configs/version2/nginx-plus.virtualserver.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,15 @@ server {
set $zone_sync_leeway {{ $oidc.ZoneSyncLeeway }};

set $oidc_authz_endpoint "{{ $oidc.AuthEndpoint }}";
set $oidc_logout_endpoint "{{ $oidc.LogoutEndpoint }}";
set $oidc_authz_extra_args "{{ $oidc.AuthExtraArgs }}";
set $oidc_token_endpoint "{{ $oidc.TokenEndpoint }}";
set $oidc_jwt_keyfile "{{ $oidc.JwksURI }}";
set $oidc_scopes "{{ $oidc.Scope }}";
set $oidc_client "{{ $oidc.ClientID }}";
set $oidc_client_secret "{{ $oidc.ClientSecret }}";
set $redir_location "{{ $oidc.RedirectURI }}";
set $redir_post_logout "{{ $oidc.RedirectPostLogout }}";
{{- end }}

{{- with $ssl := $s.SSL }}
Expand Down
22 changes: 12 additions & 10 deletions internal/configs/virtualserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1269,16 +1269,18 @@ func (p *policiesCfg) addOIDCConfig(
}

oidcPolCfg.oidc = &version2.OIDC{
AuthEndpoint: oidc.AuthEndpoint,
AuthExtraArgs: authExtraArgs,
TokenEndpoint: oidc.TokenEndpoint,
JwksURI: oidc.JWKSURI,
ClientID: oidc.ClientID,
ClientSecret: string(clientSecret),
Scope: scope,
RedirectURI: redirectURI,
ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200),
AccessTokenEnable: oidc.AccessTokenEnable,
AuthEndpoint: oidc.AuthEndpoint,
LogoutEndpoint: oidc.LogoutEndpoint,
AuthExtraArgs: authExtraArgs,
TokenEndpoint: oidc.TokenEndpoint,
JwksURI: oidc.JWKSURI,
ClientID: oidc.ClientID,
ClientSecret: string(clientSecret),
Scope: scope,
RedirectURI: redirectURI,
RedirectPostLogout: oidc.RedirectPostLogout,
ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200),
AccessTokenEnable: oidc.AccessTokenEnable,
}
oidcPolCfg.key = polKey
}
Expand Down
146 changes: 82 additions & 64 deletions internal/configs/virtualserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6228,15 +6228,17 @@ func TestGeneratePolicies(t *testing.T) {
},
Spec: conf_v1.PolicySpec{
OIDC: &conf_v1.OIDC{
AuthEndpoint: "http://example.com/auth",
TokenEndpoint: "http://example.com/token",
JWKSURI: "http://example.com/jwks",
ClientID: "client-id",
ClientSecret: "oidc-secret",
Scope: "scope",
RedirectURI: "/redirect",
ZoneSyncLeeway: createPointerFromInt(20),
AccessTokenEnable: true,
AuthEndpoint: "http://example.com/auth",
TokenEndpoint: "http://example.com/token",
JWKSURI: "http://example.com/jwks",
ClientID: "client-id",
ClientSecret: "oidc-secret",
Scope: "scope",
RedirectURI: "/redirect",
ZoneSyncLeeway: createPointerFromInt(20),
AccessTokenEnable: true,
LogoutEndpoint: "http://example.com/logout",
RedirectPostLogout: "http://example.com/",
},
},
},
Expand Down Expand Up @@ -7444,11 +7446,13 @@ func TestGeneratePoliciesFails(t *testing.T) {
},
Spec: conf_v1.PolicySpec{
OIDC: &conf_v1.OIDC{
ClientSecret: "oidc-secret",
AuthEndpoint: "http://foo.com/bar",
TokenEndpoint: "http://foo.com/bar",
JWKSURI: "http://foo.com/bar",
AccessTokenEnable: true,
ClientSecret: "oidc-secret",
AuthEndpoint: "http://foo.com/bar",
TokenEndpoint: "http://foo.com/bar",
JWKSURI: "http://foo.com/bar",
LogoutEndpoint: "http://foo.com/bar",
RedirectPostLogout: "http://foo.com/bar",
AccessTokenEnable: true,
},
},
},
Expand Down Expand Up @@ -7491,12 +7495,14 @@ func TestGeneratePoliciesFails(t *testing.T) {
},
Spec: conf_v1.PolicySpec{
OIDC: &conf_v1.OIDC{
ClientID: "foo",
ClientSecret: "oidc-secret",
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JWKSURI: "https://foo.com/certs",
AccessTokenEnable: true,
ClientID: "foo",
ClientSecret: "oidc-secret",
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JWKSURI: "https://foo.com/certs",
LogoutEndpoint: "https://foo.com/logout",
RedirectPostLogout: "https://foo.com/",
AccessTokenEnable: true,
},
},
},
Expand All @@ -7507,12 +7513,14 @@ func TestGeneratePoliciesFails(t *testing.T) {
},
Spec: conf_v1.PolicySpec{
OIDC: &conf_v1.OIDC{
ClientID: "foo",
ClientSecret: "oidc-secret",
AuthEndpoint: "https://bar.com/auth",
TokenEndpoint: "https://bar.com/token",
JWKSURI: "https://bar.com/certs",
AccessTokenEnable: true,
ClientID: "foo",
ClientSecret: "oidc-secret",
AuthEndpoint: "https://bar.com/auth",
TokenEndpoint: "https://bar.com/token",
JWKSURI: "https://bar.com/certs",
LogoutEndpoint: "https://bar.com/logout",
RedirectPostLogout: "https://bar.com/",
AccessTokenEnable: true,
},
},
},
Expand All @@ -7532,15 +7540,17 @@ func TestGeneratePoliciesFails(t *testing.T) {
context: "route",
oidcPolCfg: &oidcPolicyCfg{
oidc: &version2.OIDC{
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JwksURI: "https://foo.com/certs",
ClientID: "foo",
ClientSecret: "super_secret_123",
RedirectURI: "/_codexch",
Scope: "openid",
ZoneSyncLeeway: 0,
AccessTokenEnable: true,
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JwksURI: "https://foo.com/certs",
ClientID: "foo",
ClientSecret: "super_secret_123",
RedirectURI: "/_codexch",
Scope: "openid",
ZoneSyncLeeway: 0,
LogoutEndpoint: "https://foo.com/logout",
RedirectPostLogout: "https://foo.com/",
AccessTokenEnable: true,
},
key: "default/oidc-policy-1",
},
Expand All @@ -7556,14 +7566,16 @@ func TestGeneratePoliciesFails(t *testing.T) {
},
expectedOidc: &oidcPolicyCfg{
oidc: &version2.OIDC{
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JwksURI: "https://foo.com/certs",
ClientID: "foo",
ClientSecret: "super_secret_123",
RedirectURI: "/_codexch",
Scope: "openid",
AccessTokenEnable: true,
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JwksURI: "https://foo.com/certs",
ClientID: "foo",
ClientSecret: "super_secret_123",
RedirectURI: "/_codexch",
Scope: "openid",
LogoutEndpoint: "https://foo.com/logout",
RedirectPostLogout: "https://foo.com/",
AccessTokenEnable: true,
},
key: "default/oidc-policy-1",
},
Expand All @@ -7588,12 +7600,14 @@ func TestGeneratePoliciesFails(t *testing.T) {
},
Spec: conf_v1.PolicySpec{
OIDC: &conf_v1.OIDC{
ClientSecret: "oidc-secret",
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JWKSURI: "https://foo.com/certs",
ClientID: "foo",
AccessTokenEnable: true,
ClientSecret: "oidc-secret",
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JWKSURI: "https://foo.com/certs",
LogoutEndpoint: "https://foo.com/logout",
RedirectPostLogout: "https://foo.com/",
ClientID: "foo",
AccessTokenEnable: true,
},
},
},
Expand All @@ -7604,12 +7618,14 @@ func TestGeneratePoliciesFails(t *testing.T) {
},
Spec: conf_v1.PolicySpec{
OIDC: &conf_v1.OIDC{
ClientSecret: "oidc-secret",
AuthEndpoint: "https://bar.com/auth",
TokenEndpoint: "https://bar.com/token",
JWKSURI: "https://bar.com/certs",
ClientID: "bar",
AccessTokenEnable: true,
ClientSecret: "oidc-secret",
AuthEndpoint: "https://bar.com/auth",
TokenEndpoint: "https://bar.com/token",
JWKSURI: "https://bar.com/certs",
LogoutEndpoint: "https://bar.com/logout",
RedirectPostLogout: "https://bar.com/",
ClientID: "bar",
AccessTokenEnable: true,
},
},
},
Expand Down Expand Up @@ -7637,15 +7653,17 @@ func TestGeneratePoliciesFails(t *testing.T) {
},
expectedOidc: &oidcPolicyCfg{
&version2.OIDC{
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JwksURI: "https://foo.com/certs",
ClientID: "foo",
ClientSecret: "super_secret_123",
RedirectURI: "/_codexch",
Scope: "openid",
ZoneSyncLeeway: 200,
AccessTokenEnable: true,
AuthEndpoint: "https://foo.com/auth",
TokenEndpoint: "https://foo.com/token",
JwksURI: "https://foo.com/certs",
ClientID: "foo",
ClientSecret: "super_secret_123",
RedirectURI: "/_codexch",
Scope: "openid",
LogoutEndpoint: "https://foo.com/logout",
RedirectPostLogout: "https://foo.com/",
ZoneSyncLeeway: 200,
AccessTokenEnable: true,
},
"default/oidc-policy",
},
Expand Down
Loading