Skip to main content

Generic OpenID Connect

Use driver generic to connect an OpenID Connect service to an AuthCrunch portal. The portal discovers the service's endpoints, exchanges the login code for tokens, validates the identity, and issues its own application token.

This reference targets caddy-security v1.3.0 with go-authcrunch v1.3.8. For a provider setup walkthrough, follow Keycloak. For the relationship between the provider, portal, and policy, read the OAuth/OIDC overview.

Discovery and browser login cross different network boundariesDiscovery and browser login cross different network boundaries

Discovery and browser login cross different network boundaries. The browser must reach the authorization endpoint, while the portal server must reach discovery, token, and key endpoints. The generic example verifies issuer, audience, signature, nonce, and its S256 transaction before mapping supported ID-token claims. Its own portal token, not the upstream token, authenticates the protected application.

Scroll horizontally when needed, or open the diagram for a larger view. Download Mermaid source.

What the provider must supply​

Register a confidential, server-side client that supports the authorization code flow. For the example below, configure:

Provider settingRequired value or behavior
Client credentialsA client ID and client secret
Token endpoint authenticationAccept client_id and client_secret in the form body (client_secret_post)
Redirect URIhttps://auth.example.com/auth/oauth2/generic/authorization-code-callback
Scopesopenid email profile, plus any provider-specific scope needed for your claims
PKCESupport the S256 challenge sent by the generic driver
ID tokenA signed id_token for this client, with the login's nonce and an email claim
Application membershipA string array claim such as groups: ["app-members"] in the ID token

Use your actual public portal hostname. The callback contains the AuthCrunch realm, generic; it does not have to match a tenant or realm name at the provider. This configuration expects an OIDC ID token. For an OAuth-only service such as GitHub, follow its dedicated provider guide and profile-API setup.

Complete configuration​

Set the portal hostname, provider issuer and discovery URL in this Caddyfile. The example expects a group named app-members; replace that matcher with the exact value your provider emits. The complete file is also in the generic example directory.

Caddyfile
# Set the public portal hostname and the provider issuer/discovery URLs.
{
admin off
persist_config off

security {
oauth identity provider generic {
driver generic
realm generic
client_id {env.GENERIC_CLIENT_ID}
client_secret {env.GENERIC_CLIENT_SECRET}
scopes openid email profile
issuer https://id.example.com
metadata_url https://id.example.com/.well-known/openid-configuration
login icon text "OpenID Connect"
}

authentication portal myportal {
enable identity provider generic
crypto default token lifetime 900
crypto key sign-verify {env.JWT_SHARED_KEY}
cookie path /

ui {
links {
"Example app" /app icon "las la-external-link-alt"
"My identity" /auth/whoami icon "las la-user"
}
}

# Reserve portal roles and app/member for the transforms below.
transform user {
regex match role "^(authp/.*|app/member)$"
action drop matched role
}

transform user {
match realm generic
action add role authp/user
}

transform user {
match realm generic
match role app-members
action add role app/member
}
}

authorization policy apppolicy {
set auth url https://auth.example.com/auth/
crypto key verify {env.JWT_SHARED_KEY}
allow roles app/member
}
}
}

