BetaMCPG is in public beta. Join the waitlist for managed cloud + early-access features.
MCPG
beta
All guides
Security6 min

Identity — OIDC, mTLS, SPIFFE, API keys

Configure identity resolution. MCPG ships five identity plugins; pick one or chain them.

Identity is the first decision MCPG makes on every request. Five identity plugins ship out of the box; you can chain them (e.g. mTLS first, fall back to API key) or run just one.

The plugins

PluginWhen to use
identity.api-keyInternal services, simple bootstrap, no IdP
identity.basicLegacy systems migrating from htpasswd
identity.mtlsService-to-service with X.509 certs from upstream TLS termination
identity.oidcHuman users with Google / Okta / Auth0 / Entra
identity.workloadKubernetes / SPIFFE workloads with X.509-SVID + JWT-SVID

Multiple plugins can run in a chain. The first one to resolve an identity wins; the rest short-circuit.

OIDC (Google, Okta, Auth0, Entra)

yaml
identity:
  - id: oidc-google
    type: identity.oidc
    issuer: https://accounts.google.com
    audience: mcpg-prod
    jwks_url: https://www.googleapis.com/oauth2/v3/certs
    jwks_cache_ttl: 1h
    claim_mapping:
      subject: email
      groups: hd          # workspace domain

The plugin pulls JWKS on first use, refreshes via a circuit breaker (no cascading failures if the IdP is down), and validates JWT bearer tokens on every request. SSRF guards prevent the JWKS URL from being weaponized.

mTLS

When MCPG sits behind a TLS-terminating proxy that injects client cert info as headers:

yaml
identity:
  - id: mtls-front-door
    type: identity.mtls
    header: x-forwarded-client-cert
    subject_field: cn
    trusted_proxy_cidrs:
      - 10.0.0.0/8

The plugin only accepts the header when the request comes from one of the trusted CIDRs. Otherwise the header is ignored.

For direct mTLS (no proxy), enable tls.client_cert_required on the gateway listener itself; the plugin reads from the negotiated session.

SPIFFE workload identity

For Kubernetes / SPIRE deployments:

yaml
identity:
  - id: workload
    type: identity.workload
    workload_api_socket: unix:///run/spire/agent/api.sock
    trust_domain: example.org
    audience: mcpg-prod
    jwt_svid: true   # accept JWT-SVIDs in addition to X.509-SVIDs

The plugin streams from the SPIRE Workload API, hot-reloads trust bundles, and stamps each request with the resolved SPIFFE ID + selectors. Policy plugins downstream can then authorize on spiffe://example.org/ns/prod/sa/payments.

API key

Simplest option for internal services:

yaml
identity:
  - id: api-keys
    type: identity.api-key
    keys:
      - id: alice
        digest: $argon2id$v=19$m=65536,t=3,p=4$...
        attributes:
          team: platform
      - id: ci-bot
        digest: $argon2id$...
        attributes:
          team: ci

Generate digests with mcpg-ctl key generate. Constant-time comparison; no plaintext ever stored.

Chaining

When you have multiple paths to identity:

yaml
identity:
  - id: workload      # try SPIFFE first (service-to-service)
    type: identity.workload
    # …
  - id: oidc          # fall back to OIDC (human users via UI)
    type: identity.oidc
    # …
  - id: api-keys      # fall back to API key (CI bots)
    type: identity.api-key
    # …

Order matters. The first plugin to return Resolved wins.

After identity: policy

Identity resolution produces a Caller struct with subject, attributes, and audience. Policy plugins consume this. See the policy guide next.