Distinguish login clients and upstream credentials
Each client_id belongs to a different authentication flow; register and configure them separately. Replace these example domains. Hub user tokens target the full server.public_url; administrator tokens target admin.public_url. They are not interchangeable.
| Purpose | Configuration | Example callback registration |
|---|---|---|
| Employee CLI login to Hub | CLI --client-id |
http://127.0.0.1:PORT/oauth/callback |
| Ordinary-user portal | client_authorization.client_id |
https://hub.example.com/client-auth/auth/callback |
| Administrator browser login | admin.client_id |
https://admin.example.com/auth/callback |
| Hub verifies identity with enterprise SSO | auth.sso.upstream.client_id |
https://hub.example.com/sso/callback |
| User connects a business account | backends[].credentials.oauth.client_id |
https://hub.example.com/client-auth/api/accounts/callback |
backends[].oauth is Hub's service-account OAuth client_credentials, without a browser callback; credentials.oauth is personal user authorization. They cannot coexist. Hub required_scopes and upstream oauth.scopes are interpreted by their respective identity services and never automatically map or grant each other.
auth
Default built-in deployments configure LDAP and OIDC on the console’s Identity services page. Secrets are encrypted in managed storage and saving applies immediately. After the first UI save, database connection settings take precedence over auth.sso.upstream; YAML identity settings remain static and require restart.
| Field | Default / requirement | Meaning |
|---|---|---|
mode |
builtin in default templates |
Built-in accounts, with optional enterprise login. Advanced external verification uses external. |
issuer |
Derived in built-in mode | HTTPS origin of server.public_url plus /sso; no issuer environment variable. External mode requires a HTTPS issuer. |
sso |
Optional | Add an enterprise upstream or extra public clients. MCPBridge, portal and console registrations are provided by default. See built-in accounts and SSO. |
enterprise_membership_max_age |
24h |
Maximum age of verified enterprise membership, accepting 1m–720h. Expired membership requires sign-in or directory synchronization. Local accounts are unaffected. |
Permission groups in managed storage use mcphub:permissions; source_groups maps stable LDAP/OIDC organization IDs. The permission-group API's permissions.scope_mode: derived compiles a selected-capability scope snapshot when saved; explicit retains manual scopes. Manage these permissions through the console or API rather than adding user grants to startup YAML. See groups and permissions.
Built-in mode requires managed storage. Hub checks user permissions and sessions; password resets, disabling and MFA enrollment revoke credentials. Ordinary password authentication has no MFA marker. The following discovery/JWKS requirements apply to external verification.
JWT requirements are: the issuer and signature must validate against this issuer; aud must contain the complete server.public_url including its path—when aud is a string it must equal public_url, and when aud is an array it must include public_url; sub must be non-empty; and exp must be present. nbf, when present, is checked too. Expiry, activation, and OIDC time comparisons allow 30 seconds of clock skew. The verifier becomes ready only after OIDC discovery succeeds, jwks_uri is an absolute HTTPS URL, and a reachable JWKS response contains at least one parseable, valid, asymmetric public verification key; symmetric oct keys and invalid or empty keys do not satisfy this condition. Before that first successful refresh, the MCP endpoint returns 503; after it is ready, a temporary discovery or JWKS refresh failure retains the last-known-good verifier. OIDC discovery and JWKS responses are each capped at 1 MiB.
For JWKS readiness, a usable key has no use or use: sig; if key_ops is present it includes verify; and an explicit alg matches a supported RSA, EC, or Ed25519 JWS algorithm declared by OIDC discovery. If discovery omits id_token_signing_alg_values_supported, RS256 is assumed. Unsupported or malformed keys in the same JWKS do not hide another usable key.
Scopes are read from both JWT scope and scp claims. scope accepts only a space-delimited string (including an empty string or JSON null); scp accepts a space-delimited string or a string array. The two claims are merged and deduplicated; array entries may not contain whitespace. Backend access uses all-of semantics: required_scopes: [a, b] requires the token to contain both a and b. If either is missing, that backend is absent from the token's catalog view and an identified direct call returns 403 insufficient_scope. A backend with no required_scopes is not scope-gated. Protected Resource Metadata reports the deduplicated union of all backend required scopes in scopes_supported.
External OIDC registration for the user CLI
These requirements apply when using an external issuer directly. With auth.sso, register public clients with MCPHub as described in the SSO guide. Give users the MCP URL, client ID and any required fixed callback port.
Register a public native OAuth client at that issuer with authorization-code and refresh-token grants, PKCE S256, and token-endpoint authentication method none. Allow the callback http://127.0.0.1:<port>/oauth/callback; use an arbitrary loopback port when the provider supports native clients, or register a fixed port and pass --callback-port 8765. Discovery must advertise PKCE S256. The issuer must issue a signed JWT access token with an audience containing the exact MCPHub public URL, including /mcp, plus sub, exp, and the required scopes. No client secret is needed on the user's machine.