Registry stack documentation: machine-readable Markdown.
Index of all pages: https://docs.registrystack.org/dev/llms.txt
Full corpus: https://docs.registrystack.org/dev/llms-full.txt

# Connect an OIDC issuer

> Choose the secure network configuration for a Registry Stack token issuer.

Use this guide when a Registry Stack runtime must fetch OpenID Connect (OIDC) discovery metadata
or signing keys from an issuer on a public, private, container, or loopback network.

## Choose the issuer connection

Configure the exact issuer origin that you operate or trust. The runtime permits that declared
origin to resolve to a private address. A signing-key URI you declare in configuration, such as
`jwksSource: {type: uri, uri: ...}`, inherits the same allowance on any origin, so the runtime may
reach keys at a container or private address that differs from the issuer's public name. A
`jwks_uri` learned through discovery inherits the private address allowance only when it has the
same scheme, host, and port as the issuer.

| Deployment | Configuration |
| --- | --- |
| Local development on loopback | The product's local development mode (see below) |
| Docker Compose with an HTTP issuer on the container network | `allowInsecureHttp: true` beside the issuer |
| Kubernetes or a private network with an HTTPS issuer | No additional setting |
| Hosted issuer on public addresses | No additional setting |

Cloud metadata and link-local addresses remain blocked, declared or not. A cross-origin
signing-key endpoint learned through discovery also remains blocked when it resolves to a private
or loopback address, even if the declared issuer is private. Redirects are not followed, so an
accepted origin cannot redirect a key fetch to a different destination.

{/* Evidence: crates/registry-platform-oidc/src/lib.rs, IssuerNetworkPolicy;
    crates/registry-platform-httputil/src/lib.rs, FetchUrlPolicy and
    outbound_client_does_not_follow_redirects. */}

## Permit plain HTTP only when required

Without another setting, each product accepts a loopback HTTP issuer only in its own local
development mode:

- The Base Registry Engine (BReg) accepts an issuer or key URI on IPv4 or IPv6 loopback.
- Casework, Scheduling, Messaging, the Coordinator, BReg Review, and the MCP gateway accept one on
  loopback only when `listener.tlsTermination` is `development-loopback`.
- Evidence accepts only the canonical origin `http://127.0.0.1:PORT`, with the JWKS URI on that
  same origin, and only under the `local` assurance profile. `production` and `evidence-grade`
  bundles refuse loopback HTTP too.
- The OID4VCI front end accepts a `http://127.0.0.1:PORT` origin only under
  `validationMode: supervised-local-development`.

For an HTTP issuer elsewhere, set the runtime's `allowInsecureHttp` field beside `issuer`:

```yaml
authentication:
  oidc:
    issuer: http://identity.internal:8080
    allowInsecureHttp: true
```

The runtime logs a warning at startup while this setting is active. Keep it limited to a trusted
private network because bearer tokens and issuer metadata have no transport confidentiality on
plain HTTP. The setting covers the issuer's origin and a JWKS URI you configure. It does not
permit cloud metadata access, and a `jwks_uri` on another origin learned through discovery must
still use HTTPS and may not resolve to a private address. Evidence accepts it only under the `local` assurance profile:
`production` and `evidence-grade` bundles require HTTPS for the issuer and signing keys.

BReg Review has no `allowInsecureHttp` setting. It signs people in only with an HTTPS issuer, or a
loopback one under `development-loopback`, because it sends its client credentials to the
issuer's token endpoint.

## Trust an internal certificate authority

Prefer HTTPS for an in-cluster or private-network issuer. Registry Stack HTTP clients use rustls
with the operating system's native trust roots. Install the internal certificate authority (CA)
in the host trust store before starting the runtime.

A distroless image usually has no writable host trust store. Mount a read-only PEM bundle into the
container and set `SSL_CERT_FILE` in the runtime environment. This variable replaces native-store
loading for the process, so the bundle must contain the internal CA and every other root the
runtime needs, including public roots when it also calls public services:

```yaml
volumeMounts:
  - name: internal-ca
    mountPath: /etc/registry-stack/internal-ca.pem
    subPath: internal-ca.pem
    readOnly: true
env:
  - name: SSL_CERT_FILE
    value: /etc/registry-stack/internal-ca.pem
```

Restart the runtime after changing the mounted bundle, then use the product's readiness and doctor
checks to confirm that discovery and signing-key retrieval succeed. If the issuer is reachable but
certificate validation fails, confirm that the bundle contains every required root and the issuing
CA chain, and that `SSL_CERT_FILE` names the mounted file inside the container.

{/* Evidence: Cargo.toml, workspace reqwest features rustls-tls-native-roots;
    crates/registry-platform-httputil/src/lib.rs, OutboundClientBuilder;
    crates/registry-caseworkctl/src/dev/mod.rs, SSL_CERT_FILE runtime environment. */}