This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
# Connecting computer to Authelia (OIDC)
|
||||
|
||||
computer includes an **Authelia OpenID Connect provider scaffold**, but
|
||||
end-to-end sign-in is intentionally **stubbed**. Real credentials register
|
||||
the NextAuth provider; the login button and sign-in callback still block it
|
||||
until a developer implements mapping to local Go users.
|
||||
|
||||
This guide covers configuration you can prepare now and the developer work
|
||||
needed to finish the connection. Email/password login remains available.
|
||||
The client-managed OIDC flow runs on the trusted Next.js server; Go owns
|
||||
local users, accounts, and data authorization.
|
||||
|
||||
---
|
||||
|
||||
## 1. Current implementation
|
||||
|
||||
Paths in this table are relative to the repository root.
|
||||
|
||||
| Piece | File | Current behavior |
|
||||
|---|---|---|
|
||||
| Config detection | `web/lib/oidc-config.ts` | `enabled` means all three OIDC variables contain non-placeholder values; it does not verify connectivity or a working login |
|
||||
| Auth provider | `web/auth.ts` | Registers provider `authelia` when configured, but `callbacks.signIn` rejects every Authelia sign-in |
|
||||
| Login page | `web/app/login/client.tsx` | `oidcReady = false` keeps the button disabled even with real credentials |
|
||||
| Settings → OIDC | `web/app/(app)/settings/client.tsx` | Shows configuration status, issuer, and callback URL; explicitly says integration is pending |
|
||||
| Go OIDC handlers | `internal/oidc/provider.go` | Status reports configuration; login and callback return **501** |
|
||||
|
||||
A value counts as "not set" if it is empty or looks like a placeholder. These
|
||||
are matched case-insensitively: `REPLACE_ME`, `changeme`, `placeholder`,
|
||||
anything containing `example.com`/`.org`/`.net`, `<...>`, values starting with
|
||||
`your_`/`your-`, or `todo`.
|
||||
|
||||
**All three** variables must hold real values before the NextAuth provider is
|
||||
registered. The readiness gate and identity mapping are separate requirements.
|
||||
|
||||
The root `.env.example` supplies:
|
||||
|
||||
```env
|
||||
OIDC_ISSUER=REPLACE_ME
|
||||
OIDC_CLIENT_ID=REPLACE_ME
|
||||
OIDC_CLIENT_SECRET=REPLACE_ME
|
||||
```
|
||||
|
||||
Setting these values prepares the configuration. Complete section 4 before
|
||||
expecting users to sign in through Authelia.
|
||||
|
||||
---
|
||||
|
||||
## 2. What to configure in Authelia
|
||||
|
||||
The example uses **Authelia 4.39 syntax**. Authelia must have its OIDC provider
|
||||
configured, be served over valid HTTPS, and be reachable from both the user's
|
||||
browser and the Next.js container. See the upstream
|
||||
[OIDC provider](https://www.authelia.com/configuration/identity-providers/openid-connect/provider/)
|
||||
and [client configuration](https://www.authelia.com/configuration/identity-providers/openid-connect/clients/)
|
||||
documentation for your installed version.
|
||||
|
||||
### 2.1 Generate a client secret
|
||||
|
||||
```bash
|
||||
docker run --rm authelia/authelia:4.39 authelia crypto hash generate pbkdf2 \
|
||||
--variant sha512 --random --random.length 72 --random.charset rfc3986
|
||||
```
|
||||
|
||||
This prints:
|
||||
- **Random Password**: the *plain* secret. It goes into computer as `OIDC_CLIENT_SECRET`.
|
||||
- **Digest**: the *hashed* secret. It goes into Authelia's `client_secret`.
|
||||
|
||||
### 2.2 Register the computer client (`configuration.yml`)
|
||||
|
||||
Merge this example into the existing OIDC provider configuration. Replace the
|
||||
client secret digest and public app hostname; keep your existing provider
|
||||
signing keys, HMAC secret, and other clients.
|
||||
|
||||
```yaml
|
||||
identity_providers:
|
||||
oidc:
|
||||
# jwks / hmac_secret must already be configured for OIDC to work
|
||||
claims_policies:
|
||||
computer:
|
||||
# Include these identity claims in the ID token.
|
||||
id_token: ['email', 'email_verified', 'name', 'preferred_username']
|
||||
clients:
|
||||
- client_id: 'computer'
|
||||
client_name: 'computer'
|
||||
client_secret: '$pbkdf2-sha512$310000$...' # Digest from 2.1
|
||||
public: false
|
||||
authorization_policy: 'two_factor' # or 'one_factor'
|
||||
consent_mode: 'explicit'
|
||||
claims_policy: 'computer'
|
||||
redirect_uris:
|
||||
- 'https://<COMPUTER_HOST>/api/auth/callback/authelia'
|
||||
scopes: ['openid', 'profile', 'email']
|
||||
grant_types: ['authorization_code']
|
||||
response_types: ['code']
|
||||
token_endpoint_auth_method: 'client_secret_basic'
|
||||
```
|
||||
|
||||
Validate the configuration and restart your Authelia deployment after editing.
|
||||
|
||||
**Redirect URI rule:** it must exactly match
|
||||
`<NEXTAUTH_URL>/api/auth/callback/authelia`, including scheme, hostname, port
|
||||
if present, and path. For an HTTPS deployment, use
|
||||
`https://<COMPUTER_HOST>/api/auth/callback/authelia`.
|
||||
|
||||
The callback is handled by NextAuth on the **web app**, not the Go API.
|
||||
Forward `/api/auth/*` to Next.js in your reverse proxy. The identically named
|
||||
direct-Go callback on port 8080 is a deliberate 501 stub.
|
||||
|
||||
### 2.3 Users
|
||||
|
||||
Provide email and profile claims for Authelia users. Automatic local account
|
||||
creation and linking are not implemented yet. The developer integration must
|
||||
define account provisioning and verify ownership before linking an existing
|
||||
email/password account; matching an email string alone is not enough.
|
||||
|
||||
---
|
||||
|
||||
## 3. What to configure in computer
|
||||
|
||||
Set these environment variables in the **root** `.env` or hosting environment.
|
||||
Compose passes the OIDC variables to the API and web containers. Replace the
|
||||
sample hostnames with your actual hosts.
|
||||
|
||||
| Variable | Example | Notes |
|
||||
|---|---|---|
|
||||
| `NEXTAUTH_URL` | `https://computer.company.tld` | Public web app URL; determines the callback |
|
||||
| `COOKIE_SECURE` | `1` | For an HTTPS deployment |
|
||||
| `OIDC_ISSUER` | `https://auth.company.tld` | Exact issuer advertised in Authelia's discovery document |
|
||||
| `OIDC_CLIENT_ID` | `computer` | Must match `client_id` in Authelia |
|
||||
| `OIDC_CLIENT_SECRET` | *(plain secret from 2.1)* | The **plain** value, not the digest |
|
||||
|
||||
Keep the existing `AUTH_SECRET`: changing it makes stored IMAP passwords
|
||||
unreadable. The client secret is a separate value and stays server-side.
|
||||
|
||||
The default Compose ports bind to localhost. Configure an HTTPS reverse proxy
|
||||
for the public web URL before using these HTTPS settings; see
|
||||
[RUNNING.md](../../RUNNING.md#running-on-a-remote-server).
|
||||
|
||||
Apply environment changes from the repository root:
|
||||
|
||||
```sh
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Open **Settings → OIDC** to confirm the three variables are set. With real
|
||||
values it shows **Configured … Client integration is still pending**.
|
||||
This is configuration confirmation, not a successful connection test.
|
||||
|
||||
---
|
||||
|
||||
## 4. Developer handoff: complete local identity mapping
|
||||
|
||||
NextAuth handles OIDC discovery, authorization, token exchange, and token
|
||||
validation. The remaining integration must connect that verified identity to
|
||||
the PostgreSQL users that Go authorizes.
|
||||
|
||||
1. **Add trusted Go-backed identity lookup/provisioning.** No provisioning
|
||||
endpoint is supplied yet. Any new endpoint must authenticate calls from
|
||||
the trusted Next server, and accept only identities obtained after OIDC
|
||||
verification. Define first-login account creation and an explicit policy
|
||||
for linking existing accounts.
|
||||
2. **Persist the external identity link.** Use the `User` and `Account` tables
|
||||
in `db/schema.sql` to associate provider `authelia` and its verified subject
|
||||
with a local `User.id`. Validate the configured issuer as part of the flow.
|
||||
Returning users must resolve to the same local user.
|
||||
3. **Update `web/auth.ts`.** Replace the unconditional Authelia rejection in
|
||||
`callbacks.signIn` with the completed lookup/provisioning flow. Ensure the
|
||||
JWT/session callbacks store the resolved local `User.id`, rather than the
|
||||
OIDC profile's `sub`. `web/lib/api.ts` signs API assertions for the session
|
||||
ID, and Go expects that ID to identify a real local user.
|
||||
4. **Enable the login readiness gate.** Update `oidcReady` in
|
||||
`web/app/login/client.tsx` only after identity mapping works. Retain the
|
||||
configuration check for the three OIDC variables.
|
||||
5. **Rebuild and verify.** Run `docker compose up -d --build`, then perform
|
||||
the checks in section 5.
|
||||
|
||||
Keep the authorization-code callback on Next.js. Completing this integration
|
||||
does not require turning Go's placeholder login/callback routes into another
|
||||
OIDC client. Simply enabling the button or accepting `sub` as the local user
|
||||
ID will not make authenticated Go data access work.
|
||||
|
||||
## 5. Verify the completed integration
|
||||
|
||||
Before implementing the handoff, you can verify configuration and discovery:
|
||||
|
||||
1. Open `<OIDC_ISSUER>/.well-known/openid-configuration`. It should return
|
||||
JSON with the expected issuer and endpoints. The Next container must also
|
||||
be able to reach those HTTPS endpoints.
|
||||
2. Check **Settings → OIDC** for the configured issuer and exact callback URL.
|
||||
3. Confirm email/password login remains usable while integration is pending.
|
||||
|
||||
After the developer integration is complete:
|
||||
|
||||
1. Sign out, click **Sign in with Authelia**, and authenticate with Authelia.
|
||||
2. Confirm the browser returns through the NextAuth callback to `/pages`.
|
||||
3. Check `/api/me` through the web app and save a bookmark to confirm the
|
||||
session resolves to the intended local user and Go accepts its identity.
|
||||
4. Sign out and back in to verify the same user and data are retained.
|
||||
5. Test a new Authelia user, an explicitly linked existing account, and two
|
||||
different users to verify provisioning, account linking, and data isolation.
|
||||
|
||||
## 6. Troubleshooting
|
||||
|
||||
| Symptom | Likely cause |
|
||||
|---|---|
|
||||
| Variables are set, but button is disabled | Expected in the current build: `oidcReady` remains false until section 4 is implemented |
|
||||
| Config still says Not connected | One of the variables is empty or a placeholder, or containers were not recreated after editing `.env` |
|
||||
| NextAuth returns AccessDenied | The current `callbacks.signIn` deliberately rejects Authelia; after integration, investigate identity mapping |
|
||||
| Go callback returns 501 | Expected stub; the browser callback must reach Next.js, not Go |
|
||||
| Authelia shows "invalid redirect_uri" | Callback URL not listed exactly in `redirect_uris` |
|
||||
| Error page `?error=Configuration` after login | Wrong client secret (digest used instead of plain), or the issuer is unreachable or has an invalid TLS certificate |
|
||||
| Required identity claims are missing | Check Authelia's claims policy and user profile |
|
||||
| Browser has a session, but Go returns 401 | Check that the session ID is the resolved local `User.id`, not the OIDC subject |
|
||||
|
||||
## 7. Optional: Authelia-only login
|
||||
|
||||
Once the completed integration has been verified, decide whether to keep
|
||||
email/password login as a fallback. An Authelia-only deployment requires
|
||||
disabling the credentials provider, local login/signup screens, and local
|
||||
signup/login endpoints in both Next.js and Go, while preserving the trusted
|
||||
OIDC identity-provisioning path. Hiding the email form alone does not disable
|
||||
the backend password login routes.
|
||||
Reference in New Issue
Block a user