https://github.com/nihalgonsalves/oidc-cookie-forward-auth
Simple forward-auth provider to make cookie-based auth compatible with OpenID Connect
https://github.com/nihalgonsalves/oidc-cookie-forward-auth
forward-auth oidc oidc-proxy traefik
Last synced: 4 days ago
JSON representation
Simple forward-auth provider to make cookie-based auth compatible with OpenID Connect
- Host: GitHub
- URL: https://github.com/nihalgonsalves/oidc-cookie-forward-auth
- Owner: nihalgonsalves
- License: agpl-3.0
- Created: 2025-07-26T17:48:31.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2026-05-06T21:21:58.000Z (28 days ago)
- Last Synced: 2026-05-06T23:30:56.506Z (27 days ago)
- Topics: forward-auth, oidc, oidc-proxy, traefik
- Language: TypeScript
- Homepage:
- Size: 73.2 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
# OIDC Cookie Forward-Auth
This is a simple forward-auth middleware for Traefik that handles cookie-based
auth on behalf of a user authenticated via OpenID Connect.
Apps such as [tinyauth](https://github.com/steveiliop56/tinyauth) or
[oauth2-proxy](https://github.com/oauth2-proxy/oauth2-proxy) can protect
unauthenticated apps or apps that support auth via a plain header, but do not
provide support for stateful authentication.
This forward-auth middleware keeps track of cookies as part of the forward-auth
session, and provides them to the reverse-proxy forward-auth handler, to be used
in the origin request.
The forward-auth endpoint / server is never exposed. Everything is handled via
the forward-auth middleware.
## Setup
### Prerequisites
- A reverse proxy with forward-auth support (only [Traefik][traefik] is
currently supported and tested). See [Limitations](#limitations).
- An OIDC provider, such as [Pocket ID][pocket-id]. Any provider conforming to
the OIDC specification should work.
[traefik]: https://doc.traefik.io/traefik/getting-started/install-traefik/
[pocket-id]: https://github.com/pocket-id/pocket-id
### Configuration reference
#### Environment variables
| Name | Description |
| ---------------------- | ------------------------------------------------------------------------------------ |
| CLIENT_ID | OAuth2 Client ID |
| CLIENT_SECRET | OAuth2 Client Secret |
| OIDC_ISSUER_CONFIG_URL | Fully qualified OIDC issuer URL, e.g. `https://auth.example.com/` |
| SQLITE_PATH | Database file, e.g. `/var/lib/oidc/db/sessions.db`, defaults to in-memory if not set |
| DOMAIN_BASE | Base domain, used to shorten the config filenames |
| UNSAFE_COOKIE_INSECURE | Can be set to `true` or `1` to enable using insecure session cookies |
#### Configuration files
You must create a new config file in `/var/lib/oidc/config/` for each host you
want to support.
For example, if you have `https://whoami.example.com`, set your `DOMAIN_BASE` to
`.example.com`, and create a config file in at `/var/lib/oidc/config/whoami.ts`.
### Step-by-step
> [!TIP] There's a complete example in the
> [./docs/example/ directory](./docs/example/)
1. Make sure you have
[Traefik set up with SSL](https://doc.traefik.io/traefik/https/overview/)
correctly
1. Create a new OIDC client in your provider. The redirect URL is
`https://whoami.example.com/oauth2/callback` – the same host as your regular
service. The forward-auth proxy itself is not exposed.
If you need to protect multiple hosts, you can set a wildcard redirect URL,
list all the hosts, or create a client per host (as well as a forward-auth
container and middleware per host).
1. Add the forward-auth container and the middleware to the service you want to
protect:
```yaml
services:
# ...
oidc-cookie-forward-auth:
image: ghcr.io/nihalgonsalves/oidc-cookie-forward-auth:latest
# depends_on:
# pocket-id:
# condition: service_healthy
restart: unless-stopped
env_file:
# this file should contain:
# CLIENT_ID=...
# CLIENT_SECRET=...
- .env.oidc-cookie-forward-auth
environment:
# you can omit this and the DB volume if you'd like sessions not to
# be persisted across container restarts
SQLITE_DB: /var/lib/oidc/db/sessions.db
OIDC_ISSUER_CONFIG_URL: "https://auth.example.com/.well-known/openid-configuration"
DOMAIN_BASE: ".example.com"
volumes:
- oidc-db:/var/lib/oidc/db
# or other local path to store the config
- ./config/:/var/lib/oidc/config
expose:
- 3000
labels:
traefik.enable: true
traefik.http.middlewares.oidc-cookie-forward-auth.forwardauth.address: http://oidc-cookie-forward-auth:3000/oauth2/traefik
traefik.http.middlewares.oidc-cookie-forward-auth.forwardauth.authResponseHeaders: cookie
# ...
whoami:
depends_on:
oidc-cookie-forward-auth:
condition: service_healthy
image: traefik/whoami:latest
restart: unless-stopped
labels:
traefik.enable: true
traefik.http.routers.whoami.rule: Host(`whoami.example.com`)
traefik.http.routers.whoami.entrypoints: websecure
traefik.http.routers.whoami.middlewares: oidc-cookie-forward-auth
volumes:
oidc-db:
```
1. Create a config file:
```ts
// ./config/whoami.ts
export const config = {
// this is any function that returns a fetch Response containing
// the Set-Cookie headers
getUpstreamCookies: () =>
fetch(new URL("http://whoami:80/auth/signin"), {
method: "POST",
body: new URLSearchParams({
// you can also add env variables to the cookie auth file
// and reference them using process.env.NAME
username: "admin",
password: "password",
}),
}),
// this is a validation request to make sure the session is still valid.
// use any URL that is only accessible when logged in.
// this enables the user to use logout functionality inside the origin
// app and seamlessly invalidate the OIDC session too.
validateUpstreamSession: async (headers: Bun.HeadersInit) => {
try {
const response = await fetch(new URL("http://whoami:80/me"), {
headers,
redirect: "manual",
});
return response.ok;
} catch {
return false;
}
},
};
```
1. That's it. Start the container, and visit your service, for example
. You should be redirected to the OIDC provider.
Once logged in there, `getUpstreamCookies` will be called to log in to the
origin service, creating a session in the forward-auth service.
Every subsequent request will be re-validated using
`validateUpstreamSession`, and then the valid cookies will be sent to the
reverse proxy to be provided to the origin request.
## Limitations
- This has only been tested with Traefik, but Caddy and nginx also support
forward-auth and should work.
- While an upstream session is unique to a browser session, this doesn't support
any sub-configuration based on the user (or for e.g. groups). Access is
allowed as long as the OIDC provider authorises the user to access this
client.