package oidc_provider import ( "context" "fmt" gooidc "github.com/coreos/go-oidc/v3/oidc" "golang.org/x/oauth2" ) // OidcFetchUserInfo returns a FetchUserInfo function that verifies an OIDC ID token. func OidcFetchUserInfo(verifier *gooidc.IDTokenVerifier) func(context.Context, *oauth2.Token, string) (*UserInfo, error) { return func(ctx context.Context, token *oauth2.Token, nonce string) (*UserInfo, error) { rawIDToken, ok := token.Extra("id_token").(string) if !ok || rawIDToken == "" { return nil, fmt.Errorf("no id_token in token response") } idToken, err := verifier.Verify(ctx, rawIDToken) if err != nil { return nil, fmt.Errorf("verifying ID token: %w", err) } if idToken.Nonce != nonce { return nil, fmt.Errorf("nonce mismatch") } var claims struct { Email string `json:"email"` EmailVerified bool `json:"email_verified"` } if err := idToken.Claims(&claims); err != nil { return nil, fmt.Errorf("extracting claims: %w", err) } // TODO pretty subtle check here for a specific claim that silently breaks login. if !claims.EmailVerified { return nil, fmt.Errorf("email not verified: %s", claims.Email) } return &UserInfo{ Subject: idToken.Subject, Email: claims.Email, EmailVerified: true, }, nil } }