diff --git a/internal/server/authn/method/oidc/server.go b/internal/server/authn/method/oidc/server.go index 4dd87e70e1..47584a2162 100644 --- a/internal/server/authn/method/oidc/server.go +++ b/internal/server/authn/method/oidc/server.go @@ -30,6 +30,9 @@ const ( storageMetadataOIDCPicture = "io.flipt.auth.oidc.picture" storageMetadataOIDCSub = "io.flipt.auth.oidc.sub" storageMetadataOIDCPreferredUsername = "io.flipt.auth.oidc.preferred_username" + storageMetadataOIDCIssuer = "io.flipt.auth.oidc.issuer" + storageMetadataOIDCClientID = "io.flipt.auth.oidc.client_id" + storageMetadataOIDCIDToken = "io.flipt.auth.oidc.id_token" oauthChallengeTTL = 2 * time.Minute nonceStatic = "static" ) @@ -174,6 +177,9 @@ func (s *Server) Callback(ctx context.Context, req *auth.CallbackRequest) (_ *au metadata := map[string]string{ storageMetadataOIDCProvider: req.Provider, + storageMetadataOIDCIssuer: providerCfg.IssuerURL, + storageMetadataOIDCClientID: providerCfg.ClientID, + storageMetadataOIDCIDToken: string(responseToken.IDToken()), } rawClaims := make(map[string]any) diff --git a/internal/server/authn/method/oidc/server_test.go b/internal/server/authn/method/oidc/server_test.go index 0a7b1fafc5..041ec136e1 100644 --- a/internal/server/authn/method/oidc/server_test.go +++ b/internal/server/authn/method/oidc/server_test.go @@ -549,9 +549,14 @@ func testOIDCFlow(t *testing.T, ctx context.Context, tpAddr, clientAddress strin claims := response.Authentication.Metadata["io.flipt.auth.claims"] delete(response.Authentication.Metadata, "io.flipt.auth.claims") + idToken := response.Authentication.Metadata["io.flipt.auth.oidc.id_token"] + delete(response.Authentication.Metadata, "io.flipt.auth.oidc.id_token") + assert.Equal(t, map[string]string{ "io.flipt.auth.oidc.provider": "google", - "io.flipt.auth.oidc.email": "mark@flipt.io", + "io.flipt.auth.oidc.issuer": tpAddr, + "io.flipt.auth.oidc.client_id": "client_id", + "io.flipt.auth.oidc.email": "mark@flipt.io", "io.flipt.auth.email": "mark@flipt.io", "io.flipt.auth.oidc.name": "Mark Phelps", "io.flipt.auth.name": "Mark Phelps", @@ -559,6 +564,7 @@ func testOIDCFlow(t *testing.T, ctx context.Context, tpAddr, clientAddress strin }, response.Authentication.Metadata) assert.NotEmpty(t, claims) + assert.NotEmpty(t, idToken) if expectedUserInfoClaims != nil { var claimSet map[string]any require.NoError(t, json.Unmarshal([]byte(claims), &claimSet)) diff --git a/ui/src/components/NavUser.tsx b/ui/src/components/NavUser.tsx index e8d3eb9b8a..63fb3e1a5c 100644 --- a/ui/src/components/NavUser.tsx +++ b/ui/src/components/NavUser.tsx @@ -34,7 +34,21 @@ export function NavUser({ user }: { user: User }) { await expireAuthSelf(); clearSession(); if (user?.issuer) { - window.location.href = `//${user.issuer}`; + const logoutUrl = new URL( + 'protocol/openid-connect/logout', + user.issuer.endsWith('/') ? user.issuer : user.issuer + '/' + ); + if (user?.idToken) { + logoutUrl.searchParams.set('id_token_hint', user.idToken); + } + if (user?.clientId) { + logoutUrl.searchParams.set('client_id', user.clientId); + } + logoutUrl.searchParams.set( + 'post_logout_redirect_uri', + window.location.origin + ); + window.location.href = logoutUrl.toString(); } else { navigate('/login'); } diff --git a/ui/src/data/user.ts b/ui/src/data/user.ts index c043c3bfc5..61a2e4fd8b 100644 --- a/ui/src/data/user.ts +++ b/ui/src/data/user.ts @@ -31,6 +31,14 @@ export function getUser(session?: Session): User | undefined { if (metadata[authMethodIssuerKey as keyof typeof metadata]) { u.issuer = metadata[authMethodIssuerKey as keyof typeof metadata]; } + const authMethodClientIdKey = `io.flipt.auth.${authMethod}.client_id`; + if (metadata[authMethodClientIdKey as keyof typeof metadata]) { + u.clientId = metadata[authMethodClientIdKey as keyof typeof metadata]; + } + const authMethodIdTokenKey = `io.flipt.auth.${authMethod}.id_token`; + if (metadata[authMethodIdTokenKey as keyof typeof metadata]) { + u.idToken = metadata[authMethodIdTokenKey as keyof typeof metadata]; + } } return u; } diff --git a/ui/src/types/auth/OIDC.ts b/ui/src/types/auth/OIDC.ts index ecd7c283d9..ddd932b49c 100644 --- a/ui/src/types/auth/OIDC.ts +++ b/ui/src/types/auth/OIDC.ts @@ -13,6 +13,9 @@ export interface IAuthMethodOIDC extends IAuthMethod { export interface IAuthMethodOIDCMetadata { 'io.flipt.auth.oidc.provider': string; + 'io.flipt.auth.oidc.issuer'?: string; + 'io.flipt.auth.oidc.client_id'?: string; + 'io.flipt.auth.oidc.id_token'?: string; 'io.flipt.auth.oidc.email'?: string; 'io.flipt.auth.oidc.email_verified'?: string; 'io.flipt.auth.oidc.name'?: string; diff --git a/ui/src/types/auth/User.ts b/ui/src/types/auth/User.ts index 1800df79f8..90494641ce 100644 --- a/ui/src/types/auth/User.ts +++ b/ui/src/types/auth/User.ts @@ -3,5 +3,7 @@ export type User = { login: string | undefined; imgURL: string | undefined; issuer: string | undefined; + clientId: string | undefined; + idToken: string | undefined; authMethod: string | undefined; };