oauth2-proxy/oauth2-proxy · error

unable to enrich session: %v

Error message

unable to enrich session: %v

What it means

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.

Source

Thrown at providers/ms_entra_id.go:64

// NewMicrosoftEntraIDProvider initiates a new MicrosoftEntraIDProvider
func NewMicrosoftEntraIDProvider(p *ProviderData, opts options.Provider) *MicrosoftEntraIDProvider {
	p.setProviderDefaults(providerDefaults{
		name: microsoftEntraIDProviderName,
	})

	return &MicrosoftEntraIDProvider{
		OIDCProvider: NewOIDCProvider(p, opts.OIDCConfig),

		multiTenantAllowedTenants: opts.MicrosoftEntraIDConfig.AllowedTenants,
		federatedTokenAuth:        ptr.Deref(opts.MicrosoftEntraIDConfig.FederatedTokenAuth, options.DefaultMicrosoftEntraIDUseFederatedToken),
		microsoftGraphURL:         microsoftGraphURL,
	}
}

// EnrichSession checks for group overage after calling generic EnrichSession
func (p *MicrosoftEntraIDProvider) EnrichSession(ctx context.Context, session *sessions.SessionState) error {
	if err := p.OIDCProvider.EnrichSession(ctx, session); err != nil {
		return fmt.Errorf("unable to enrich session: %v", err)
	}

	hasGroupOverage, err := p.checkGroupOverage(session)
	if err != nil {
		return fmt.Errorf("unable to check token: %v", err)
	}

	if hasGroupOverage {
		logger.Printf("entra overage found, reading groups from Graph API")
		if err = p.addGraphGroupsToSession(ctx, session); err != nil {
			return fmt.Errorf("unable to enrich session: %v", err)
		}
	}

	return nil
}

// ValidateSession checks for allowed tenants (e.g. for multi-tenant apps) and passes through to generic ValidateSession

View on GitHub (pinned to 33c2eb92de)

Solutions

  1. Inspect the wrapped inner error (printed after 'unable to enrich session:') — it names the actual failure (HTTP status, token problem, etc.).
  2. Verify the session's AccessToken/IDToken are valid and not expired at enrichment time.
  3. Confirm the OIDC provider issuer/discovery URLs are reachable from the process.
  4. Refresh the session tokens before calling EnrichSession if they are near expiry.

Example fix

// before
s, _ := provider.EnrichSession(ctx, staleSession) // token expired hours ago
// after
if ok, _ := provider.RefreshSession(ctx, staleSession); ok {
    err := provider.EnrichSession(ctx, staleSession)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check token validity before enrichment
if session.AccessToken == "" || isTokenExpired(session.AccessToken) {
    if ok, _ := provider.RefreshSession(ctx, session); !ok {
        return errors.New("cannot enrich: no valid access token")
    }
}

Try / catch

if err := provider.EnrichSession(ctx, session); err != nil {
    var inner error
    if errors.Unwrap(err) != nil { inner = errors.Unwrap(err) }
    log.Printf("entra enrichment failed: %v (cause: %v)", err, inner)
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of oauth2-proxy/oauth2-proxy@33c2eb92de (2026-09-06). Data as JSON: /api/errors/063be47cbfb04665. Report an issue: GitHub.