Skip to main content

Header / Gateway Authentication

Framework M supports header-based authentication for enterprise deployments where an upstream API gateway (such as Nginx, Traefik, Envoy, Kong, or an OIDC-aware proxy) authenticates the request and forwards identity metadata via HTTP headers.

This approach is standards-aligned, stateless, and avoids proprietary IAM protocols. It is commonly used together with an external identity provider (e.g. Keycloak, Auth0, Okta) that issues tokens and with a gateway that validates those tokens and sets identity headers.


Authentication Strategy

The HeaderAuth strategy hydrates UserContext from trusted headers. It does not perform any network calls; the upstream gateway is responsible for token validation and tenant resolution.

Expected Headers

HeaderDescription
x-user-idUser's primary identity.
x-service-idService identity (used when no user is present).
x-emailUser's email address.
x-user-rolesComma-separated list of roles.
x-scopesComma-separated list of service scopes.
x-tenant-idVerified primary tenant ID(s).
x-active-tenant-idSelector/Hint passed by the user to request a specific tenant context.
x-user-attributesBase64-encoded JSON string containing user metadata.
x-tenant-attributesBase64-encoded JSON string containing tenant-level metadata.

Configuration

Header auth is enabled by including it in the authentication chain.

Global Configuration (framework_config.toml)

[auth]
strategies = ["jwt", "header"]

Reverse Proxy / Gateway Example

A typical Nginx configuration that validates a JWT and forwards identity headers:

location /api/ {
auth_jwt "Framework M API";
auth_jwt_key_file /etc/nginx/jwks.json;

proxy_set_header X-User-ID $jwt_claim_sub;
proxy_set_header X-Email $jwt_claim_email;
proxy_set_header X-User-Roles $jwt_claim_roles;
proxy_set_header X-Tenant-ID $jwt_claim_tenant_id;

proxy_pass http://framework-m-backend:8888;
}

Token Introspection Example

When the gateway cannot validate tokens locally, Framework M can introspect opaque Bearer tokens remotely and optionally call the OIDC UserInfo endpoint if the introspection response only contains active: true/false.

[auth]
strategies = ["jwt", "remote_introspection", "header"]

[auth.remote_introspection]
enabled = true
endpoint = "https://idp.example.com/oauth/introspect"
# Optional: fetch claims from UserInfo when introspection is sparse
userinfo_endpoint = "https://idp.example.com/oauth/userinfo"
client_id = "framework-m"
client_secret = "..."
timeout_seconds = 2.0

Usage in Code

Authentication Chain

The header strategy is automatically included in the authentication chain when configured.

from framework_m_standard.adapters.auth.strategies import create_auth_chain_from_config

# Factory creates the chain including HeaderAuth if set in config
auth_chain = create_auth_chain_from_config(jwt_secret="...")

# Middleware uses it to hydrate request.state.user
user_context = await auth_chain.authenticate(request.headers)

Context Mapping

The adapter maps headers to the UserContext as follows:

  • Identity: id is taken from x-user-id (if present) or x-service-id.
  • Tenants: tenants is a list starting with x-active-tenant-id, followed by any additional IDs in x-tenant-id.
  • Attributes:
    • x-user-attributes are decoded and merged directly into the root of UserContext.attributes.
    • x-tenant-attributes are decoded and placed under the tenant_attributes key in UserContext.attributes.
  • Metadata: is_service and scopes are added to attributes if a service identity is used.