Skip to content

Configure OpenID Connect (OIDC)

The Pull Server supports external identity providers via OpenID Connect, allowing users to sign in with their organization's existing credentials. Each provider also issues JWT bearer tokens that API clients can use directly.

When to use this guide

Use this guide when you want to:

  • Allow users to sign in through Microsoft Entra ID, Okta, Auth0, or any standards-compliant OIDC provider.
  • Avoid managing local passwords for team members who already have an organizational identity.
  • Enable CI/CD pipelines or scripts to authenticate with short-lived JWT bearer tokens from a trusted provider.

How it works

When OIDC is configured, the Pull Server registers a pair of authentication schemes for each provider:

  • Cookie scheme — used by the web UI; the browser is redirected to the provider, signs in, and a session cookie is issued.
  • JWT bearer scheme — used by API clients; the client presents an access token in the Authorization: Bearer header and the server validates it against the provider's authority.

On first sign-in, the server automatically provisions a local user account and links it to the provider identity. Subsequent sign-ins look up the existing account.

Note

OIDC users cannot set or change a local password. Their identity is managed entirely by the external provider.

Prerequisites

  • An application registered with your identity provider (client ID and secret).
  • The provider's authority (issuer) URL.
  • The Pull Server must be reachable at the redirect URI configured in your app registration.

Register an application with your provider

Microsoft Entra ID

  1. Open the Azure portal and navigate to Microsoft Entra ID → App registrations.
  2. Click New registration.
  3. Set the redirect URI to:
https://<your-server>/signin-oidc-<ProviderName>

For example: https://dsc.example.com/signin-oidc-EntraId 4. Note the Application (client) ID and Directory (tenant) ID. 5. Under Certificates & secrets, create a new client secret and note its value.

Okta

  1. In your Okta admin console, go to Applications → Create App Integration.
  2. Choose OIDC - OpenID Connect and Web Application.
  3. Set the sign-in redirect URI to:
https://<your-server>/signin-oidc-<ProviderName>
  1. Note the Client ID and Client Secret.
  2. Your authority URL is https://<your-okta-domain>.

Configure the Pull Server

Add one or more providers under Authentication:OidcProviders in appsettings.json:

{
    "Authentication": {
    "OidcProviders": [
        {
        "Name": "EntraId",
        "DisplayName": "Sign in with Microsoft",
        "Authority": "https://login.microsoftonline.com/<tenant-id>/v2.0",
        "ClientId": "<application-client-id>",
        "ClientSecret": "<client-secret>",
        "Scopes": ["openid", "profile", "email"]
        }
    ]
    }
}
{
  "Authentication": {
    "OidcProviders": [
      {
        "Name": "Okta",
        "DisplayName": "Sign in with Okta",
        "Authority": "https://<your-okta-domain>",
        "ClientId": "<client-id>",
        "ClientSecret": "<client-secret>",
        "Scopes": ["openid", "profile", "email"]
      }
    ]
  }
}
{
  "Authentication": {
    "OidcProviders": [
      {
        "Name": "Auth0",
        "DisplayName": "Sign in with Auth0",
        "Authority": "https://<your-auth0-domain>",
        "ClientId": "<client-id>",
        "ClientSecret": "<client-secret>",
        "Scopes": ["openid", "profile", "email"]
      }
    ]
  }
}

Warning

Store ClientSecret in a secrets manager or environment variable rather than in appsettings.json directly. Use ASP.NET Core Secret Manager during development, or environment variable overrides in production:

Authentication__OidcProviders__0__ClientSecret=<secret>

Restart the Pull Server after changing the configuration.

Configuration reference

Property Required Description
Name Yes Unique key for the provider. Used to build the redirect path /signin-oidc-{Name} and the challenge endpoint /api/v1/auth/oidc/{Name}/challenge.
DisplayName Yes Text shown on the login page button.
Authority Yes The OIDC issuer URL. The server appends /.well-known/openid-configuration to discover endpoints.
ClientId Yes The application (client) ID registered with the provider.
ClientSecret Yes The client secret for the authorization code flow.
Scopes No Additional scopes to request. Defaults to ["openid", "profile", "email"].
GroupClaimType No The token claim that contains group identifiers. Defaults to groups.

Multiple providers

You can configure more than one provider simultaneously. The login page will show a button for each.

{
  "Authentication": {
    "OidcProviders": [
      {
        "Name": "EntraId",
        "DisplayName": "Sign in with Microsoft",
        "Authority": "https://login.microsoftonline.com/<tenant-id>/v2.0",
        "ClientId": "<client-id-1>",
        "ClientSecret": "<secret-1>"
      },
      {
        "Name": "Okta",
        "DisplayName": "Sign in with Okta",
        "Authority": "https://<your-okta-domain>",
        "ClientId": "<client-id-2>",
        "ClientSecret": "<secret-2>"
      }
    ]
  }
}

Map provider groups to Pull Server roles

When a provider includes group identifiers in the token, you can map those groups to Pull Server roles for automatic role assignment.

  1. Set GroupClaimType to the claim name your provider uses (if it isn't groups):

    {
      "GroupClaimType": "roles"
    }
    
  2. In the web UI, navigate to Admin → Roles and create or edit a role.

  3. Add the external group ID to the role's group mappings.

Users whose token contains the mapped group identifier will automatically be granted that role on sign-in.

Authenticate API clients with JWT bearer tokens

Users who have signed in interactively at least once can also authenticate API requests with an access token issued by the same provider.

Prerequisites for bearer token auth

Bearer tokens are not automatically accepted for new identities. Both of the following must be true before a bearer token succeeds:

  1. The user must be provisioned. A local account and ExternalLogin record are created on first interactive sign-in. A token whose sub has no matching record will be rejected with a 401.
  2. The token audience must match ClientId. The Pull Server validates aud against the ClientId configured for the matching provider. Tokens acquired with a different resource/audience will fail validation.

To acquire a token whose audience matches ClientId, request the application's own scope. For Microsoft Entra ID this is api://<client-id>/.default (or <client-id>/.default). For other providers, use the resource/audience scope documented by that provider.

# Acquire a token scoped to the Pull Server application
$body = @{
    grant_type    = 'client_credentials'
    client_id     = '<client-id>'
    client_secret = '<client-secret>'
    scope         = 'api://<client-id>/.default'
}
$token = (Invoke-RestMethod `
    -Uri 'https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token' `
    -Method Post -Body $body).access_token

# Use the token in API calls
$headers = @{ Authorization = "Bearer $token" }
Invoke-RestMethod -Uri 'https://dsc.example.com/api/v1/configurations' `
    -Headers $headers
# Acquire a token scoped to the Pull Server application
TOKEN=$(curl -s -X POST \
  "https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token" \
  -d "grant_type=client_credentials&client_id=<id>&client_secret=<secret>&scope=api%3A%2F%2F<client-id>%2F.default" \
  | jq -r '.access_token')

# Use the token in API calls
curl -H "Authorization: Bearer $TOKEN" \
  https://dsc.example.com/api/v1/configurations

Note

The server determines which JWT bearer scheme to use by reading the iss (issuer) claim from the token and matching it against the configured provider authorities. No extra configuration is needed.

Verify the configuration

  1. Open https://<your-server>/login in a browser.
  2. A button labelled with your DisplayName should appear alongside the username/password form.
  3. Click the button — you should be redirected to your provider's sign-in page.
  4. After authenticating, you should be redirected back to the Pull Server and signed in.

Tip

If the button does not appear, check the Pull Server logs for configuration errors at startup. Common issues are an unreachable authority URL or a mismatched redirect URI in the provider's app registration.