> ## Documentation Index
> Fetch the complete documentation index at: https://docs.strata.io/llms.txt
> Use this file to discover all available pages before exploring further.

# OIDC App

Register OpenID Connect clients with the Orchestrator's built-in OIDC Provider. The Orchestrator acts as an authorization server, handling authentication flows, enriching claims from multiple identity sources, and providing seamless IdP failover -- all without changes to your OIDC-compatible applications.

<Note>
  **Console vs. YAML:** In the Maverics Console, an OIDC app's authentication, authorization, claims, scopes, token settings, and the Identity Fabric components it relies on are configured directly on the application's settings page. In YAML, these elements are configured within each app's configuration block (for example under `apps[].authentication`, `apps[].authorization`, and `apps[].claimsMapping`).
</Note>

## Overview

An OIDC app registers an OpenID Connect client with the Orchestrator's [OIDC Provider](/reference/modes/oidc-provider) mode. Each app entry defines a client with its own credentials, redirect URLs, grant types, and token settings. The Orchestrator issues ID tokens, access tokens, and refresh tokens to registered clients, acting as a standards-compliant authorization server.

## How It Works

The OIDC Provider authentication flow follows these steps:

1. **Application redirects** -- A user accesses an application registered as an OIDC relying party. The application redirects the user to the Orchestrator's authorization endpoint.
2. **Upstream authentication** -- The Orchestrator routes the user to the configured upstream identity provider (Microsoft Entra ID, Okta, etc.) for authentication. If multiple IdPs are configured, failover rules determine which to use.
3. **Attribute enrichment** -- After authentication, the Orchestrator loads additional attributes from configured attribute providers (directories, databases, APIs) and enriches the user's profile.
4. **Token issuance** -- The Orchestrator generates OIDC tokens (ID token, access token, optional refresh token) with claims mapped from the authenticated identity and enriched attributes.
5. **Application receives tokens** -- The application receives the tokens at its redirect URI and uses them for session establishment and authorization decisions.
6. **Ongoing token operations** -- The Orchestrator serves the JWKS endpoint for token verification, handles token introspection and revocation, and manages token refresh flows.

## Use Cases

* **SSO consolidation** -- Unify multiple IdPs behind a single OIDC interface so applications authenticate against one provider.
* **IdP migration with zero downtime** -- Move users between identity providers transparently while applications continue to use the same OIDC endpoints.
* **Legacy app modernization** -- Add OIDC-based authentication to older applications without rewriting them.
* **Claim enrichment from multiple sources** -- Combine attributes from multiple [Identity Fabric](/reference/orchestrator/identity-fabric) connectors into a single set of OIDC claims.

## Key Concepts

### Claims Mapping

Claims mapping translates attributes from upstream identity providers into OIDC token claims. The format `connector.attribute` (e.g., `upstream-idp.email`) references a specific claim from a named connector. This enables enriching tokens with data from multiple identity sources.

### IdP Failover

When multiple identity providers are listed under `authentication.idps`, the Orchestrator tries them in order. If the primary IdP is unavailable, authentication falls back to the next provider seamlessly -- no application changes required.

### Token Types

The Orchestrator issues two token formats: JWT tokens (self-contained, verified via JWKS) and opaque tokens (reference tokens, verified via introspection). Choice depends on whether resource servers can validate locally or must call back.

### Service Extensions

Go-based extension hooks allow custom logic at key points in the flow -- custom authentication checks, custom claim building, and custom attribute loading. These provide escape hatches when standard configuration is insufficient.

### Resources and Dependencies

An OIDC app declares the Identity Fabric components and service extensions it uses as its **resources**. Identity providers, attribute providers, and service extensions must be added to the app's resources before they can be referenced anywhere else in its configuration -- the authentication source, authorization rules, claim sources, and the Access Token and ID Token claim service extensions all select from the app's declared resources. This guarantees every reference points at a component the app actually uses.

## Setup

