# How to Configure OIDC/SSO Authentication with Authentik, Keycloak, Google, or Apple in TREK

> Configure OIDC SSO authentication for TREK using Authentik, Keycloak, Google, or Apple. Learn how to set up seamless single sign-on with this flexible OIDC flow.

- Repository: [Maurice/TREK](https://github.com/mauriceboe/TREK)
- Tags: how-to-guide
- Published: 2026-07-11

---

**TREK provides a built-in OpenID Connect (OIDC) flow that supports any OIDC-compatible provider—such as Google, Apple, Authentik, or Keycloak—through a three-layer architecture consisting of an admin UI, server controller, and OIDC service wrapper.**

The TREK repository ships with a complete SSO implementation that enables administrators to configure external identity providers without custom code. Whether you are integrating corporate Keycloak, self-hosted Authentik, or consumer providers like Google and Apple, the platform handles discovery, token exchange, and user provisioning automatically. This guide explains how to enable and configure OIDC authentication using the built-in admin interface or REST API.

## Understanding TREK's OIDC Architecture

TREK's authentication system is organized into three distinct layers that handle configuration, protocol exchange, and user management.

### Frontend Admin Configuration

The **Admin Settings UI** provides the primary interface for enabling SSO. Located in [`client/src/pages/admin/AdminSettingsTab.tsx`](https://github.com/mauriceboe/TREK/blob/main/client/src/pages/admin/AdminSettingsTab.tsx) (lines 30-95), this component allows administrators to toggle **SSO Login** and **SSO Auto-Provisioning**, and to input provider-specific parameters including issuer URLs, discovery endpoints, client IDs, and secrets.

### Server-Side Controller and Service

The backend implementation resides in two key files:

- **[`server/src/nest/oidc/oidc.controller.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/nest/oidc/oidc.controller.ts)**: Handles the OAuth2 + PKCE flow through endpoints `/api/auth/oidc/login`, `/api/auth/oidc/callback`, and `/api/auth/oidc/exchange`. This controller generates the `trek_oidc_state` cookie, validates incoming parameters against the [`shared/src/oidc/oidc.schema.ts`](https://github.com/mauriceboe/TREK/blob/main/shared/src/oidc/oidc.schema.ts) Zod schema, and manages the redirection flow.

- **[`server/src/nest/oidc/oidc.service.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/nest/oidc/oidc.service.ts)**: Acts as a thin wrapper around the legacy OIDC helper, performing provider discovery, token validation, user lookup, and JWT generation.

## Provider-Specific Configuration

Each identity provider requires specific issuer URLs and configuration nuances.

| Provider | Issuer URL | Discovery URL | Special Requirements |
|----------|------------|---------------|---------------------|
| **Google** | `https://accounts.google.com` | Auto-detected at `https://accounts.google.com/.well-known/openid-configuration` | Standard OAuth2 client credentials |
| **Apple** | `https://appleid.apple.com` | `https://appleid.apple.com/.well-known/openid-configuration` | Client secret must be a **JWT-signed** token per Apple's specifications |
| **Authentik** | `https://auth.example.com` | Must be specified manually (not automatically at `<issuer>/.well-known/openid-configuration`) | Custom discovery endpoint required |
| **Keycloak** | `https://keycloak.example.com/realms/{realm}` | Auto-detected unless using custom paths | Replace `{realm}` with your specific realm name |

## Step-by-Step Configuration via Admin UI

Follow these steps to activate OIDC authentication through the web interface:

1. Log in as a TREK administrator and navigate to **Admin → Settings → Single Sign-On (OIDC)**.

2. Toggle **"SSO Login"** to enable the external authentication button on the login page.

3. (Optional) Enable **"SSO Auto-Provisioning"** to allow TREK to automatically create local user accounts for new SSO users.

4. Configure the provider parameters:
   - **Display name**: The label shown on the login button (e.g., "Google" or "Corporate Authentik").
   - **Issuer URL**: The base URL of your identity provider (see table above).
   - **Discovery URL**: Leave empty for standard providers; required for Authentik or custom configurations.
   - **Client ID**: The OAuth2 client identifier obtained from your provider.
   - **Client Secret**: The confidential secret (or JWT for Apple).

5. Click **Save**. The configuration is persisted to the database and immediately active.

Once saved, [`client/src/pages/LoginPage.tsx`](https://github.com/mauriceboe/TREK/blob/main/client/src/pages/LoginPage.tsx) automatically renders a "Sign in with {Display Name}" button that initiates the OIDC flow.

## Manual Configuration via API

For infrastructure-as-code deployments, update the OIDC configuration directly using the REST API:

```bash
curl -X PUT https://your-trek.example.com/api/admin/oidc \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <admin-jwt>" \
  -d '{
        "issuer": "https://accounts.google.com",
        "discovery_url": null,
        "client_id": "YOUR_GOOGLE_CLIENT_ID",
        "client_secret": "YOUR_GOOGLE_CLIENT_SECRET",
        "display_name": "Google",
        "oidc_login": true,
        "oidc_registration": true
      }'

```

Replace the JSON values with your specific provider details. For Apple, replace `client_secret` with your JWT-signed secret. For Authentik, include the custom `discovery_url` field.

## Authentication Flow Deep Dive

When a user clicks the SSO button, TREK executes the following sequence:

1. **Login Initiation**: The browser redirects to `/api/auth/oidc/login`. The controller generates a PKCE code challenge and stores a one-time `trek_oidc_state` cookie.

2. **Provider Discovery**: The server retrieves the provider's configuration from the `.well-known/openid-configuration` endpoint (or the custom discovery URL for Authentik).

3. **Authorization Redirect**: The user is redirected to the provider's `authorization_endpoint` with the PKCE parameters.

4. **Callback Processing**: After authentication, the provider redirects to `/api/auth/oidc/callback` with `code` and `state` parameters. The controller validates the state cookie against the returned state.

5. **Token Exchange**: The server exchanges the authorization code for tokens, verifies the `id_token`, and fetches user information from the userinfo endpoint. If **SSO Auto-Provisioning** is enabled, TREK creates or updates the local user record.

6. **Session Establishment**: A short-lived JWT is converted into an auth-code returned to the frontend (`/login?oidc_code=...`). The frontend calls `/api/auth/oidc/exchange` to receive the final JWT, which is stored in the `trek_auth` cookie and returned in the response body.

All error conditions—such as invalid state or token failures—redirect to the login page with query parameters like `?oidc_error=token_failed`, displayed using i18n strings from `shared/src/i18n/*/login.ts`.

## Troubleshooting Common OIDC Errors

When integration issues occur, check these specific error patterns:

- **`oidc_error=issuer_not_https`**: The issuer URL must use HTTPS in production environments. Verify your configuration includes the `https://` prefix.

- **`oidc_error=no_email`**: The identity provider must expose an email claim. Ensure your OAuth2 scopes include `email` or that the user has granted email access.

- **State cookie missing**: Verify the browser accepts cookies and that third-party cookie blockers are disabled for your TREK domain. The `trek_oidc_state` cookie must persist between the login and callback requests.

- **Token exchange failures**: Check server logs for messages prefixed with `[OIDC] Login error:` or `[OIDC] Token exchange failed:`. These logs in [`server/src/nest/oidc/oidc.controller.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/nest/oidc/oidc.controller.ts) provide detailed failure reasons.

## Summary

- TREK's OIDC implementation spans three layers: the admin UI ([`AdminSettingsTab.tsx`](https://github.com/mauriceboe/TREK/blob/main/AdminSettingsTab.tsx)), the controller ([`oidc.controller.ts`](https://github.com/mauriceboe/TREK/blob/main/oidc.controller.ts)), and the service wrapper ([`oidc.service.ts`](https://github.com/mauriceboe/TREK/blob/main/oidc.service.ts)).
- Configuration supports standard providers (Google, Apple) and self-hosted solutions (Authentik, Keycloak) with specific discovery URL requirements.
- Enable SSO via **Admin → Settings** or programmatically through the `PUT /api/admin/oidc` endpoint.
- The flow uses **PKCE** for secure code exchange and supports automatic user provisioning.
- Errors are returned as query parameters (`oidc_error`) and handled by the i18n system in `shared/src/i18n/*/login.ts`.

## Frequently Asked Questions

### How does TREK handle user account creation with SSO?

When **SSO Auto-Provisioning** is enabled in the admin settings, TREK automatically creates a local user record during the first OIDC authentication. The system extracts the email from the identity provider's `id_token` or userinfo endpoint and maps it to a TREK user account. If disabled, only existing users with matching emails can log in via SSO.

### Can I use multiple OIDC providers simultaneously?

The current implementation supports a single OIDC configuration at the system level. While you can switch providers by updating the configuration in [`AdminSettingsTab.tsx`](https://github.com/mauriceboe/TREK/blob/main/AdminSettingsTab.tsx), TREK does not support multiple concurrent IdPs in the same instance. You must choose one primary provider (e.g., Google, Authentik, or Keycloak) per TREK deployment.

### What is the difference between the discovery URL and issuer URL?

The **issuer URL** is the base identifier of your identity provider (e.g., `https://accounts.google.com`). The **discovery URL** is the full path to the OpenID Connect configuration document (usually `<issuer>/.well-known/openid-configuration`). Authentik requires a custom discovery URL because its configuration endpoint may not follow the standard pattern, while Google and Keycloak auto-detect this location from the issuer.

### Is PKCE required for all providers in TREK?

Yes, TREK implements **PKCE (Proof Key for Code Exchange)** for all OIDC flows as implemented in [`server/src/nest/oidc/oidc.controller.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/nest/oidc/oidc.controller.ts). This security feature protects against authorization code interception attacks and is automatically generated for every login request, regardless of whether the provider strictly requires it.