Appearance
plexctl platform-idp
plexctl platform-idp is the CLI surface over platform-scoped (shared) IdP bindings. A platform binding is owned by no Domain and is usable by any Domain, so a single upstream IdP — for example one GitHub OIDC app — can authenticate users into more than one Domain instead of forcing a duplicate binding per Domain. It groups two operations against /v1/admin/platform-idp:
plexctl platform-idp create— POST a newPlatformIdPBindingRequest.plexctl platform-idp list— GET every platform binding.
Unlike plexctl domain-idp, this family carries no --domain-id and no --primary flag: a shared binding has no owning Domain, and it has no Domain to be the default for. The just-in-time provisioned user joins the Domain selected at login, not the binding's.
Two safety contracts carry over from domain-idp:
- Secret masking on output. Response fields whose JSON key matches
(?i)secret|key|tokenare rewritten to***increateandlistoutput. Pass--reveal-secretsto opt out; in that case a one-line warning is written to stderr and the invocation is audit-logged. - File-only client secret on create.
--client-secretMUST be passed as@<path>to a file holding the secret; an inline literal is rejected at parse time. The file content is read once and trimmed of trailing whitespace before being marshalled into thePlatformIdPBindingRequest.client_secret_reffield.
A platform binding's domain_id is null in the response. The default table renderer shows the domain column as platform to make the scope obvious at a glance.
Synopsis
shell
plexctl platform-idp create --client-id <ID> --client-secret @<PATH> \
--discovery-url <URL> --issuer <URL> --jit-policy allow|deny \
[--alias <slug>] \
[--required-acr <VALUE>]... [--required-amr <VALUE>]... \
[--claim-mapping plexsphere_claim=idp_claim]...
plexctl platform-idp list [--reveal-secrets]Invocation
plexctl platform-idp create
POSTs a PlatformIdPBindingRequest to /v1/admin/platform-idp, gated on the platform manage permission. The CLI validates --jit-policy, parses --claim-mapping plexsphere_claim=idp_claim pairs, and rejects an inline literal --client-secret.
Flags
| Flag | Type | Required | Default | Description |
|---|---|---|---|---|
--client-id | string | yes | — | OIDC client identifier. |
--client-secret | string (@<path>) | yes | — | File spec; inline literals rejected. The file's trimmed contents become client_secret_ref. |
--discovery-url | URL | yes | — | OIDC discovery document URL. |
--issuer | URL | yes | — | OIDC issuer URL. |
--jit-policy | enum | yes | — | Just-in-time provisioning policy: allow or deny. |
--alias | string | no | — | Human-friendly handle for the binding, unique among active platform bindings (e.g. github). Normalised to lowercase kebab-case. A collision with another active platform alias surfaces as 409 alias-conflict. |
--required-acr | string (repeatable) | no | — | Required OIDC ACR value. May be passed multiple times. |
--required-amr | string (repeatable) | no | — | Required OIDC AMR value. May be passed multiple times. |
--claim-mapping | key=value (repeatable) | no | — | Map a plexsphere claim to an IdP claim, e.g. email=preferred_email. The mappings apply uniformly to every Domain that resolves through this shared binding. |
Persistent flags inherited from root: see plexctl.md. The root-level --reveal-secrets is honoured by create for masking fields on the IdPBindingResponse echoed back to stdout.
plexctl platform-idp list
GETs /v1/admin/platform-idp, gated on the platform read permission. Only platform bindings are returned; per-Domain bindings are reached via plexctl domain-idp list, which returns a Domain's effective set (its own bindings plus the platform ones). The response masks (?i)secret|key|token fields unless --reveal-secrets is passed.
Persistent flags inherited from root: see plexctl.md.
Exit codes
| Code | Reachable from | Meaning |
|---|---|---|
0 | every subcommand | Success. |
1 | every subcommand | Runtime / API error (non-2xx response, body parse error). |
2 | every subcommand | Flag-parse / misconfiguration (missing required flag, inline --client-secret without @ prefix, unknown --jit-policy, malformed --claim-mapping). |
3 | every subcommand | Missing or insecure credentials. |
4 | every subcommand | Permission denied (HTTP 403 from the server). |
No platform-idp subcommand produces exit 64; the whole family is wired against the typed OpenAPI client.
Examples
Create a shared IdP binding (file-only client secret)
shell
echo -n 'super-secret-from-github' > /run/secrets/github-client.secret
chmod 0400 /run/secrets/github-client.secret
plexctl platform-idp create \
--server "${PLEXSPHERE_URL}" \
--client-id plexsphere-shared \
--client-secret @/run/secrets/github-client.secret \
--discovery-url https://github-idp.example.com/.well-known/openid-configuration \
--issuer https://github-idp.example.com/ \
--jit-policy allow \
--alias githubList platform bindings (default masked output)
shell
plexctl platform-idp list \
--server "${PLEXSPHERE_URL}" \
--output jsonjson
[
{
"id": "0190a8c1-...-a0a4",
"domain_id": null,
"client_id": "plexsphere-shared",
"client_secret_ref": "***",
"discovery_url": "https://github-idp.example.com/.well-known/openid-configuration",
"issuer": "https://github-idp.example.com/",
"jit_policy": "allow",
"status": "active",
"alias": "github"
}
]Log in two Domains through the same shared binding
shell
# Two different Domains, one shared IdP — each user lands in its Domain.
plexctl login --server "${PLEXSPHERE_URL}" --domain-id "${DOMAIN_A}"
plexctl login --server "${PLEXSPHERE_URL}" --domain-id "${DOMAIN_B}"When a Domain owns no binding of its own, a Domain-only login resolves the shared platform binding from the Domain's effective set. When the Domain also owns a binding (or marks one primary), its own binding wins — the shared binding never out-ranks a Domain's own default.
Cross-references
../../../api/openapi/plexsphere-v1.yaml— OpenAPI source of truth for/v1/admin/platform-idpand thePlatformIdPBindingRequest/IdPBindingResponseschemas.domain-idp.md— the per-Domain IdP binding CLI surface, whoselistreturns a Domain's effective set.../../contexts/identity/idp.md— bounded-context reference: platform-scoped bindings, the just-in-time-into-login-Domain semantics, and the resolution precedence.login.md—plexctl login, which resolves a shared binding for a Domain that owns none.plexctl.md— root command reference (persistent flags, profile resolution, shared exit-code taxonomy).