Skip to content

[Feature]: Support OIDC step-up authentication via acr_values parameter #35

Description

@alexlovelltroy

Describe the feature

Enable clients to request specific authentication levels via the standard OIDC acr_values parameter for step-up authentication flows.

High-sensitivity operations (token revocation, admin actions) should require the user to re-authenticate with MFA, even if they have a valid session.

Why do you want this feature?

Current Behavior:

  • tokensmith does not provide a mechanism to request higher authentication levels
  • Clients cannot force MFA re-authentication for sensitive operations

Desired Behavior:

  1. Authorization Endpoint Enhancement:
// Support acr_values in /oauth/authorize
func (s *AuthService) Authorize(ctx context.Context, req AuthorizeRequest) (AuthorizeResponse, error) {
    // Extract requested ACR values
    requestedACRs := req.ACRValues  // e.g., ["urn:mfa:required", "AAL2"]
    
    // Check current session's ACR
    currentACR := req.Session.ACR
    
    if !meetsACRRequirement(currentACR, requestedACRs) {
        // Redirect to upstream IdP with acr_values parameter
        return redirectToIdP(req, acr_values=requestedACRs)
    }
    
    // ... continue authorization
}
  1. Token Validation for ACR Requirements:
// Middleware to enforce ACR requirements on endpoints
func RequireACR(minACR string) middleware {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            claims := extractClaims(r)
            
            if !meetsACRRequirement(claims.ACR, []string{minACR}) {
                // Return 403 with "insufficient_acr" error
                // Client should retry with acr_values parameter
                w.WriteHeader(403)
                json.NewEncoder(w).Encode(map[string]string{
                    "error": "insufficient_acr",
                    "error_description": fmt.Sprintf("This operation requires ACR >= %s", minACR),
                })
                return
            }
            
            next.ServeHTTP(w, r)
        })
    }
}

Example Usage:

// Protect token revocation with MFA requirement
router.DELETE("/oauth/token/{id}", RequireACR("urn:mfa:required"), RevokeToken)

Acceptance Criteria:

  • /oauth/authorize accepts and respects acr_values parameter
  • RequireACR middleware for endpoint protection
  • ACR comparison logic (hierarchical ACR values)
  • Error response insufficient_acr triggers client retry
  • Documentation with step-up auth flow examples

Alternatives you've considered

I considered doing...

Additional context

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions