Class OidcMiddleware

java.lang.Object
dev.relism.flash.ext.oidc.OidcMiddleware

public class OidcMiddleware extends Object
Request-level OIDC middleware. Exposed in the FlashContext for manual use on lambda routes; injected automatically for handlers annotated with Authenticated, RolesAllowed or ScopesAllowed.

Resolution order on each request:

  1. Authorization: Bearer ... header — validated via JWKS (JwtValidator).
  2. oidc_session cookie — looked up in OidcSessionStore; transparently refreshed if the access token is expired.
  3. Browser clients (no Accept: application/json) → redirect to {routePrefix}/login?redirect={path}.
  4. API clients → 401.

 // Manual use on a lambda route:
 OidcMiddleware oidc = app.ctx().require(OidcMiddleware.class);
 app.get("/api/me", (req, res) -> ClaimsHolder.claim("sub"), oidc.protect());
 app.delete("/admin/users/{id}", handler, oidc.requireRole("admin"));
 
  • Method Summary

    Modifier and Type
    Method
    Description
    dev.relism.flash.routing.Middleware
    authorize(dev.relism.flash.ext.oidc.OidcAuthPolicy policy)
    Compiled authorization policy path used by annotation-driven mounting.
    OIDC issuer this middleware validates tokens against — the iss claim it enforces.
    dev.relism.flash.routing.Middleware
    Silently populates ClaimsHolder if a valid bearer token or session cookie is present, but never rejects or redirects unauthenticated requests.
    dev.relism.flash.routing.Middleware
    Validates the bearer token or session cookie.
    dev.relism.flash.routing.Middleware
    protect(String resourceMetadataPath)
    Like protect(), but a 401 challenge also carries resource_metadata (RFC 9728 §5.1), resolved against this request's own scheme/host exactly like OidcExtension's redirect URIs.
    dev.relism.flash.routing.Middleware
    Requires at least one of the listed scopes to be present in the token.
    dev.relism.flash.routing.Middleware
    requireRole(String... roles)
    Like protect() but also enforces that the caller holds at least one of the given roles (OR semantics).
    dev.relism.flash.routing.Middleware
    requireScopes(String... scopes)
    Requires all listed scopes to be present in the token.
    The single configured claim path used by every transport for role checks.
    static String
    selfOrigin(dev.relism.flash.models.Request req, String fallbackScheme)
    scheme://host clients actually reach this app on — the basis for every absolute URL it publishes about itself (OAuth2 redirect_uri, the RFC 9728 resource identifier and the resource_metadata challenge).
    Scheme used to build this app's own absolute URLs — see OidcConfig.selfScheme().

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • rolesClaimPath

      public String rolesClaimPath()
      The single configured claim path used by every transport for role checks.
    • protect

      public dev.relism.flash.routing.Middleware protect()
      Validates the bearer token or session cookie. Browser clients are redirected to the login page on failure; API clients receive 401.
    • protect

      public dev.relism.flash.routing.Middleware protect(String resourceMetadataPath)
      Like protect(), but a 401 challenge also carries resource_metadata (RFC 9728 §5.1), resolved against this request's own scheme/host exactly like OidcExtension's redirect URIs. resourceMetadataPath is an absolute path (e.g. "/.well-known/oauth-protected-resource/mcp"); pass null for plain challenges. Used by flash-ext-mcp to make its Protected Resource Metadata document discoverable straight from the WWW-Authenticate header, per the MCP Authorization spec.
    • issuer

      public String issuer()
      OIDC issuer this middleware validates tokens against — the iss claim it enforces.
    • selfScheme

      public String selfScheme()
      Scheme used to build this app's own absolute URLs — see OidcConfig.selfScheme().
    • optional

      public dev.relism.flash.routing.Middleware optional()
      Silently populates ClaimsHolder if a valid bearer token or session cookie is present, but never rejects or redirects unauthenticated requests. Use this on public routes that want to personalise the response when the user happens to be logged in (e.g. showing a username on a landing page).
      
       app.get("/", handler, oidc.optional());
       // Inside handler: ClaimsHolder.user() is non-null iff the user is logged in.
       
    • authorize

      public dev.relism.flash.routing.Middleware authorize(dev.relism.flash.ext.oidc.OidcAuthPolicy policy)
      Compiled authorization policy path used by annotation-driven mounting. The policy is immutable and built once at boot.
    • requireRole

      public dev.relism.flash.routing.Middleware requireRole(String... roles)
      Like protect() but also enforces that the caller holds at least one of the given roles (OR semantics). Roles are extracted via OidcConfig.rolesClaimPath().
    • requireScopes

      public dev.relism.flash.routing.Middleware requireScopes(String... scopes)
      Requires all listed scopes to be present in the token. Scopes are resolved from configured claim paths (default: scope,scp).
    • requireAnyScope

      public dev.relism.flash.routing.Middleware requireAnyScope(String... scopes)
      Requires at least one of the listed scopes to be present in the token. Scopes are resolved from configured claim paths (default: scope,scp).
    • selfOrigin

      public static String selfOrigin(dev.relism.flash.models.Request req, String fallbackScheme)
      scheme://host clients actually reach this app on — the basis for every absolute URL it publishes about itself (OAuth2 redirect_uri, the RFC 9728 resource identifier and the resource_metadata challenge). Behind a reverse proxy the request's own Host is the upstream address the proxy dialled, so X-Forwarded-Host/-Proto win whenever present: without them the app would name an address no client can resolve, and OAuth2 discovery fails with no error anyone can trace back to here. Trusted unconditionally — a caller able to reach this app without passing the proxy can do worse than spoof a self URL.