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. |
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.