<Tabs>
  <Tab title="Console UI">
    In the Maverics Console you create an OIDC app from a few essentials, then refine the rest of its configuration from the application's settings page.

    <Steps>
      <Step title="Start a new OIDC application">
        Go to **Applications** in the sidebar, click **Create**, and select **OIDC-based**.
      </Step>

      <Step title="Enter the details">
        Provide:

        * **Name** -- the friendly name of your application.
        * **Client ID** -- the client ID OIDC clients use to authenticate. A unique value is suggested by default; keep it, or replace it with the existing `client_id` when migrating an existing integration.
        * **Public Client** (optional) -- enable for single-page or native apps that cannot securely store credentials. Public clients cannot use flows that require a client secret, such as `client_credentials`.
        * **Client authentication** -- a **Client Secret** or a **JWT** public key (RFC 7523).
        * **Grant Types** -- the flows this client supports. New apps default to **Authorization Code** and **Refresh Token**; the create form offers only modern and machine-to-machine flows (legacy flows can be enabled later).
        * **Redirect URLs** -- the allow-list of URLs your clients can be redirected to. Required when Authorization Code is used.
        * **Authentication Source** -- the identity service or authentication service extension that authenticates users. Required for interactive grants; not needed for non-interactive grants (Client Credentials, Token Exchange) since there is no end user to sign in.
      </Step>

      <Step title="Save">
        Click **Save**. Maverics creates the app with defaults -- the selected grant types and an allow-all access policy that uses the authentication source you chose -- and opens the settings page.
      </Step>
    </Steps>

    Once created, the settings page presents the configuration as a set of cards. Click **Edit** on a card to open its drawer.

    **Client Configuration**

    * **Client Credentials** -- the **Client ID** and the client authentication method: one or more **Client Secret** values, or **JWT Client Authentication (RFC 7523)** with a name, optional audience, and a public key from an uploaded file or a secret store reference.
    * **Redirect URLs & Endpoints** -- the **Redirect URLs** allow-list, an optional **Default Redirect URL (Fallback)** toggle, and **Logout Redirect URLs**.
    * **Application Security Settings** -- **Public Client**, **Require DPoP**, and **CORS** (**Allowed Origins** and **Include Credentials**).
    * **PKCE Configuration** -- **Bypass Proof Key for Code Exchange (PKCE)**, for legacy apps only.

    <Warning>
      Store client secrets in a [secret provider](/reference/orchestrator/configuration/secret-providers) rather than entering them directly. Use secret reference syntax (e.g., `<vault.client_secret>`) so the Orchestrator resolves the value at runtime.
    </Warning>

    **Grant Types & Tokens**

    * **Grant Types** -- choose from **Recommended and Modern Flows** (Authorization Code, Refresh Token), **Machine to Machine and Agentic Flows** (Client Credentials, Token Exchange), and **Legacy or Deprecated Flows** (ROPC, Implicit (ID Token), Implicit (Access Token)).
    * **Audience & Resource Configuration** -- the **Allowed Audiences** permitted in token requests.
    * **Access Token Settings** -- **Type** (**JWT** or **Opaque**), **Lifetime Seconds**, and **Length** (22--256 characters for opaque tokens).
    * **Refresh Token Settings** -- **Allow Offline Access**, **Lifetime Seconds**, and **Length** (22--256 characters).

    **Resources**

    Declare the Identity Fabric components and service extensions this app depends on. Click **Add Resource** and pick an identity provider, attribute provider, or service extension. Attribute providers also require an **Identity Source** and **Username Mapping**; service extensions that expose metadata can have per-app **Metadata Overrides**. Only resources declared here can be referenced by the app's authentication source, authorization rules, claim sources, and claim service extensions.

    **Access Control**

    * **Authentication** -- select the authentication source (an identity provider, continuity strategy, or authentication service extension from the app's resources) that establishes who the user is.
    * **Authorization** -- choose an **Authorization method**: **Allow all access**, **Use rules to define access**, **Use service extension**, or **Use rules + service extension**.
    * **Rules-Based Authorization** -- when using rules, define conditions with an **Identity Source**, **Attribute**, **Condition** (**Equals**, **Contains**, **Does not equal**, **Does not contain**), and **Value**. Combine conditions within a rule, and combine multiple rules, using **AND**/**OR**.
    * **Token Minting** -- optionally define Rego access-token minting policies (each with a **Policy Name** and **Policy Code**) that run across all grant types before a token is returned. At least one policy must accept the access token for the request to succeed.

    **Claims and OAuth 2.0 Scopes**

    * **Attribute to Standard OIDC Claim Mapping** -- map each OIDC claim by name to a source (one of the app's resources) and a value, so issued tokens carry consistent user information such as name, email, or roles.
    * **Custom Claim Service Extensions** -- optionally select a service extension to build non-standard claims for the **Access Token** and/or the **ID Token**.
    * **Custom OAuth Scopes** -- define additional scopes beyond the standard `openid`, `profile`, `email`, and `offline_access`.
  </Tab>

  <Tab title="Configuration">
    OIDC apps are defined under the `apps` key with `type: oidc`. For shared app fields (`name`, `type`) and authorization rule syntax, see the [Applications reference](/reference/orchestrator/applications).

    #### Configuration Reference

    **Core Fields**

    | Key                                     | Type    | Required | Description                                                                  |
    | --------------------------------------- | ------- | -------- | ---------------------------------------------------------------------------- |
    | `clientID`                              | String  | Yes      | Unique client identifier for the OIDC relying party                          |
    | `public`                                | Boolean | No       | When `true`, marks the client as a public client (no client secret required) |
    | `credentials.secrets`                   | Array   | No       | Client secrets used for client authentication                                |
    | `credentials.jwtPublicKeys[].name`      | String  | No       | Name identifier for a JWT-based client authentication key                    |
    | `credentials.jwtPublicKeys[].aud`       | String  | No       | Expected audience value for the client JWT assertion                         |
    | `credentials.jwtPublicKeys[].publicKey` | String  | No       | PEM-encoded public key for verifying client JWT assertions (RFC 7523)        |

    <Note>
      The `clientSecret` field is deprecated. Use `credentials.secrets` instead to support multiple secrets and secret rotation.
    </Note>

    **DPoP (Demonstrating Proof-of-Possession)**

    | Key                   | Type    | Required | Description                                       |
    | --------------------- | ------- | -------- | ------------------------------------------------- |
    | `dpop.enabled`        | Boolean | No       | Enable DPoP sender-bound access tokens (RFC 9449) |
    | `dpop.nonce.disabled` | Boolean | No       | When `true`, disables the DPoP nonce requirement  |

    **Grant Types and URLs**

    | Key                       | Type    | Required | Description                                                                                                                                                                                               |
    | ------------------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `grantTypes`              | Array   | No       | Allowed OAuth 2.0 grant types. Defaults to `authorization_code`, `client_credentials`, `refresh_token`. Also supports `urn:ietf:params:oauth:grant-type:token-exchange` (RFC 8693) and `password` (ROPC). |
    | `redirectURLs`            | Array   | No       | Allowed redirect URIs for authorization code flow                                                                                                                                                         |
    | `logoutRedirectURLs`      | Array   | No       | Allowed redirect URIs after logout                                                                                                                                                                        |
    | `allowDefaultRedirectURI` | Boolean | No       | Allow a default redirect URI when none is supplied in the request                                                                                                                                         |

    **Claims and Scopes**

    | Key                          | Type   | Required | Description                                                                                                                                     |
    | ---------------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
    | `claimsMapping`              | Object | No       | Map connector attributes to OIDC claims. Keys are claim names, values are `connector.attribute` references (e.g., `email: upstream-idp.email`). |
    | `customScopes.scopes[].name` | String | No       | Define custom OAuth scopes beyond the standard set                                                                                              |
    | `allowedAudiences`           | Array  | No       | Restrict which audience values are permitted in token requests                                                                                  |

    **Authentication**

    | Key                                         | Type   | Required    | Description                                                                            |
    | ------------------------------------------- | ------ | ----------- | -------------------------------------------------------------------------------------- |
    | `authentication`                            | Object | Conditional | See note below.                                                                        |
    | `authentication.idps`                       | Array  | No          | List of identity provider connector names for user authentication                      |
    | `authentication.isAuthenticatedSE`          | Object | No          | Service extension for custom authentication checks                                     |
    | `authentication.authenticateSE`             | Object | No          | Service extension for custom authentication flows                                      |
    | `authentication.backchannel.authenticateSE` | Object | No          | Service extension for backchannel authentication (used with the `password` grant type) |

    <Note>
      The `authentication` block is required when the client allows any interactive grant type. It may be omitted when `grantTypes` is restricted to `client_credentials` and/or `urn:ietf:params:oauth:grant-type:token-exchange`.
    </Note>

    <Note>
      `isAuthenticatedSE` and `authenticateSE` must be defined together. When using SE-based authentication, you cannot also specify `idps`.
    </Note>

    **Authorization**

    | Key                                               | Type    | Required | Description                                                                                                               |
    | ------------------------------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------- |
    | `authorization.allowAll`                          | Boolean | No       | Allow all authenticated users                                                                                             |
    | `authorization.rules`                             | Array   | No       | Authorization rules with `and`/`or` conditions. See [Applications](/reference/orchestrator/applications) for rule syntax. |
    | `authorization.rulesAggregationMethod`            | String  | No       | How to combine top-level rules: `and` (all must pass) or `or` (any may pass)                                              |
    | `authorization.isAuthorizedSE`                    | Object  | No       | Service Extension for custom authorization logic. Mutually exclusive with `allowAll` and `rules`.                         |
    | `authorization.unauthorizedPage`                  | String  | No       | Redirect URL for unauthorized users                                                                                       |
    | `authorization.tokenMinting.accessToken.policies` | Array   | No       | OPA policies for access token minting. Each entry has `name`, `file` (or `rego`).                                         |

    **Access Tokens**

    | Key                           | Type    | Required | Description                                                                                 |
    | ----------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------- |
    | `accessToken.type`            | String  | No       | Token format: `jwt` (signed JSON Web Token) or `opaque` (random string reference token)     |
    | `accessToken.length`          | Integer | No       | Length of opaque access tokens (22--256). Only applies when `accessToken.type` is `opaque`. |
    | `accessToken.lifetimeSeconds` | Integer | No       | Access token lifetime in seconds                                                            |

    **Refresh Tokens**

    | Key                               | Type    | Required | Description                           |
    | --------------------------------- | ------- | -------- | ------------------------------------- |
    | `refreshToken.allowOfflineAccess` | Boolean | No       | Enable refresh tokens for this client |
    | `refreshToken.length`             | Integer | No       | Refresh token length (22--256)        |
    | `refreshToken.lifetimeSeconds`    | Integer | No       | Refresh token lifetime in seconds     |

    **Attribute Providers and Service Extensions**

    | Key                               | Type   | Required | Description                                                           |
    | --------------------------------- | ------ | -------- | --------------------------------------------------------------------- |
    | `attrProviders[].connector`       | String | No       | Connector name for loading additional attributes after authentication |
    | `attrProviders[].usernameMapping` | String | No       | Template mapping for the username lookup (e.g., `{{ azure.sub }}`)    |
    | `loadAttrsSE`                     | Object | No       | Service extension for custom attribute loading                        |
    | `buildIDTokenClaimsSE`            | Object | No       | Service extension for customizing ID token claims                     |
    | `buildAccessTokenClaimsSE`        | Object | No       | Service extension for customizing access token claims                 |

    **CORS**

    | Key                       | Type    | Required | Description                                       |
    | ------------------------- | ------- | -------- | ------------------------------------------------- |
    | `cors.allowedOrigins`     | Array   | No       | Allowed CORS origins for browser-based OIDC flows |
    | `cors.allowedCredentials` | Boolean | No       | Allow credentials in CORS requests                |

    **Security**

    | Key                | Type    | Required | Description                                                                                                     |
    | ------------------ | ------- | -------- | --------------------------------------------------------------------------------------------------------------- |
    | `insecureSkipPKCE` | Boolean | No       | Disable PKCE requirement. **Not recommended** -- PKCE protects against authorization code interception attacks. |

    #### Example

    A complete OIDC app with authorization code flow, claim enrichment, and refresh tokens:

    ```yaml theme={null}
    apps:
      - name: employee-portal
        type: oidc
        clientID: employee-portal-client
        credentials:
          secrets:
            - <vault.employee_portal_secret>
        grantTypes:
          - authorization_code
          - refresh_token
        redirectURLs:
          - https://portal.example.com/callback
        claimsMapping:
          email: azure.preferred_username
          name: azure.name
          groups: azure.groups
        accessToken:
          type: jwt
          lifetimeSeconds: 3600
        refreshToken:
          allowOfflineAccess: true
        cors:
          allowedOrigins:
            - https://portal.example.com
    ```
  </Tab>
</Tabs>

## DPoP (Demonstrating Proof-of-Possession)

DPoP ([RFC 9449](https://datatracker.ietf.org/doc/html/rfc9449)) creates sender-bound access tokens -- the token is cryptographically tied to a specific client's key pair, preventing token theft and replay attacks. When a client presents a DPoP-bound access token, it must also present a proof that it possesses the private key. If an attacker intercepts the access token, they cannot use it without the client's private key.

DPoP is configured per-app on OIDC Provider applications. When enabled, the Orchestrator validates DPoP proof headers on token requests and issues sender-bound access tokens.

<Tabs>
  <Tab title="Console UI">
    In the Console, DPoP is set on the application's **Client Configuration** card under **Application Security Settings**. Enable **Require DPoP** to bind issued access tokens to the client's key; DPoP proofs are rejected if they are older than five minutes or issued more than five minutes in the future.
  </Tab>

  <Tab title="Configuration">
    ```yaml theme={null}
    apps:
      - name: my-secure-client
        type: oidc
        clientID: my-secure-client
        credentials:
          secrets:
            - <my_secure_client_secret>
        dpop:
          enabled: true
          nonce:
            disabled: false  # nonce required by default
        accessToken:
          type: jwt
          lifetimeSeconds: 3600
        authentication:
          idps:
            - upstream-idp
    ```
  </Tab>
</Tabs>

| Key                   | Type    | Default | Description                                                                                                                                                                           |
| --------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dpop.enabled`        | Boolean | `false` | Enable DPoP sender-bound access tokens per RFC 9449. When enabled, the Orchestrator validates DPoP proof headers and binds issued tokens to the client's public key.                  |
| `dpop.nonce.disabled` | Boolean | `false` | When `false` (the default), the Orchestrator requires a server-issued nonce in DPoP proofs. This prevents pre-generated proof replay. Set to `true` to disable the nonce requirement. |

<Note>
  DPoP provides defense against token exfiltration attacks. Even if an access token is stolen from a log, cache, or network trace, it cannot be used without the corresponding private key. For maximum security, combine DPoP with short token lifetimes and [TLS](/reference/orchestrator/tls-security) for transport-level protection.
</Note>

## JWT and Opaque Token Options

The `accessToken.type` field controls whether the OIDC Provider issues JWT tokens or opaque (reference) tokens:

* **JWT tokens** (`accessToken.type: jwt`) -- Self-contained tokens that include claims directly. Resource servers can validate them locally using the JWKS endpoint without calling back to the provider. This is the most common choice for APIs and modern applications.

* **Opaque tokens** (`accessToken.type: opaque`) -- Random string tokens that carry no claims. Resource servers must call the introspection endpoint to validate them. Use opaque tokens when you need to revoke tokens immediately or avoid exposing claims to intermediate services.

<Tabs>
  <Tab title="Console UI">
    In the Console, the access token format is set on the application's **Grant Types & Tokens** card under **Access Token Settings**. Choose the **Type** -- **JWT** or **Opaque** -- and optionally set **Lifetime Seconds** and, for opaque tokens, **Length** (22--256 characters).
  </Tab>

  <Tab title="Configuration">
    ```yaml theme={null}
    # JWT access tokens (self-contained, validated via JWKS)
    apps:
      - name: my-api-client
        type: oidc
        clientID: my-api-client
        accessToken:
          type: jwt
          lifetimeSeconds: 3600

    # Opaque access tokens (reference tokens, validated via introspection)
      - name: my-internal-client
        type: oidc
        clientID: my-internal-client
        accessToken:
          type: opaque
          length: 32
          lifetimeSeconds: 3600
    ```
  </Tab>
</Tabs>

## Token Minting Policies

OIDC apps can attach OPA token minting policies that the Orchestrator evaluates on every token request before issuance. They add a governance layer on top of authentication and authorization -- even after a user authenticates, a policy can deny or constrain the token based on client identity, grant type, requested scopes, or environmental conditions.

In the Console, manage these on the application's **Access Control** card under **Token Minting** (each policy has a **Policy Name** and **Policy Code**). In YAML, they are defined under `authorization.tokenMinting.accessToken.policies`.

For the policy `input` document, the `result` output schema, and worked deny-by-default Rego examples, see [OPA token minting policies](/guides/security/policies#configure-opa-token-minting-policies-oidc-provider-only-optional) in the Policies guide.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Token validation fails at the application">
    **Symptoms:** The application rejects tokens with "invalid signature", "unable to verify token", or similar errors.

    **Causes:**

    * The JWKS endpoint is unreachable from the application's network.
    * A key mismatch occurred after key rotation -- the application cached an old JWKS response.
    * The `oidcProvider.discovery.issuer` URL does not match the `iss` claim the application expects.

    **Resolution:**

    1. Verify that `oidcProvider.discovery.issuer` matches exactly what the application has configured as the issuer (including scheme, host, and path).
    2. Confirm the JWKS endpoint is accessible from the application by requesting `<issuer>/.well-known/openid-configuration` and following the `jwks_uri`.
    3. If you recently rotated keys, ensure the active signing key is the **first** entry in the `jwks` array and that old keys are still present for verification of previously issued tokens.
  </Accordion>

  <Accordion title="Redirect URI mismatch">
    **Symptoms:** Users see a "redirect\_uri\_mismatch" or "invalid redirect URI" error during the login flow.

    **Causes:**

    * The redirect URL sent by the application is not listed in the app's `redirectURLs` array.
    * A subtle mismatch in scheme (`http` vs. `https`), port, or trailing slash between the configured and requested redirect URI.

    **Resolution:**

    1. Add the exact redirect URI (including scheme, host, port, and path) to `apps[].redirectURLs` in the OIDC app configuration.
    2. Compare the redirect URI in the browser's address bar during the error with the configured values -- they must match character-for-character.
  </Accordion>

  <Accordion title="Claims missing from tokens">
    **Symptoms:** The application receives a valid token but expected claims (e.g., `email`, `groups`) are empty or absent.

    **Causes:**

    * The `claimsMapping` references a wrong connector name or attribute that does not exist on the upstream identity.
    * Attribute providers (`attrProviders`) are not configured, so enrichment attributes are not loaded.
    * The upstream IdP does not return the expected attributes in its token or UserInfo response.

    **Resolution:**

    1. Verify that connector names in `claimsMapping` match the `connectors[].name` values exactly.
    2. If enrichment is needed, confirm `attrProviders` entries are configured with the correct connector names and `usernameMapping`.
    3. Test the upstream IdP directly to confirm it returns the expected attributes.
  </Accordion>

  <Accordion title="IdP failover not working">
    **Symptoms:** Authentication fails when the primary IdP is down instead of falling back to a secondary IdP.

    **Causes:**

    * Only one IdP is listed in `authentication.idps` -- there is no fallback configured.
    * The secondary IdP connector is misconfigured (wrong URL, expired credentials, network issue).

    **Resolution:**

    1. Verify that multiple IdP connector names are listed in `authentication.idps` in the desired failover order.
    2. Test each connector independently by temporarily making it the only entry to confirm it works on its own.
    3. Check Orchestrator logs for connector-specific error messages when failover is attempted.
  </Accordion>

  <Accordion title="Ephemeral key warning / tokens invalidated on restart">
    **Symptoms:** All previously issued tokens become invalid after an Orchestrator restart. Logs may show a warning about ephemeral key generation.

    **Causes:**

    * The `jwks` array is omitted from `oidcProvider`, so the Orchestrator auto-generates an ephemeral RSA key pair on every startup. Each restart produces new keys, invalidating tokens signed with the previous keys.

    **Resolution:**

    1. Provide explicit signing keys in the `oidcProvider.jwks` array using [secret provider](/guides/security/secrets-management) references (e.g., `<oidc.signingPublicKey>`, `<oidc.signingPrivateKey>`).
    2. Ensure both `publicKey` and `privateKey` are set for at least one entry in the `jwks` array.
  </Accordion>
</AccordionGroup>

## Related Pages

<CardGroup cols={2}>
  <Card title="Applications" icon="grid-2" href="/reference/orchestrator/applications">
    Overview of application types and routing configuration
  </Card>

  <Card title="OIDC Provider" icon="openid" href="/reference/modes/oidc-provider">
    Configure the Orchestrator as an OIDC authorization server
  </Card>

  <Card title="Identity Fabric" icon="compass" href="/reference/orchestrator/identity-fabric">
    Connect identity sources for claim enrichment and IdP failover
  </Card>

  <Card title="Sessions" icon="id-badge" href="/reference/orchestrator/sessions">
    Session storage and lifecycle configuration
  </Card>
</CardGroup>
