Learn Authentik - Integrating Applications with OIDC
Episode 10 of 31

Learn Authentik - Integrating Applications with OIDC

Integrating real applications like Grafana, Nextcloud, Portainer, and Gitea with Authentik OIDC, a login flow walkthrough, token verification with jwt.io, and troubleshooting common errors like redirect mismatches and scope issues.

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

Introduction

In episode 9, the token contents were fully in your hands through property mappings. Now it's time for the real test: connecting real applications. Grafana, Nextcloud, Portainer, Gitea — all support OIDC, and all can use Authentik as a single login gateway.

The trick is recognizing the pattern. Each application has a different configuration point, but the requested parameters are always the same: the discovery URL or endpoint, client ID, client secret, redirect URI, and scopes. You already have all those ingredients from episodes 8 and 9. All that's left is translating them into each application's configuration language.

The Common OIDC Integration Pattern

Before touching any application, make sure these four things are ready:

  • An OAuth2 provider in Authentik for that application, complete with the registered redirect URI.
  • An application in Authentik binding the provider, plus the access policy from episode 6.
  • The client ID and secret generated by the provider (for confidential clients).
  • Scopes: at minimum openid profile email, add offline_access if the application needs refresh tokens.

The redirect URI is a contract between the application and Authentik: both sides must write the exact same value.

Grafana

Grafana supports OIDC through the generic OAuth module. First, create an OAuth2 provider in Authentik with the redirect URI https://grafana.example.com/login/generic_oauth. Then add the configuration in the grafana.ini file.

grafana.ini
[auth.generic_oauth]
enabled = true
name = Authentik
allow_sign_up = true
client_id = <client-id>
client_secret = <client-secret>
scopes = openid profile email
auth_url = https://auth.example.com/application/o/authorize/
token_url = https://auth.example.com/application/o/token/
api_url = https://auth.example.com/application/o/userinfo/

allow_sign_up makes new users auto-created on first login — convenient for a homelab. For role control, you can map groups from the groups claim (built in episode 9) to Grafana roles, for example Viewer and Admin.

Nextcloud

Nextcloud uses the official user_oidc app. After installing it, go to Settings > OpenID Connect clients and register Authentik with:

  • Discovery URL: https://auth.example.com/application/o/nextcloud/.well-known/openid-configuration
  • Client ID and secret: from the OAuth2 provider.
  • Redirect URI: https://nextcloud.example.com/apps/user_oidc/code

Auto-discovery lets Nextcloud read all endpoints and JWKS keys directly from Authentik — a big advantage over manual configuration, because signing key changes on the provider don't need to be translated again.

Portainer

Portainer is configured through its UI: Settings > Authentication, then enable OAuth. It only asks for endpoint URLs and client credentials — there's no configuration file to edit:

  • Authorization endpoint: https://auth.example.com/application/o/authorize/
  • Token endpoint: https://auth.example.com/application/o/token/
  • Userinfo endpoint: https://auth.example.com/application/o/userinfo/
  • Client ID and secret: from the provider.
  • Redirect URI: https://portainer.example.com (shown by Portainer during configuration).

Enable Autoprovisioning so users who log in via Authentik automatically get an account. Without it, users must be created manually first.

Gitea

Gitea provides OAuth2 sources via Site Administration > Authentication Sources. Choose the OpenID Connect provider, then fill in:

  • OpenID Connect Auto Discovery URL: https://auth.example.com/application/o/gitea/.well-known/openid-configuration
  • Client ID and secret: from the Authentik provider.
  • Redirect URI: https://gitea.example.com/user/oauth2/<source-name>/callback

For reference, the same configuration can be represented in app.ini:

app.ini (example)
[oauth2_client.1]
NAME = Authentik
PROVIDER = openidConnect
CLIENT_ID = <client-id>
CLIENT_SECRET = <client-secret>
AUTO_DISCOVERY_URL = https://auth.example.com/application/o/gitea/.well-known/openid-configuration

Tip

Always start with the discovery URL rather than copying endpoints manually. It automatically loads the authorize, token, userinfo, and JWKS endpoints. If Authentik changes or the issuer mode is reset, applications with auto-discovery will stay in sync.

Login Flow Walkthrough

When all applications are configured, the SSO flow you see will look exactly like this:

  1. The user opens an application and presses the sign-in button.
  2. The browser is redirected to Authentik's authorize endpoint.
  3. Authentik runs the login flow: identification, password, then MFA if a policy requires it.
  4. The user consents to the scopes requested by the application.
  5. The browser returns to the application's redirect URI carrying a code.
  6. The application exchanges the code at the token endpoint using its client credentials.
  7. The application verifies the ID token and calls userinfo to build its local session.

From the user's perspective, login is the same single door for all applications. From the admin's perspective, one account and one set of policies controls everything.

Token Verification with jwt.io

After the first successful login, verify what the application actually receives. Paste the ID token into jwt.io — this tool decodes the header, payload, and signature. What to check:

  • iss: the issuer matches the application.
  • aud: contains the application's client ID.
  • exp: a sensible validity period.
  • Claims from episode 9's mappings: email, groups, or the custom claims you created.

Without opening a browser, you can decode a token from the command line:

Decode an ID token without a library
echo "<id-token>" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | jq .

Important

jq and base64 here are only for peeking at the token's contents — not authenticity verification. To verify the signature, use the public key from the JWKS endpoint. Accepting a token just because its payload is readable is a dangerous habit.

Troubleshooting Common Errors

Even with correct configuration, some errors keep recurring. Learn to recognize the patterns:

  • Redirect URI mismatch: the application sends a redirect URI not registered on the provider. Check the trailing slash, http vs https scheme, and hostname — all must be identical.
  • Invalid scope: the application requests a scope not configured on the provider. Make sure the scope mapping from episode 9 is added, and that the client actually requests that scope.
  • Signature verification failure: the application can't find the key or uses the wrong JWKS. Check the discovery URL and make sure a signing key (not HMAC) is selected on the provider.
  • email_verified false: the application refuses login because of the verification claim. Create a custom email_verified mapping as in episode 9, or verify the user's email.
  • Issuer mismatch: the issuer in the token doesn't match what the application expects. Review the provider's issuer mode.

Warning

When checking integration issues, open the Authentik logs and the application logs side by side. Errors usually appear twice: once from the application side (the parameters it sent), once from the Authentik side (the parameters it rejected). Matching both speeds up diagnosis dramatically.

Closing

Key points from this episode:

  • The OIDC integration pattern is always the same: discovery URL, client ID, client secret, redirect URI, and scopes.
  • Grafana via grafana.ini, Nextcloud via the user_oidc app, Portainer via the UI, Gitea via authentication sources.
  • The SSO login flow runs from redirect, authentication, consent, code, to the token exchange.
  • jwt.io and base64/jq for peeking at token contents; JWKS for verifying signatures.
  • Common errors: redirect mismatch, scope, signature, and issuer.

All modern applications now log in through a single door. But what about applications that don't support OIDC at all — old tools that only accept a plain reverse proxy? In episode 11, you'll get to know the proxy provider and outpost, Authentik's weapon for wrapping any application with authentication, without changing a single line of code.

Learn Authentik - Integrating Applications with OIDC | Learning Authentik