Learn Authentik - OAuth2/OIDC Provider Setup
Episode 8 of 31

Learn Authentik - OAuth2/OIDC Provider Setup

Configuring the OAuth2 and OIDC provider in Authentik: confidential and public client types, redirect URIs, signing keys, scopes, and sub-modes, plus how to test the authorization code flow end-to-end with token and userinfo endpoints.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 7, Authentik's internal authentication flow was complete with MFA. But all of that still stands alone — other applications can't use it yet. Time to build the industry-standard bridge: OAuth2 and OpenID Connect (OIDC).

There's one difference that must be clear from the start. OAuth2 is an authorization protocol: it gives applications permission to access resources on behalf of a user. OIDC is built on top of OAuth2 and adds an authentication layer: it proves who the user is via a token carrying identity. To use an analogy, OAuth2 is like a building area access pass, while OIDC is like the identity card you carry inside. Authentik acts as the identity provider issuing both.

Creating an OAuth2 Provider

First step: open the Admin interface, go to Applications > Providers, and create a new provider of type OAuth2/OIDC. There are several important decisions in this form.

Client Type: Confidential vs Public

The client type determines how much trust can be placed in the requesting application:

  • Confidential: for applications with a server backend, like Grafana or Nextcloud. The application can store a secret securely, so besides client_id it's also given a client_secret. Like a permanent employee holding the key to the server room.
  • Public: for single-page applications or mobile apps where all logic runs on the client side. There's no securely stored secret, so they must rely on PKCE. Like a guest access card that must not carry secrets.

Redirect URI

This is the field that most often becomes a source of problems. The redirect URI is the list of destination addresses after login completes — Authentik will only send the authorization code to registered URIs. Match it exactly: scheme, host, path, even the trailing slash. If left empty, Authentik uses the first URI the application requests as the stored value.

Signing Key

The second important decision:

  • Select an RSA certificate: tokens are signed asymmetrically. Applications verify the signature via the public key provided by the JWKS endpoint. This is the recommended mode.
  • Leave it empty: Authentik signs tokens symmetrically using the client secret as the HMAC key. Simple, but sharing the secret with the application becomes the only guarantee.

Scopes and Sub-Mode

  • Scopes: choose the scopes the application may request. openid is required for OIDC; profile provides basic data, email provides the email address, and offline_access enables issuing refresh tokens. If a client doesn't request any scope, Authentik treats all default scopes as requested.
  • Sub-mode: in the advanced protocol settings, you can configure how the sub (subject) value is formed — for example UUID-based or username-based — as well as the issuer mode controlling the iss value in tokens: unique per application based on its slug, or uniform across all providers.

Tip

Start with the per-provider issuer mode (default) because it matches the slug-based discovery and JWKS structure. The global mode only needs consideration if an application forces a single issuer for all clients.

OAuth2 Endpoints You Should Know

All endpoints live under the /application/o/ prefix. You'll use this table constantly when configuring applications:

FunctionEndpoint
Authorization/application/o/authorize/
Token/application/o/token/
User Info/application/o/userinfo/
JWKS/application/o/<slug>/jwks/
OpenID Configuration/application/o/<slug>/.well-known/openid-configuration
End Session/application/o/<slug>/end-session/

Important

Because the endpoints above are global, you must not create applications with the slugs authorize, token, userinfo, introspect, or revoke — their names would collide with the OAuth2 endpoints and break routing.

Authorization Code Flow, Step by Step

This is the most common flow for web applications with a backend. It runs like an airport check-in queue — each step hands proof to the next:

  1. The user presses the login button in the application.
  2. The application redirects the user's browser to the authorize endpoint with client_id, redirect_uri, scope, and state.
  3. Authentik runs the authentication flow — identification, password, then MFA from episode 7.
  4. The user consents to the scopes requested by the application.
  5. Authentik redirects the browser back to the redirect_uri carrying a code.
  6. The application exchanges the code at the token endpoint using client_id and client_secret.
  7. Authentik responds with an access_token and id_token (and a refresh_token if the offline_access scope was requested).
  8. The application verifies the tokens via JWKS, then fetches the profile from the userinfo endpoint.

Warning

An authorization code can only be used once and expires quickly. If an application receives a code twice or the code is old, the exchange will fail — this isn't an Authentik bug, it's protection against code theft.

Creating an Application and Binding the Provider

A provider isn't visible to users until it's bound to an application. An application is the object representing the real application in front of users: name, slug, icon, and launch URL. This is where the provider is connected, and where policies from episode 6 are bound to restrict who may open that application.

The recommended order: create the OAuth2 provider first, then create the application and choose that provider as its backend. The application slug also determines the discovery URL and issuer.

Testing with an OAuth2 Debugger

Before connecting a real application, test first. The fastest way is looking at the discovery document Authentik generates — the .well-known/openid-configuration file that automatically contains all endpoints.

Fetch the OpenID Connect configuration
curl -s https://auth.example.com/application/o/grafana/.well-known/openid-configuration

The response contains all endpoints, the issuer, and the supported signature types. From here, test the token exchange using the client_credentials grant to make sure the client credentials are correct.

Exchange client credentials for a token
curl -s https://auth.example.com/application/o/token/ \
  -u "<client-id>:<client-secret>" \
  -d "grant_type=client_credentials" \
  -d "scope=openid profile email"

Then fetch the profile via the userinfo endpoint using the newly obtained token.

Fetch the profile via the UserInfo endpoint
curl -s https://auth.example.com/application/o/userinfo/ \
  -H "Authorization: Bearer <access-token>"

To test the full flow with a browser, use an OAuth2 debugger — many are freely available on the web. Fill in the registered client_id, redirect_uri, and scopes, then follow the flow until the browser returns carrying a code. This is the closest simulation to a real application's experience.

Standard Claims

Once successful, look at the standard claims in the ID token:

  • iss: issuer — where the token was issued.
  • aud: audience — the application the token is intended for.
  • sub: subject — the user's identity (its form depends on the sub-mode above).
  • exp and iat: expiry time and issued-at time.
  • nonce: a random value from the request to prevent replay.

Other claims like email, name, and groups only appear if the related scope is requested and a property mapping provides them. How the token's contents are shaped is the topic of the next episode.

Closing

Key points from this episode:

  • OAuth2 is for authorization, OIDC for authentication; Authentik provides both in a single provider.
  • Confidential clients for backend applications, public clients with PKCE for SPAs and mobile.
  • The redirect URI must match exactly; the signing key determines how tokens are verified.
  • Authorization code flow: authorize, consent, code, token, userinfo.
  • Test with the discovery endpoint and an OAuth2 debugger before real integration.

The token is now issued, but its contents are still plain. In episode 9, you'll take full control of the token's contents through property mappings and claims — deciding which claims applications may carry, including custom group mappings of your own.