auth.example.com {
route {
redir /auth /auth/ 308

authenticate /auth/* with myportal

@app path /app /app/*
route @app {
authorize with apppolicy
respond "You reached the OIDC-protected app." 200
}

respond "AuthCrunch is running. Open /app to begin." 200
}
}

The first transform removes provider-derived authp/* and app/member roles. The next transforms grant portal access and translate app-members into app access. Keep this order: an upstream role named app/member must not bypass the group rule, and authp/admin must not grant portal administration. Other provider roles remain available for matching.

Supply these variables to the running process:

VariableValue
GENERIC_CLIENT_IDThe registered OIDC client ID
GENERIC_CLIENT_SECRETThat client's secret
JWT_SHARED_KEYA random signing secret shared by this portal and policy

For an interactive trial, export the client credentials and generate the signing key with export JWT_SHARED_KEY="$(openssl rand -hex 32)". For a managed service, store all three in its protected environment and keep the signing key stable across restarts. {env.VARIABLE} resolves when AuthCrunch starts.

Run ./bin/authcrunch adapt --adapter caddyfile --config Caddyfile >/dev/null to check parsing, then ./bin/authcrunch run --config Caddyfile to start. Provisioning contacts the discovery and key endpoints. Start the provider first; parsing alone does not establish provider connectivity or valid credentials. The public HTTPS host also needs working DNS and certificate issuance.

The example disables the admin endpoint. Use Ctrl+C and restart the foreground process after edits. Replace the protected respond with your application's reverse_proxy when the login and denial checks pass.

Discovery, issuer, and keys​

Copy the exact discovery URL from the provider's configuration. Read its JSON from the AuthCrunch host to verify connectivity:

curl --fail --silent --show-error https://id.example.com/.well-known/openid-configuration
Caddyfile settingMeaning in this release
metadata_urlThe discovery document URL. It supplies authorization_endpoint, token_endpoint, and jwks_uri.
issuerExpected token issuer. It must match the token's iss exactly, including case and a trailing slash. If omitted, the driver uses the discovered issuer when supplied.
authorization_url / token_urlExplicit endpoint overrides; these take precedence over the corresponding discovery values.
base_auth_urlA provider base URL used by configuration defaults. It is not a substitute for metadata_url and does not establish the expected issuer. Omit it for this discovery-based example.

Use an issuer and discovery document for the same tenant or realm. The browser must reach the authorization endpoint; the AuthCrunch server must reach the token and signing-key endpoints and trust their TLS certificates. A container-only hostname in published metadata is not a browser-accessible URL.

The driver verifies signatures with the provider's public keys and checks the ID token's issuer, audience, and nonce. An invalid identity token rejects login. PKCE, nonce, TLS verification, and signing-key verification remain enabled in this example. Fix endpoint, certificate, and claim mismatches at their source.

The default token response requires both id_token and access_token. A non-identity access token may be opaque. A JWT access token can also contribute claims if its signature and trust checks succeed; a failed supplemental access token check does not invalidate an otherwise accepted ID token. Put essential application membership in the ID token to make the mapping explicit.

For static public-key pins, access-token audiences and remote rollover behavior, see Upstream OIDC token trust.

Map claims to application permissions​

The generic driver's supported role paths include:

Provider token claimAvailable to the portal as
groupsRoles after the portal combines group and role claims
role, group, rolesRoles
realm_access.rolesRoles, including Keycloak realm roles
app_metadata.authorization.rolesRoles
resource_access.CLIENT.rolesNot extracted by this release's generic token parser; map the needed values into a supported claim

Configure membership claims as arrays of strings and inspect the resulting roles at /auth/whoami. Claim extraction is implemented in the released token parser. Arbitrary token fields are not automatically copied into the AuthCrunch token.

The example's access decision is:

StageValue
Provider ID tokengroups: ["app-members"]
Portal transformMatches realm generic and role app-members
Issued AuthCrunch tokenIncludes the added app/member role
Application policyRequires app/member

A user without that group still receives authp/user for portal access but cannot reach /app. An identity-provider group is an authorization input; verify the issued claims and a denied account before opening access.

Email and UserInfo​

By default, the driver requires the email claim to be present in the identity token before optional UserInfo fetching runs. Requesting the email scope alone does not create it. Configure the provider's email mapper and the user's email. This presence check does not require email_verified: true.

For a provider that intentionally omits email, email claim check disabled inside the provider block disables that specific check. Review any email-dependent transforms before using it.

UserInfo fetching is optional and must be enabled explicitly, for example:

user_info_fields email groups

Place this inside the oauth identity provider block. It requires the openid scope and a discovered userinfo_endpoint. Selected ordinary fields are stored under userinfo; extracted role/group fields become portal roles. In this release, non-empty roles extracted from UserInfo replace the previously extracted token roles. Fetch errors are logged and login processing continues. UserInfo email does not satisfy the earlier ID-token email check. The UserInfo implementation defines this behavior; the complete example relies on ID-token claims instead.

Verify and troubleshoot​

Open /app, sign in through OpenID Connect, and check /auth/whoami. A member of app-members should reach the protected response; a different account should sign in but receive 403 at /app, /app/, and /app/nested. Use fresh logins after changing claims or transforms: existing AuthCrunch tokens keep their issued roles until they expire or are otherwise rejected.

SymptomCheck
Startup fails while loading the providerFetch the discovery document from the server; verify its URLs, TLS trust, and jwks_uri.
Provider rejects the clientCheck client ID/secret, confidential-client settings, and support for form-body client authentication.
Callback rejectedMatch the public scheme, host, port, /auth/ mount, and AuthCrunch realm exactly.
Issuer or audience failureUse the intended tenant's discovery document; compare iss with issuer and ID-token aud with the client ID.
Missing email errorAdd email to the ID token; a UserInfo-only email is too late for the default check.
Login works but the app denies accessInspect roles, including group prefixes or paths; check the transform and required app/member role.
A claimed custom field is missingCheck the supported token paths and any explicit UserInfo field selection.
Callback fails after retrying a copied URLStart a new login flow. Codes, state, nonce, and PKCE belong to one login attempt.

The Keycloak walkthrough shows the provider-side mapper and both allowed and denied users with this model.

Agentic Prompts​

Copy a prompt into your LLM to explore this topic. Each prompt prioritizes upstream repository guidance and code over this page, and asks for version-aware reasoning.

Trace generic OIDC login
Help me understand Generic OpenID Connect.

Primary authorities (take precedence over website documentation):
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each repository's root AGENTS.md first, then any scoped AGENTS.md that
applies to inspected paths. Read the relevant SKILL.md files and follow their
implementation and test references.

Relevant skills to locate: configuration-oauth-providers,
oauth-identity-provider.

Secondary reference:
https://docs.authcrunch.com/docs/authenticate/oauth/backend-oauth2-0000-generic

If a source is inaccessible, ask me to paste its relevant text. Identify the
versions your answer applies to; main may be newer than my release. Resolve
disagreements using code and tests, and flag unverified claims. Use synthetic
credentials and redacted examples; explain proposed checks before any changes.

Draw discovery, browser authorization, code/PKCE exchange, verified ID token,
portal transform, and app ACL. Separate realm from issuer and upstream tokens
from the portal access token. Ask which released library and adapter I run.
Review the provider contract
Help me understand Generic OpenID Connect.

Primary authorities (take precedence over website documentation):
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each repository's root AGENTS.md first, then any scoped AGENTS.md that
applies to inspected paths. Read the relevant SKILL.md files and follow their
implementation and test references.

Relevant skills to locate: configuration-oauth-providers,
oauth-identity-provider.

Secondary reference:
https://docs.authcrunch.com/docs/authenticate/oauth/backend-oauth2-0000-generic

If a source is inaccessible, ask me to paste its relevant text. Identify the
versions your answer applies to; main may be newer than my release. Resolve
disagreements using code and tests, and flag unverified claims. Use synthetic
credentials and redacted examples; explain proposed checks before any changes.

Review a redacted confidential-client registration for callback, form-body
client authentication, S256 PKCE, nonce, email, and intended ID-token
membership. Explain which URLs the browser versus server must reach and why a
container-only metadata hostname can fail.
Explore claim sources
Help me understand Generic OpenID Connect.

Primary authorities (take precedence over website documentation):
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each repository's root AGENTS.md first, then any scoped AGENTS.md that
applies to inspected paths. Read the relevant SKILL.md files and follow their
implementation and test references.

Relevant skills to locate: configuration-oauth-providers,
oauth-identity-provider.

Secondary reference:
https://docs.authcrunch.com/docs/authenticate/oauth/backend-oauth2-0000-generic

If a source is inaccessible, ask me to paste its relevant text. Identify the
versions your answer applies to; main may be newer than my release. Resolve
disagreements using code and tests, and flag unverified claims. Use synthetic
credentials and redacted examples; explain proposed checks before any changes.

Compare supported ID-token role/group paths, supplemental access JWT claims,
opaque access tokens, and optional UserInfo. Explain email presence timing and
whether UserInfo roles replace token roles in my release. Do not assume
arbitrary nested/custom claims are copied.
Diagnose login versus app denial
Help me understand Generic OpenID Connect.

Primary authorities (take precedence over website documentation):
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each repository's root AGENTS.md first, then any scoped AGENTS.md that
applies to inspected paths. Read the relevant SKILL.md files and follow their
implementation and test references.

Relevant skills to locate: configuration-oauth-providers,
oauth-identity-provider.

Secondary reference:
https://docs.authcrunch.com/docs/authenticate/oauth/backend-oauth2-0000-generic

If a source is inaccessible, ask me to paste its relevant text. Identify the
versions your answer applies to; main may be newer than my release. Resolve
disagreements using code and tests, and flag unverified claims. Use synthetic
credentials and redacted examples; explain proposed checks before any changes.

Help me classify discovery/TLS failure, invalid_client, callback mismatch,
issuer/audience/nonce failure, missing email, and 403 after successful login.
Ask for redacted metadata and normalized claims. Never disable token trust
checks to hide a registration mismatch.
Test role provenance
Help me understand Generic OpenID Connect.

Primary authorities (take precedence over website documentation):
https://github.com/greenpau/caddy-security/blob/main/AGENTS.md
https://github.com/greenpau/caddy-security/tree/main/.codex/skills
https://github.com/greenpau/go-authcrunch/blob/main/AGENTS.md
https://github.com/greenpau/go-authcrunch/tree/main/.codex/skills
Read each repository's root AGENTS.md first, then any scoped AGENTS.md that
applies to inspected paths. Read the relevant SKILL.md files and follow their
implementation and test references.

Relevant skills to locate: configuration-oauth-providers,
oauth-identity-provider.

Secondary reference:
https://docs.authcrunch.com/docs/authenticate/oauth/backend-oauth2-0000-generic

If a source is inaccessible, ask me to paste its relevant text. Identify the
versions your answer applies to; main may be newer than my release. Resolve
disagreements using code and tests, and flag unverified claims. Use synthetic
credentials and redacted examples; explain proposed checks before any changes.

Build member/nonmember and reserved-role injection cases for a generic portal.
Trace role removal, realm/group matching, and app/member grant. Include fresh
login after membership changes and distinguish parser validity, a synthetic
signing fixture, and a live provider browser test.

Source Code References​

Start with the code search, then follow the parser, runtime, and tests relevant to this topic. These links target main; use GitHub's branch/tag selector to compare them with your installed release.

  1. Search this topic in both repositories — searches topic-specific symbols and paths across both codebases.
  2. caddy-security: caddyfile_identity_provider_oauth.go — adapts OAuth/OIDC provider settings, scopes, endpoints, and trust options.
  3. go-authcrunch: pkg/idp/oauth/config.go — validates generic and named-driver defaults and endpoint settings.
  4. go-authcrunch: pkg/idp/oauth/provider.go — loads discovery metadata, provider readiness, and driver setup.
  5. go-authcrunch: pkg/idp/oauth/authenticate.go — handles authorization callbacks, token exchange, and identity completion.
  6. go-authcrunch: pkg/idp/oauth/jwt.go — checks upstream token signatures, issuer, audience, and transaction trust.
  7. go-authcrunch: pkg/idp/oauth/claim_parser.go — maps supported token claims into the normalized provider identity.
  8. go-authcrunch: pkg/idp/oauth/claim_parser_test.go — tests supported claim paths and rejected value shapes.