Skip to content

Identity configuration

Paths in the tables are relative to [oidc] or [identity]. Check parsing and cross-field rules with gdsgate doctor --config <PATH> --json. Follow the OIDC setup and troubleshooting guide for provider registration, profile distribution, device/browser login and claim-to-policy examples.

[oidc]

Authority owns the intended public OIDC profile. Authorized Proxy join saves it with the role configuration; the Proxy advertises its effective profile to gdsgate connect, and the client writes it to its configuration. Existing Proxy and client files need an explicit update when that profile changes; see profile lifecycle. Standalone clients can maintain the profile locally. Group permissions are always evaluated by Authority. An explicit Proxy issuer or client ID conflicting with its authorized saved binding refuses startup. Extended profiles require current Proxy and client builds: older builds refuse the new bootstrap layout and require an upgrade.

Used by: Authority, Proxy, Client.

External OIDC identity provider. With issuer and client_id set, Authority verifies identity tokens against the provider's signing keys (JWKS), and gdsgate login runs the device flow against it. Unset: the built-in development issuer is used (HS256; the client creates a local token). For development only.

Set issuer and client_id together. Missing or blank values, an audience without a provider, and malformed issuer URLs are errors in every profile. Issuer URLs must use HTTPS and contain no credentials, query or fragment. An explicit allow_insecure_http = true permits HTTP for a loopback development provider. config check and doctor report invalid settings without contacting the provider.

Discovery, issuer mismatch, token validation and identity-file failures stop the operation. They do not switch to a development identity. A connect bundle advertising an incomplete provider is refused before the client config or its trust anchor is written.

Key Type Default Purpose
issuer string unset Issuer base URL, for example https://idp.example.com/realms/gdsgate. Discovery is fetched from <issuer>/.well-known/openid-configuration. Config and discovery issuers are cross-checked; the token's iss must match the advertised validation issuer.
client_id string unset OAuth client id registered for gdsgate at the identity provider.
audience string client_id Expected aud claim.
id_token_signing_algs array of string all supported asymmetric algorithms (RS256/384/512, PS256/384/512, ES256, ES384, EdDSA) Allowed id_token signing algorithms. Checked against the provider's id_token_signing_alg_values_supported at discovery and against the token header alg at validation. HS* is always refused.
display_name_claims array of string ["preferred_username", "email"] Claim names or JSON pointers to take a display name from, in order; the first string claim present is used. Authority stores the name with the subject at each sign-in. authority audit list shows the name in place of the subject (--json shows both) and accepts it in --actor. The audit chain stores only the subject. authority users forget-name removes a name. [] stores no names.
jwks_refresh_secs u64 3600 Interval at which Authority re-fetches the JWKS; provider key rotation needs no restart. A token with an unknown key also triggers a fetch. 0 disables the periodic refresh.
request_timeout_secs u64 15 Timeout for each HTTP call to the provider (discovery, JWKS, device code, token exchange), covering connect and read.
allow_insecure_http bool false Allow http:// provider URLs. For a loopback development provider only; each http:// call is logged at WARN.
scopes array of string [] Empty uses discovery defaults: openid and, when advertised or discovery omits its scope list, offline_access. An explicit list must include openid and is used exactly as written; it is never silently narrowed after a refusal.
resource string unset Public OAuth resource identifier, sent at authorization, device authorization, token exchange and refresh.
browser.callback_port u16 0 Port for http://127.0.0.1:<port>/callback; 0 selects an ephemeral port. Register the exact fixed callback at the provider when required. An occupied fixed port fails the login.
device.interval u64 unset Local polling minimum, 1–3600 seconds. The greater of this value and the provider interval is used; slow_down adds five seconds each time.
device.expires_in u64 unset Local maximum wait, 1–86400 seconds. The shorter of this bound and the provider lifetime is used. Without either lifetime, polling stops after 60 attempts.
device.pending_errors array of tables [] Optional compatibility rules matching both error = "invalid_grant" and a nonempty, case-sensitive description_prefix. They apply only to device polling and remain bounded by expiry. Default RFC handling treats invalid_grant as terminal.
claims.groups.path string "groups" Exact top-level claim name or JSON pointer, such as /membership/roles, read only from the verified id_token.
claims.groups.format string "array" array: array of strings; string: one group; delimited: string split by the explicit delimiter. Other types refuse the token.
claims.groups.delimiter string unset Required only for delimited; 1–16 bytes. No trimming or case conversion is performed. Empty group elements are refused.
claims.groups.required bool false Refuse a token when the group claim is absent. When false, an absent claim yields no groups; a malformed present claim still fails.
claims.email string "email" Exact claim name or JSON pointer for email. Empty disables extraction. A present non-string value is refused.
claims.preferred_username string "preferred_username" Exact claim name or JSON pointer for username. Empty disables extraction. The security identity remains the verified iss and sub.
parameters.authorization table of strings {} Extra public parameters on the browser authorization URL, for example prompt or acr_values.
parameters.device_authorization table of strings {} Extra public form parameters on the device authorization request.
parameters.token table of strings {} Extra public form parameters on authorization-code and device-code exchange.
parameters.refresh table of strings {} Extra public form parameters on refresh only; no automatic scope narrowing.
[oidc]
issuer    = "https://idp.example.com/realms/gdsgate"
client_id = "gdsgate"
# audience defaults to client_id
# restrict to the algorithms your provider uses:
id_token_signing_algs = ["RS256"]

