Bearer token support in ForwardAuth + OAuth2 client_credentials grant #10

Open
opened 2026-03-05 10:36:25 +00:00 by Claude · 0 comments

Summary

Enable server-to-server access to ForwardAuth-protected services (e.g., WebDAV) by:

  1. Teaching /api/verify to accept Authorization: Bearer tokens (not just session cookies)
  2. Adding the client_credentials grant type so services can obtain tokens without a browser

Use Case

Canister (media organizer) needs to access a WebDAV server that sits behind Clinch's ForwardAuth. There's no browser involved — it's pure server-to-server.

Canister → webdav.example.com [Authorization: Bearer xyz]
             → Caddy forward_auth → Clinch /api/verify → validates token → 200
             → Caddy proxies to WebDAV

Part 1: Bearer token validation in /api/verify

Currently /api/verify only checks session cookies. Add support for Authorization: Bearer <token> header:

  • Check for Authorization: Bearer header first, fall back to session cookie
  • Look up the token in oidc_access_tokens (same tokens issued by the token endpoint)
  • Validate expiry, check application group access
  • Return the same headers (Remote-User, Remote-Email, Remote-Groups, etc.)
  • For client_credentials tokens (no user), return application-level identity

This is the core feature — both API keys and client_credentials tokens are validated the same way.

Part 2: client_credentials grant on /oauth/token

Add client_credentials as a supported grant type:

POST /oauth/token
  grant_type=client_credentials
  client_id=canister
  client_secret=secret123

Returns an access token directly. No browser, no redirects, no human. The application authenticates with its client_secret and gets a short-lived bearer token.

  • Application is the authenticated principal (no user context)
  • Token lifetime configurable per application (like existing TTL settings)
  • Group-based access control applies at the application level
  • Update grant_types_supported in discovery endpoint

Part 3 (optional): API Keys as an alternative

For simpler setups, allow admins to create long-lived API keys per application via the UI. Same validation path in /api/verify, just a different way to create the token.

API Key client_credentials
Created by Admin in UI Service, automatically
Lifetime Until revoked Configurable (e.g., 1 hour)
If leaked Access until revoked Limited window
Client code Read from config Token refresh logic needed

How the pieces fit together

Client Auth method Clinch's role
Kavita (OIDC app) authorization_code flow Issues tokens
Browser → WebDAV Session cookie via ForwardAuth Validates session
Canister → WebDAV Bearer token via ForwardAuth Validates token

Implementation order

  1. Bearer token validation in /api/verify (unblocks everything)
  2. client_credentials grant (proper token issuance)
  3. API keys via admin UI (optional, simpler alternative)
## Summary Enable server-to-server access to ForwardAuth-protected services (e.g., WebDAV) by: 1. Teaching `/api/verify` to accept `Authorization: Bearer` tokens (not just session cookies) 2. Adding the `client_credentials` grant type so services can obtain tokens without a browser ## Use Case Canister (media organizer) needs to access a WebDAV server that sits behind Clinch's ForwardAuth. There's no browser involved — it's pure server-to-server. ``` Canister → webdav.example.com [Authorization: Bearer xyz] → Caddy forward_auth → Clinch /api/verify → validates token → 200 → Caddy proxies to WebDAV ``` ## Part 1: Bearer token validation in `/api/verify` Currently `/api/verify` only checks session cookies. Add support for `Authorization: Bearer <token>` header: - Check for `Authorization: Bearer` header first, fall back to session cookie - Look up the token in `oidc_access_tokens` (same tokens issued by the token endpoint) - Validate expiry, check application group access - Return the same headers (`Remote-User`, `Remote-Email`, `Remote-Groups`, etc.) - For client_credentials tokens (no user), return application-level identity This is the core feature — both API keys and client_credentials tokens are validated the same way. ## Part 2: `client_credentials` grant on `/oauth/token` Add `client_credentials` as a supported grant type: ``` POST /oauth/token grant_type=client_credentials client_id=canister client_secret=secret123 ``` Returns an access token directly. No browser, no redirects, no human. The application authenticates with its client_secret and gets a short-lived bearer token. - Application is the authenticated principal (no user context) - Token lifetime configurable per application (like existing TTL settings) - Group-based access control applies at the application level - Update `grant_types_supported` in discovery endpoint ## Part 3 (optional): API Keys as an alternative For simpler setups, allow admins to create long-lived API keys per application via the UI. Same validation path in `/api/verify`, just a different way to create the token. | | API Key | client_credentials | |---|---------|-------------------| | Created by | Admin in UI | Service, automatically | | Lifetime | Until revoked | Configurable (e.g., 1 hour) | | If leaked | Access until revoked | Limited window | | Client code | Read from config | Token refresh logic needed | ## How the pieces fit together | Client | Auth method | Clinch's role | |--------|------------|---------------| | Kavita (OIDC app) | authorization_code flow | Issues tokens | | Browser → WebDAV | Session cookie via ForwardAuth | Validates session | | Canister → WebDAV | Bearer token via ForwardAuth | Validates token | ## Implementation order 1. Bearer token validation in `/api/verify` (unblocks everything) 2. `client_credentials` grant (proper token issuance) 3. API keys via admin UI (optional, simpler alternative)
Claude changed title from Add OAuth2 client_credentials grant for server-to-server authentication to Bearer token support in ForwardAuth + OAuth2 client_credentials grant 2026-03-07 00:03:35 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dkam/clinch#10