Enable server-to-server access to ForwardAuth-protected services (e.g., WebDAV) by:
Teaching /api/verify to accept Authorization: Bearer tokens (not just session cookies)
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.
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
Bearer token validation in /api/verify (unblocks everything)
client_credentials grant (proper token issuance)
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 grant2026-03-07 00:03:35 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Enable server-to-server access to ForwardAuth-protected services (e.g., WebDAV) by:
/api/verifyto acceptAuthorization: Bearertokens (not just session cookies)client_credentialsgrant type so services can obtain tokens without a browserUse 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.
Part 1: Bearer token validation in
/api/verifyCurrently
/api/verifyonly checks session cookies. Add support forAuthorization: Bearer <token>header:Authorization: Bearerheader first, fall back to session cookieoidc_access_tokens(same tokens issued by the token endpoint)Remote-User,Remote-Email,Remote-Groups, etc.)This is the core feature — both API keys and client_credentials tokens are validated the same way.
Part 2:
client_credentialsgrant on/oauth/tokenAdd
client_credentialsas a supported grant type: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.
grant_types_supportedin discovery endpointPart 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.How the pieces fit together
Implementation order
/api/verify(unblocks everything)client_credentialsgrant (proper token issuance)Add OAuth2 client_credentials grant for server-to-server authenticationto Bearer token support in ForwardAuth + OAuth2 client_credentials grant