An extended profile can select a resource and the claims it issues:

[oidc]
issuer = "https://idp.example.com"
client_id = "gdsgate"
scopes = ["openid", "profile"]
resource = "urn:gdsgate:people"
display_name_claims = ["/person/name", "upn", "email"]

[oidc.browser]
callback_port = 8400

[oidc.claims]
email = "/person/mail"
preferred_username = "upn"

[oidc.claims.groups]
path = "/membership/roles"
format = "array"
required = true

[oidc.parameters.authorization]
prompt = "login"

Additional parameters are public: they are distributed in bootstrap and must contain no credentials or private values. Each stage accepts at most 32 parameters. Generated client_id, grant_type, codes, redirect_uri, state, nonce, PKCE and token fields cannot be overridden; scope and resource use the typed settings above. Credential parameter names and request objects are refused. The complete public profile is limited to 60 KiB.

Only enable a device pending rule after confirming that the exact response means the device code is still waiting for approval. A matching rule does not change refresh handling; a different or missing description still terminates the device login. Omitting pending_errors disables description matching.

Group extraction does not assign cluster roles by itself. Authority still applies [identity] sanitisation and authorization policy to verified groups. The token's subject, issuer, audience, expiry, signing algorithm, signature and browser nonce checks remain fixed protocol checks. The client obtains and validates an id_token; access-token and userinfo claims are not merged into it. The public browser entry uses this profile's scopes, resource and parameters, with its HTTPS callback; the CLI loopback port is not used by that surface.

See the MSIS9612 example, verified claims and policy and error diagnosis.

Use the trusted issuer

The configured issuer and discovery issuer are cross-checked, tolerating a trailing slash. The token's iss must match the advertised validation issuer. Different hostnames or paths are refused; issuer aliases and a separate discovery-base override are unavailable. Use the same trusted provider coordinates on every node and client.

[identity]

Used by: Authority.

Checks on identity claims (the token's sub and groups, and Kubernetes impersonation values).

Key Type Default Purpose
allow_system_groups bool false Permit otherwise valid values starting with system:; each occurrence is logged at WARN because built-in roles can be privileged. Reserved literals such as kubernetes-admin / cluster-admin, and the gdsgate- namespace, remain refused.
max_length usize 253 Maximum length in bytes of one value (sub or one group).
max_groups usize 64 Maximum groups per identity. Limits the certificate's group list and the impersonation headers.
[identity]
allow_system_groups = false
max_groups          = 64

A token whose sub or groups contain a value starting with gdsgate- is refused; no key changes this. The prefix is reserved for names the cluster issues: gdsgate-admin and gdsgate-provisioner (control-plane certificates), gdsgate-connector, gdsgate-proxy, gdsgate-workload (nodes), and gdsgate-break-glass (break-glass rule). Map provider claims to names without this prefix.