Skip to content

Runbook: añadir PocketID OIDC a un servicio nuevo

Estado al 2026-04-29: Vaultwarden, Karakeep, Paperless, Audiobookshelf, Immich, integrados con PocketID (nota: Jellyseerr va por CF Access edge, no OIDC nativo). Patrón verificado, gotchas conocidas documentadas abajo.

Cuándo usar OIDC nativo vs CF Access

Servicio tiene OIDC nativo Mobile/desktop apps lo consumen
Sí (audiobookshelf, immich, paperless, etc.) OIDC nativo (no CF Access — rompería las apps)
No Sólo web admin (dockge, dozzle, etc.) CF Access + PocketID (ver ../security/cloudflare-access-pocketid.md)
Sólo web Tu elección — OIDC nativo es mejor (1 menos punto de fallo)

Patrón general

  1. Crear OIDC client en PocketID (vía UI o DB script)
  2. Configurar la app (env vars o admin UI)
  3. Verificar email_verified=1 del user (auto-trigger lo hace)
  4. Probar login

1. Crear OIDC client

Vía UI (1 servicio)

https://pocketid.monxas.casa/settings/admin/oidc-clients → New: - Name: <service> - Callback URLs: depende del servicio (ver tabla abajo) - Public: OFF - PKCE: ON - Require re-auth: OFF

Tras crear, copia Client ID + Client Secret.

Vía script (en batch)

~/stacks/scripts/create-pocketid-clients.py (en VM 208) — define clients en lista, genera bcrypt secrets, INSERT directo. Output con plaintext para copiar a .env de cada app.

ssh media-208 'python3 ~/stacks/scripts/create-pocketid-clients.py'

2. Callback URLs por servicio (verificadas)

Servicio Callback URL Mobile callback (si aplica)
Vaultwarden https://<host>/identity/connect/oidc-signin
Karakeep https://<host>/api/auth/callback/custom
Audiobookshelf https://<host>/auth/openid/callback audiobookshelf://oauth
Immich https://<host>/auth/login app.immich:///oauth-callback
Paperless-ngx https://<host>/accounts/oidc/<provider_id>/login/callback/
Jellyseerr https://<host>/api/v1/auth/oidc-callback
Grafana https://<host>/login/generic_oauth
Stirling-PDF https://<host>/login/oauth2/code/<provider>

3. Config por tipo de app

Tipo A — env vars en compose

Vaultwarden (ojo: requiere fork timshel/oidcwarden)

image: timshel/oidcwarden:latest    # mainline NO incluye SSO
environment:
  - SSO_ENABLED=true
  - SSO_ONLY=false
  - SSO_AUTHORITY=https://pocketid.monxas.casa
  - SSO_CLIENT_ID=${VW_OIDC_ID}
  - SSO_CLIENT_SECRET=${VW_OIDC_SECRET}
  - SSO_PKCE=true
  - SSO_SCOPES=openid profile email
  - SSO_FRONTEND=override          # importante para que el botón aparezca
  - SSO_CALLBACK_PATH=/identity/connect/oidc-signin

Karakeep

environment:
  - NEXTAUTH_URL=https://<host>     # debe ser el público, NO LAN
  - OAUTH_WELLKNOWN_URL=https://pocketid.monxas.casa/.well-known/openid-configuration
  - OAUTH_CLIENT_ID=${KK_OIDC_ID}
  - OAUTH_CLIENT_SECRET=${KK_OIDC_SECRET}
  - OAUTH_PROVIDER_NAME=PocketID
  - OAUTH_SCOPE=openid profile email
  - OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING=true

Paperless-ngx (ojo: requiere PAPERLESS_APPS extra)

environment:
  - PAPERLESS_URL=https://<host>
  - PAPERLESS_APPS=allauth.socialaccount.providers.openid_connect   # CRÍTICO
  - PAPERLESS_SOCIALACCOUNT_PROVIDERS={"openid_connect":{"APPS":[{"provider_id":"pocketid","name":"PocketID","client_id":"${PAP_OIDC_ID}","secret":"${PAP_OIDC_SECRET}","settings":{"server_url":"https://pocketid.monxas.casa/.well-known/openid-configuration"}}],"OAUTH_PKCE_ENABLED":true}}
  - PAPERLESS_SOCIAL_AUTO_SIGNUP=True
  - PAPERLESS_ACCOUNT_DEFAULT_HTTP_PROTOCOL=https

Tipo B — admin UI

Audiobookshelf (Settings → Auth → OpenID Connect)

  • Issuer URL: https://pocketid.monxas.casa
  • Authorization URL: https://pocketid.monxas.casa/authorize
  • Token URL: https://pocketid.monxas.casa/api/oidc/token
  • Userinfo URL: https://pocketid.monxas.casa/api/oidc/userinfo
  • JWKS URL: https://pocketid.monxas.casa/.well-known/jwks.json
  • Logout URL: https://pocketid.monxas.casa/api/oidc/end-session
  • Match by: email
  • Auto-register: ✅
  • Subfolder for Redirect URLs: VACIO (si no, mete /audiobookshelf en la callback)

Immich (Administration → Authentication → OAuth)

  • Issuer URL: https://pocketid.monxas.casa/.well-known/openid-configuration
  • Scope: openid email profile
  • Signing alg: RS256
  • Storage label claim: preferred_username
  • Auto register: ✅

Jellyseerr (Settings → Users → OIDC Login)

  • OIDC Domain: pocketid.monxas.casa (sin https)
  • Allow new users: ✅
  • Email match required: ✅

4. PocketID gotchas (todas con triggers automáticos)

is_group_restricted=1 por defecto

Cualquier client recién creado vía UI sale restricted y bloquea a todos con "You're not allowed to access this service". Triggers activo:

CREATE TRIGGER auto_unrestrict_clients AFTER INSERT ON oidc_clients
BEGIN UPDATE oidc_clients SET is_group_restricted=0 WHERE id=NEW.id; END;

email_verified=0 por defecto

Sin verify, apps que requieren email verificado (ABS, Paperless, Immich) fallan con "User not found and email is not verified" o similar. Trigger activo:

CREATE TRIGGER auto_verify_email AFTER INSERT ON users
BEGIN UPDATE users SET email_verified=1 WHERE id=NEW.id; END;

Sólo bcrypt para crear clients vía DB

Si insertas un client a mano, el secret debe ir hasheado con bcrypt cost 10. Script ~/stacks/scripts/create-pocketid-clients.py (en media-208) lo hace.

5. Smoke test post-config

# Para cada hostname con OIDC:
curl -sk https://<host>/<oidc-login-url> -L -o /dev/null -w "%{http_code} -> %{url_effective}\n"
# Debe redirigir a https://pocketid.monxas.casa/authorize?client_id=...

O directamente: ir a la app en navegador, ver botón "Login with PocketID", click → debe redirigir a PocketID, hacer passkey, volver autenticado.

6. Limpieza

Si necesitas borrar un OIDC client:

ssh media-208 'sqlite3 /home/monxas/stacks/pocket-id/data/pocket-id.db "DELETE FROM oidc_clients WHERE name=\"<name>\""'

Si una app deja de necesitar OIDC: quitar env vars (Tipo A) o desactivar en la UI de admin (Tipo B), recrear container.

7. Reference

  • Doc OIDC + CF Access: ../security/cloudflare-access-pocketid.md
  • Endpoints PocketID: https://pocketid.monxas.casa/.well-known/openid-configuration
  • PocketID admin DB: /home/monxas/stacks/pocket-id/data/pocket-id.db