Files
rustfs/docs/operations/oidc-provider-requirements.md
T

8.2 KiB

OIDC provider requirements

Use this when: evaluating whether an identity provider (or a vendor's "OIDC-like" OAuth product) can back RustFS console SSO, or debugging why a provider fails discovery, login, or policy mapping. Source of truth: crates/iam/src/oidc/config.rs (OidcProviderConfig), crates/iam/src/oidc/provider.rs (discover_provider), crates/iam/src/oidc/runtime.rs (trusted_aud, map_claims_to_policies); crates/config/src/constants/oidc.rs (OIDC_DEFAULT_*, ENV_IDENTITY_OPENID_*); rustfs/src/admin/handlers/oidc.rs (derive_callback_uri_with_provider_config, browser_redirect_url).

RustFS is a standard OpenID Connect relying party using the authorization-code flow with PKCE. It reads every claim it uses from the ID token; it never calls the UserInfo endpoint. Provider-side setup steps for Keycloak and Authing, and the RustFS-side configuration keys, are in oidc-console-integration.md.

Requirements

The table below describes Console login. For endpoint-free STS issuers, use the workload contract below.

# Requirement Details Code anchor
1 Discovery document RUSTFS_IDENTITY_OPENID_CONFIG_URL names the provider (issuer base or full discovery URL); RustFS fetches {issuer}/.well-known/openid-configuration and needs issuer, authorization_endpoint, token_endpoint, jwks_uri, and the standard *_supported arrays. When RUSTFS_IDENTITY_OPENID_ISSUER is set, the document's issuer must equal it exactly; otherwise RustFS tries the issuer candidates derived from the config URL. crates/iam/src/oidc/provider.rs discover_provider, discover_provider_from_config_url
2 Outbound reachability Discovery, JWKS, and token requests go through the shared egress policy. A provider on a private or loopback address needs its exact origin in RUSTFS_OUTBOUND_ALLOW_ORIGINS; otherwise startup logs OIDC provider discovery blocked by outbound policy. crates/iam/src/oidc/provider.rs OIDC_DISCOVERY_BLOCKED_BY_OUTBOUND_POLICY; Outbound connection policy
3 Signed ID token, verifiable via JWKS The ID token signature is verified against jwks_uri; the key set is refreshed after OIDC_JWKS_REFRESH_INTERVAL and once more on a verification failure. A token response without id_token fails login — an OAuth-only access token is not sufficient. crates/iam/src/oidc/provider.rs OIDC_JWKS_REFRESH_INTERVAL; crates/iam/src/oidc/runtime.rs no id_token in token response
4 Authorization-code flow with PKCE (S256) The authorization request carries response_type=code, scope, redirect_uri, state, nonce, code_challenge, code_challenge_method=S256; the token request carries the code_verifier. Providers that ignore or reject PKCE, state, or nonce are not supported. crates/iam/src/oidc/runtime.rs PkceCodeChallenge::new_random_sha256; crates/iam/src/oidc/state.rs pkce_verifier
5 Scopes Default openid,profile,email (OIDC_DEFAULT_SCOPES); override with RUSTFS_IDENTITY_OPENID_SCOPES (comma-separated). The provider must accept every configured scope. crates/config/src/constants/oidc.rs OIDC_DEFAULT_SCOPES; crates/iam/src/oidc/config.rs OidcProviderConfig::scopes
6 Callback returns state The callback must carry both code and the original state; state locates the in-flight session that holds the nonce and PKCE verifier. A callback with only code fails. rustfs/src/admin/handlers/oidc.rs OIDC_CALLBACK_SUFFIX; crates/iam/src/oidc/state.rs
7 ID token claims iss, aud, exp, and nonce are verified; sub identifies the user. aud must contain the client id or one of RUSTFS_IDENTITY_OPENID_OTHER_AUDIENCES. crates/iam/src/oidc/runtime.rs trusted_aud, OidcClaims
8 Authorization claims in the ID token Policy mapping reads the claim named by RUSTFS_IDENTITY_OPENID_CLAIM_NAME (default groups, OIDC_DEFAULT_CLAIM_NAME) together with RUSTFS_IDENTITY_OPENID_GROUPS_CLAIM and the optional RUSTFS_IDENTITY_OPENID_ROLES_CLAIM, as a string or array of strings, optionally prefixed by RUSTFS_IDENTITY_OPENID_CLAIM_PREFIX. Values must equal RustFS policy names (for example consoleAdmin, readwrite, readonly) made only of [A-Za-z0-9_:.-]. Groups-claim and roles-claim values with no policy of that name, such as the Active Directory group DOMAIN\Domain Users or Keycloak's offline_access role, are ignored once storage confirms that no such policy exists. Login is rejected when a policy lookup fails, when no value resolves, when a value names an existing policy whose name is outside that character set (dropping it could remove a Deny), or when a name from RUSTFS_IDENTITY_OPENID_ROLE_POLICY, a separate RUSTFS_IDENTITY_OPENID_CLAIM_NAME claim, or an explicit IAM policy mapping does not exist. Email and username come from RUSTFS_IDENTITY_OPENID_EMAIL_CLAIM (default email) and RUSTFS_IDENTITY_OPENID_USERNAME_CLAIM (default preferred_username). A provider that returns only a user id can authenticate but cannot express RustFS authorization. crates/iam/src/oidc/runtime.rs map_claims_to_policies, extract_canonical_group_values, OidcSys::group_claim_policy_names; rustfs/src/admin/service/federated_identity.rs select_oidc_policies
9 Registered redirect URI The provider must accept the callback {public-origin}/rustfs/admin/v3/oidc/callback/{provider_id}. RustFS picks the origin in this order: the provider's redirect_uri (RUSTFS_IDENTITY_OPENID_REDIRECT_URI), then RUSTFS_BROWSER_REDIRECT_URL, then the request's own scheme and host — the last only when RUSTFS_IDENTITY_OPENID_REDIRECT_URI_DYNAMIC is enabled. rustfs/src/admin/handlers/oidc.rs derive_callback_uri_with_provider_config, browser_redirect_url
10 Logout endpoint (optional) When discovery advertises end_session_endpoint, RustFS builds an RP-initiated logout URL with id_token_hint, client_id, and post_logout_redirect_uri. Without it, logout falls back to the console login page. crates/iam/src/oidc/runtime.rs build_logout_url (reads end_session_endpoint from ProviderMetadataWithLogout)

STS workload providers

For workload identity tokens exchanged through AssumeRoleWithWebIdentity (for example Kubernetes service-account tokens), set RUSTFS_IDENTITY_OPENID_HIDE_FROM_UI=on (hide_from_ui=on in persisted configuration, or hide_from_ui: true in the admin JSON API) when discovery omits authorization_endpoint. The default is off; without this setting, RustFS applies the Console discovery contract and rejects the missing endpoint.

Endpoint-free workload discovery requires issuer, jwks_uri, and id_token_signing_alg_values_supported. token_endpoint is optional; browser authorization endpoints, response_types_supported, and subject_types_supported are not required for this path. An explicitly null, empty, or malformed authorization_endpoint is rejected rather than treated as absent. Configuration validation returns authorization_endpoint: null for an accepted workload-only provider.

Set RUSTFS_IDENTITY_OPENID_CONFIG_URL to the issuer/discovery URL and RUSTFS_IDENTITY_OPENID_CLIENT_ID to the intended token audience. Configure policy claims or RUSTFS_IDENTITY_OPENID_ROLE_POLICY to grant the required RustFS permissions. Signature, issuer, audience, and expiration verification remain enforced, and private endpoints still require the outbound allowlist. JWKS requests accept both application/json and application/jwk-set+json.

Workload-only providers cannot perform Console authorization-code login. Hiding a provider with complete discovery metadata only hides its listing; its existing direct Console login remains available.

Deployment notes

  • Behind a load balancer, authorize and callback requests must reach the same RustFS node while the state is in flight, or set RUSTFS_BROWSER_REDIRECT_URL so the callback URL is stable; the callback error text names both remedies.
  • Provider-specific setup (client registration, claim mappers, redirect-URL priority) is covered by the console integration guide for the provider in use; this page states only what any provider must offer.