{"record":{"id":"063be47cbfb04665","repo":"oauth2-proxy/oauth2-proxy","slug":"unable-to-enrich-session-v","errorCode":null,"errorMessage":"unable to enrich session: %v","messagePattern":"unable to enrich session: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"providers/ms_entra_id.go","lineNumber":64,"sourceCode":"// NewMicrosoftEntraIDProvider initiates a new MicrosoftEntraIDProvider\nfunc NewMicrosoftEntraIDProvider(p *ProviderData, opts options.Provider) *MicrosoftEntraIDProvider {\n\tp.setProviderDefaults(providerDefaults{\n\t\tname: microsoftEntraIDProviderName,\n\t})\n\n\treturn &MicrosoftEntraIDProvider{\n\t\tOIDCProvider: NewOIDCProvider(p, opts.OIDCConfig),\n\n\t\tmultiTenantAllowedTenants: opts.MicrosoftEntraIDConfig.AllowedTenants,\n\t\tfederatedTokenAuth:        ptr.Deref(opts.MicrosoftEntraIDConfig.FederatedTokenAuth, options.DefaultMicrosoftEntraIDUseFederatedToken),\n\t\tmicrosoftGraphURL:         microsoftGraphURL,\n\t}\n}\n\n// EnrichSession checks for group overage after calling generic EnrichSession\nfunc (p *MicrosoftEntraIDProvider) EnrichSession(ctx context.Context, session *sessions.SessionState) error {\n\tif err := p.OIDCProvider.EnrichSession(ctx, session); err != nil {\n\t\treturn fmt.Errorf(\"unable to enrich session: %v\", err)\n\t}\n\n\thasGroupOverage, err := p.checkGroupOverage(session)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to check token: %v\", err)\n\t}\n\n\tif hasGroupOverage {\n\t\tlogger.Printf(\"entra overage found, reading groups from Graph API\")\n\t\tif err = p.addGraphGroupsToSession(ctx, session); err != nil {\n\t\t\treturn fmt.Errorf(\"unable to enrich session: %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// ValidateSession checks for allowed tenants (e.g. for multi-tenant apps) and passes through to generic ValidateSession","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/oauth2-proxy/oauth2-proxy/blob/33c2eb92dea78204f7a18bc2dfdbccc220f39257/providers/ms_entra_id.go#L46-L82","documentation":"MicrosoftEntraIDProvider.EnrichSession first delegates to the generic OIDC provider's EnrichSession (which fetches claims/groups from the ID token and provider endpoints). If that underlying enrichment fails for any reason, the error is wrapped as 'unable to enrich session: %v' and returned, so the Azure-specific group-overage handling never runs.","triggerScenarios":"EnrichSession called on a session where the generic OIDC enrichment fails — invalid/expired access token when fetching userinfo, unreachable issuer, or any error surfaced by p.OIDCProvider.EnrichSession.","commonSituations":"Access token expired or revoked before enrichment; Keycloak/Entra issuer temporarily down; misconfigured provider URL causing the generic enrichment HTTP calls to fail; running the known test TestAzureEntraOIDCProviderEnrichSessionGroupOverage against a mock that omits required claims.","solutions":["Inspect the wrapped inner error (printed after 'unable to enrich session:') — it names the actual failure (HTTP status, token problem, etc.).","Verify the session's AccessToken/IDToken are valid and not expired at enrichment time.","Confirm the OIDC provider issuer/discovery URLs are reachable from the process.","Refresh the session tokens before calling EnrichSession if they are near expiry."],"exampleFix":"// before\ns, _ := provider.EnrichSession(ctx, staleSession) // token expired hours ago\n// after\nif ok, _ := provider.RefreshSession(ctx, staleSession); ok {\n    err := provider.EnrichSession(ctx, staleSession)\n}","handlingStrategy":"try-catch","validationCode":"// check token validity before enrichment\nif session.AccessToken == \"\" || isTokenExpired(session.AccessToken) {\n    if ok, _ := provider.RefreshSession(ctx, session); !ok {\n        return errors.New(\"cannot enrich: no valid access token\")\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := provider.EnrichSession(ctx, session); err != nil {\n    var inner error\n    if errors.Unwrap(err) != nil { inner = errors.Unwrap(err) }\n    log.Printf(\"entra enrichment failed: %v (cause: %v)\", err, inner)\n    return err\n}","preventionTips":["Refresh tokens proactively before enrichment when nearing expiry.","Monitor issuer/Keycloak availability; the generic OIDC enrichment makes network calls.","Always log the wrapped inner error, not just the outer message."],"tags":["entra-id","azure","oidc","session","enrichment"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"33c2eb92dea78204f7a18bc2dfdbccc220f39257","analyzedAt":"2026-09-06T08:51:53.077Z","contentChangedAt":"2026-09-06T08:51:53.077Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}