Vaultwarden con SSO por OpenID Connect y Pocket ID en Docker
Índice de contenidos
- Puntos clave
- Qué cambia en Vaultwarden al activar el SSO y qué no
- Qué monté y con qué versiones
- Por qué el SSO exige HTTPS y cómo lo resolví con Caddy sin dominio público
- Cómo levantar Vaultwarden, Pocket ID y Caddy con Docker Compose
- Cómo registrar Vaultwarden como cliente OIDC en Pocket ID
- Las variables SSO de Vaultwarden 1.37.3
- Cómo es el primer inicio de sesión con passkey
- Quién puede crearse una cuenta con SSO_SIGNUPS_ALLOWED
- Cómo cerrar el acceso por contraseña con SSO_ONLY
- Tres errores que encontré y cómo se arreglan
- La migración de MariaDB 12.2.2 que corrige la 1.37.3
- Keycloak, Authentik y otros proveedores en lugar de Pocket ID
- Qué no pude probar
- Preguntas frecuentes
- ¿El SSO de Vaultwarden sustituye a la contraseña maestra?
- ¿Qué pasa si pierdo la passkey de Pocket ID?
- ¿Puedo activar SSO en una instalación de Vaultwarden que ya tiene usuarios?
- Conclusión
- Fuentes
Vaultwarden 1.37.3 acepta inicio de sesión único por OpenID Connect con SSO_ENABLED, SSO_AUTHORITY y un cliente creado en tu proveedor. Con Pocket ID entras con una passkey, pero la contraseña maestra sigue siendo obligatoria porque es la que cifra la bóveda. SSO_SIGNUPS_ALLOWED decide si el SSO puede crear cuentas nuevas.
Vaultwarden 1.37.3 permite entrar en la bóveda por inicio de sesión único (SSO) con OpenID Connect, y con Pocket ID como proveedor el acceso pasa a ser una passkey. Lo que no cambia es la contraseña maestra: Vaultwarden la sigue pidiendo después del SSO, porque es la clave que cifra tus datos. Lo monté entero en Docker, con Caddy sirviendo HTTPS con una CA local, y aquí tienes las variables, el registro del cliente, el efecto de SSO_SIGNUPS_ALLOWED y SSO_ONLY, y los errores que me encontré. También está la versión en inglés de esta guía.
Puntos clave
- El SSO de Vaultwarden autentica a la persona, pero la bóveda se descifra con la contraseña maestra, que el proveedor OpenID Connect (OIDC) nunca ve.
- Vaultwarden 1.37.3, del 13 de septiembre de 2026, añade
SSO_SIGNUPS_ALLOWED: confalse, el SSO solo deja entrar a cuentas que ya existen o que tienen una invitación. - Pocket ID 2.16.0 no deja entrar a nadie en un cliente OIDC nuevo hasta que le asignas un grupo, y marca el correo de los usuarios creados a mano como no verificado.
- Ese correo no verificado bloquea el alta en Vaultwarden, y la variable que propone el ejemplo oficial de Pocket ID no lo arregla.
SSO_ONLY=truequita el acceso por contraseña de la web y el servidor rechaza el login por contraseña con un HTTP 400.- En MariaDB 12.2.2, una instalación hecha con la 1.37.2 conserva una clave foránea duplicada aunque actualices a la 1.37.3; se corrige con un
ALTER TABLE.
Qué cambia en Vaultwarden al activar el SSO y qué no
El SSO sustituye el primer paso del login, no el cifrado. La wiki de Vaultwarden sobre SSO[1] lo deja claro en su segunda línea: "A master password will still be required and not controlled by the SSO". Bitwarden cifra la bóveda en el cliente con una clave derivada de esa contraseña, y ni Vaultwarden ni Pocket ID la conocen.
En la práctica el flujo queda así:
- escribes tu correo en la web de Vaultwarden y pulsas Usar inicio de sesión único
- el navegador va a Pocket ID, que te pide la passkey y el consentimiento
- Pocket ID devuelve un código a
https://tu_dominio/identity/connect/oidc-signin - Vaultwarden canjea el código, te identifica y te pide la contraseña maestra para desbloquear
Vaultwarden guarda el vínculo en la tabla sso_users con el formato {iss}/{sub}, es decir, el emisor y el identificador del usuario en el proveedor. En mi laboratorio quedó así: https://id.b7p7.test:26743/e7733fbe-197a-4777-8472-fadd44c2d114. Lo que ganas es un solo sitio para dar altas y bajas y el fin de las contraseñas de login reutilizadas. La instalación básica de Vaultwarden está en la guía para instalar Vaultwarden con Docker, y esta parte de ahí.
Qué monté y con qué versiones
El laboratorio corrió el 30 de septiembre de 2026 en Docker sobre una máquina Linux arm64 de 18 núcleos. Son tres contenedores en una red de Compose, más Playwright con Chromium en el anfitrión para hacer los logins:
| Pieza | Imagen | Papel |
|---|---|---|
| Vaultwarden | ghcr.io/dani-garcia/vaultwarden:1.37.3 |
Servidor, con la web vault 2026.7.0 |
| Pocket ID | ghcr.io/pocket-id/pocket-id:v2.16.0 |
Proveedor OIDC solo con passkeys |
| Caddy | mirror.gcr.io/library/caddy:2.11.4-alpine |
Proxy inverso con TLS de una CA local |
| MariaDB | mirror.gcr.io/library/mariadb:12.2.2 |
Solo para la prueba de migración |
Los nombres vault.b7p7.test e id.b7p7.test usan .test, un dominio de nivel superior reservado para pruebas, y todo escucha en el puerto 26743. Pocket ID 2.16.0 salió el 20 de septiembre de 2026, según sus notas de versión[2]. Si todavía no tienes Pocket ID, la guía para instalar Pocket ID con passkeys cubre la instalación y el primer administrador.
Por qué el SSO exige HTTPS y cómo lo resolví con Caddy sin dominio público
Hacen falta certificados válidos en los dos extremos. El navegador solo permite WebAuthn, la API de las passkeys, en un contexto seguro, y la documentación de instalación de Pocket ID[3] lo pone como requisito. Además, Vaultwarden habla con Pocket ID por HTTPS desde dentro de su contenedor, y ese cliente también valida el certificado.
Sin dominio público, usé la CA interna de Caddy. Este es el Caddyfile completo:
{
https_port 26743
auto_https disable_redirects
local_certs
}
vault.b7p7.test {
reverse_proxy vaultwarden:80
}
id.b7p7.test {
reverse_proxy pocketid:1411
}
local_certs hace que Caddy firme los certificados con su propia raíz, que en este caso se llamó Caddy Local Authority - 2026 ECC Root y caduca en 2036. La documentación de HTTPS automático de Caddy[4] avisa de la consecuencia: "Any client accessing the site without trusting Caddy’s root CA certificate will show security errors". Esa confianza hay que darla en dos sitios:
- Vaultwarden: monta
root.crten el contenedor y apuntaSSL_CERT_FILEa él, como indica la wiki para CA privadas - Navegador: importa la misma raíz en su almacén de certificados; yo creé una base NSS con
certutilpara el perfil de Chromium de Playwright
Sin el primero, el log de Vaultwarden muestra failed to verify TLS certificate: invalid peer certificate: UnknownIssuer y después Failed to discover OpenID provider: Request failed. Con un dominio público y Let’s Encrypt no necesitas nada de esto, porque la raíz ya está en el almacén del sistema.
Cómo levantar Vaultwarden, Pocket ID y Caddy con Docker Compose
El compose.yml pone los tres servicios en la misma red y da a Caddy los dos nombres como alias, para que Vaultwarden resuelva id.b7p7.test hacia el proxy y no hacia fuera:
services:
caddy:
image: mirror.gcr.io/library/caddy:2.11.4-alpine
ports: ["127.0.0.1:26743:26743"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-data:/data
networks:
default:
aliases: [vault.b7p7.test, id.b7p7.test]
pocketid:
image: ghcr.io/pocket-id/pocket-id:v2.16.0
environment:
APP_URL: https://id.b7p7.test:26743
ENCRYPTION_KEY: ${POCKET_ID_ENCRYPTION_KEY}
TRUST_PROXY: "true"
ANALYTICS_DISABLED: "true"
volumes:
- ./pid-data:/app/data
APP_URL tiene que coincidir con la URL que ve el navegador, puerto incluido, porque Pocket ID la usa como emisor. La clave de cifrado sale de openssl rand -base64 32, como recomienda su documentación. El servicio de Vaultwarden completa el fichero:
vaultwarden:
image: ghcr.io/dani-garcia/vaultwarden:1.37.3
env_file: vaultwarden.env
volumes:
- ./vw-data:/data
- ./caddy-data/caddy/pki/authorities/local/root.crt:/ca/root.crt:ro
Arranca primero Caddy y Pocket ID con docker compose up -d caddy pocketid, para que Caddy genere la raíz antes de que Vaultwarden la monte. El descubrimiento responde en https://id.b7p7.test:26743/.well-known/openid-configuration, con issuer igual a APP_URL y firma RS256.
Cómo registrar Vaultwarden como cliente OIDC en Pocket ID
El cliente se crea en Administración > Clientes OIDC > Añadir cliente OIDC, y necesita tres datos. Estos son los que puse:
- URL de devolución de llamada:
https://vault.b7p7.test:26743/identity/connect/oidc-signin, que Vaultwarden construye a partir deDOMAIN - PKCE: activado, a juego con
SSO_PKCE=trueen Vaultwarden - Secreto: en Pocket ID 2.16.0 no aparece al guardar; se genera en la pestaña Credenciales con Añadir el secreto de cliente
Con eso el cliente existe, pero nadie puede usarlo. La documentación de grupos permitidos de Pocket ID[5] lo explica: "If you create a new OIDC Client, no user groups and therefore no users are allowed to access the client". Mi primer intento terminó en una página de Pocket ID con el error You are not allowed to access this service.
La solución que prefiero es crear un grupo vaultwarden-users, meter en él a quien deba usar la bóveda y marcar el cliente Vaultwarden en su pestaña Clientes OIDC permitidos. El botón Sin restricciones del cliente abre el acceso a todos los usuarios de Pocket ID.
Las variables SSO de Vaultwarden 1.37.3
La configuración cabe en un fichero de entorno. Este es el vaultwarden.env final del laboratorio, con el identificador y el secreto sustituidos:
DOMAIN=https://vault.b7p7.test:26743
SIGNUPS_ALLOWED=false
SSO_ENABLED=true
SSO_ONLY=true
SSO_SIGNUPS_ALLOWED=false
SSO_AUTHORITY=https://id.b7p7.test:26743
SSO_CLIENT_ID=tu_client_id_de_pocket_id
SSO_CLIENT_SECRET=tu_secreto_de_cliente
SSO_SCOPES=email profile offline_access
SSO_PKCE=true
SSL_CERT_FILE=/ca/root.crt
Cada variable hace una cosa, según el .env.template de la versión 1.37.3 de Vaultwarden[6] y la wiki:
SSO_ENABLED: activa el botón de inicio de sesión únicoSSO_AUTHORITY: la URL base del proveedor, sin/.well-known/openid-configuration; tiene que coincidir exactamente con elissuerdel descubrimiento, barra final incluida o excluidaSSO_SCOPES: por defectoemail profile;openidse añade soloSSO_PKCE: activo por defecto desde que existe la opciónSSO_SIGNUPS_ALLOWED: nueva en la 1.37.3, decide si el SSO puede crear cuentasSSO_ONLY: desactiva el login con correo y contraseña maestraSSO_SIGNUPS_MATCH_EMAIL: por defectotrue, asocia en el primer login una cuenta existente con el mismo correo
Sobre offline_access, en mi prueba Pocket ID 2.16.0 devolvió un token de refresco con ese ámbito y sin él. Lo dejo porque no cuesta nada y porque la wiki lo exige para Keycloak, Authentik y Authelia. El token de acceso que emitió Vaultwarden caducaba a los 3600 s.
Cómo es el primer inicio de sesión con passkey
La primera vez que entras por SSO, Vaultwarden crea la cuenta y te pide una contraseña maestra nueva, de 12 caracteres como mínimo. La pantalla se titula "Únete a la organización" y la URL lleva el identificador 00000000-01DC-01DC-01DC-000000000000, una organización ficticia que la web vault usa para este paso. Es cosmético: no se crea ninguna organización.
Automaticé el login con Playwright y un autenticador virtual de Chromium, que expone WebAuthn por el protocolo de DevTools. Registré la passkey en Pocket ID con ese autenticador y la reutilicé en cada prueba, así que el flujo pasó por la ceremonia WebAuthn real y no por un atajo. La cuenta creada usa PBKDF2 con 600 000 iteraciones, que es lo que eligió la web vault 2026.7.0.
En los logins siguientes, Pocket ID pide la passkey, Vaultwarden acepta el token y la web se queda en Tu caja fuerte está bloqueada hasta que escribes la contraseña maestra. Esa pantalla es la prueba práctica de que el SSO no toca el cifrado. Solo desde ahí llegué a la bóveda.
Quién puede crearse una cuenta con SSO_SIGNUPS_ALLOWED
Hasta la 1.37.2, cualquier persona capaz de autenticarse en tu proveedor obtenía una cuenta en Vaultwarden, salvo que filtraras por dominio de correo. La 1.37.3 separa esa decisión de SIGNUPS_ALLOWED con la nueva variable, y el .env.template la acompaña de un aviso: "You probably want to disable it when using a public provider". Con Google o GitLab como proveedor, eso significa cualquier cuenta de Google o de GitLab.
Lo probé con un segundo usuario de Pocket ID, beto, con passkey propia y dentro del grupo permitido:
- con
SSO_SIGNUPS_ALLOWED=falsey sin invitación, Vaultwarden rechazó el alta conSignups are disabled. You will need an invitation - después lo invité desde el panel
/adminy el mismo login por SSO creó la cuenta y pidió la contraseña maestra
Con Pocket ID, que solo da acceso a quien tú das de alta, dejar true es defendible. Yo prefiero false e invitaciones, porque así el alta en la bóveda es una decisión explícita y no un efecto secundario del grupo.
Cómo cerrar el acceso por contraseña con SSO_ONLY
SSO_ONLY=true deja el login de la web con un solo botón. Desaparecen la opción de entrar con contraseña maestra y el enlace Crear cuenta, porque Vaultwarden marca el registro como desactivado cuando el SSO es obligatorio.

El cierre también está en el servidor. Envié a /identity/connect/token una petición con grant_type=password y la respuesta fue un HTTP 400 con SSO sign-in is required. En el código de identity.rs de la 1.37.3[7] esa comprobación va antes de mirar la contraseña. Antes de activarlo, asegúrate de que todas tus cuentas ya entraron una vez por SSO y tienen el vínculo en sso_users.
Tres errores que encontré y cómo se arreglan
Los tres aparecieron con la configuración de las secciones anteriores, y cada uno deja un mensaje claro en algún log:
| Mensaje | Dónde aparece | Causa y arreglo |
|---|---|---|
You are not allowed to access this service. |
Página de error de Pocket ID | El cliente no tiene grupos permitidos; asigna un grupo o quita la restricción |
You need to verify your email with your provider before you can log in |
Log de Vaultwarden y aviso en la web | Pocket ID envía email_verified: false; marca el correo como verificado en el usuario |
Failed to discover OpenID provider: Request failed |
Log de Vaultwarden | El contenedor no confía en la CA; revisa SSL_CERT_FILE |
El segundo merece detalle. Los usuarios que creé a mano en Pocket ID, el administrador incluido, tenían el correo sin verificar, y Pocket ID envía el claim email_verified con ese valor. El ejemplo de Vaultwarden en la documentación de Pocket ID[8] propone SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION=true, pero en el código de la 1.37.3 esa variable solo cubre el caso en que el claim falta. Con false explícito, Vaultwarden rechaza el login igual.
Lo arreglé con el botón Marcar como verificado de la ficha del usuario en Pocket ID. No activé esa variable, que la wiki relaciona con un posible robo de cuenta si se combina con SSO_SIGNUPS_MATCH_EMAIL.
La migración de MariaDB 12.2.2 que corrige la 1.37.3
La 1.37.3 incluye el arreglo de la migración para MariaDB 12.2.2[9], y lo reproduje con un contenedor de MariaDB 12.2.2. Con Vaultwarden 1.37.2 sobre una base vacía, el arranque no da error, pero la tabla sso_users termina con dos claves foráneas: 1, sin cascada, y 2, con cascada. La migración antigua buscaba la clave por el nombre sso_users_ibfk_1, MariaDB 12.2.2 la llamó 1 y el borrado no ocurrió.
La consecuencia aparece al borrar un usuario vinculado por SSO: MariaDB responde ERROR 1451 (23000) porque la clave 1 no admite el borrado. Con la 1.37.3 sobre una base nueva queda una sola clave, con cascada. Lo que el arreglo no hace es reparar una base creada antes, porque la migración ya consta como aplicada entre las 55 que registra Vaultwarden. Si instalaste con MariaDB 12.2.2 y una versión anterior, actualiza y quita la clave sobrante:
SHOW CREATE TABLE sso_users;
-- si ves dos FOREIGN KEY sobre user_uuid, borra la que no tiene CASCADE
ALTER TABLE sso_users DROP FOREIGN KEY `1`;
Comprueba antes con SHOW CREATE TABLE cuál de las dos no tiene ON DELETE CASCADE, porque el número puede variar. Después de quitarla, el mismo borrado de prueba funcionó y eliminó la fila de sso_users. Si piensas actualizar el servidor de base de datos, el artículo sobre MariaDB 13 en Docker repasa qué cambia.
Keycloak, Authentik y otros proveedores en lugar de Pocket ID
Vaultwarden funciona con cualquier proveedor que publique el descubrimiento de OpenID Connect y autentique el cliente con identificador y secreto. La wiki recoge ajustes concretos para 12 proveedores, y los más habituales en un servidor propio son estos:
| Proveedor | SSO_AUTHORITY |
Ajuste que pide la wiki |
|---|---|---|
| Pocket ID | https://id.example.com |
Grupo permitido y correo verificado (en mi prueba) |
| Keycloak | https://host/realms/nombre_del_realm |
Token de acceso de al menos 10 minutos y offline_access |
| Authentik | https://host/application/o/nombre_app/ |
Barra final obligatoria, offline_access y firma RS256 |
| Authelia | La URL del servicio | offline_access para tener token de refresco |
En Keycloak y Authentik, la vida por defecto del token de acceso puede ser de 5 minutos. Es el mismo margen con el que la web vault de Bitwarden decide refrescarlo, y de ahí la advertencia.
Si ya usas Keycloak, el artículo sobre proteger un servidor MCP con Keycloak monta un realm con Docker que te sirve de base. La instalación de Authentik para SSO cubre la otra opción, y la comparativa entre Pocket ID, Authelia y Authentik ayuda a elegir. Solo probé Pocket ID; las filas de Keycloak, Authentik y Authelia resumen la wiki.
Qué no pude probar
Todo lo anterior pasó por la web vault. No probé las aplicaciones de escritorio ni las móviles de Bitwarden, y la wiki recoge problemas con la redirección del escritorio en Chrome y en Firefox para Linux. Tampoco probé un dominio público con Let’s Encrypt, ni la combinación del SSO con el segundo factor de Vaultwarden.
Una nota sobre la herramienta: el Chromium 153 que trae Playwright 1.63 se cerró con Received signal 4 al desbloquear la bóveda en arm64. Otras dos compilaciones de Chromium que tenía en caché hicieron el mismo flujo sin fallos, así que es un problema del navegador en esta máquina y no de Vaultwarden.
Preguntas frecuentes
¿El SSO de Vaultwarden sustituye a la contraseña maestra?
No. El proveedor OIDC te identifica, pero la bóveda se descifra en el cliente con una clave derivada de la contraseña maestra. Vaultwarden te la pide al crear la cuenta por SSO y en cada desbloqueo posterior.
¿Qué pasa si pierdo la passkey de Pocket ID?
Pierdes el primer paso, no los datos. Un administrador de Pocket ID puede emitir un código de acceso de un solo uso, por ejemplo con pocket-id one-time-access-token nombre_de_usuario dentro del contenedor, y registras una passkey nueva. Si guardas esa passkey dentro de Vaultwarden, la documentación de Pocket ID recomienda tener otra fuera.
¿Puedo activar SSO en una instalación de Vaultwarden que ya tiene usuarios?
Sí. Con SSO_SIGNUPS_MATCH_EMAIL=true, el valor por defecto, el primer login por SSO asocia la cuenta existente con el mismo correo, siempre que el proveedor marque ese correo como verificado. La contraseña maestra de esa cuenta sigue siendo la misma.
Conclusión
Conectar Vaultwarden 1.37.3 con Pocket ID son once variables y un cliente OIDC, y el resultado es un login con passkey delante de una bóveda que sigue cifrada con tu contraseña maestra. Lo que me llevó tiempo no fue el SSO sino sus bordes: los grupos permitidos de Pocket ID, el correo sin verificar y la confianza en la CA local. Mi recomendación es empezar con SSO_SIGNUPS_ALLOWED=false e invitaciones, activar SSO_ONLY cuando todas las cuentas tengan el vínculo en sso_users y, si usas MariaDB 12.2.2, revisar las claves foráneas de esa tabla.
Fuentes: [1] Notas de la versión 1.37.3 de Vaultwarden[6], [2] Wiki de Vaultwarden sobre SSO con OpenID Connect[1], [3] Código de identity.rs en Vaultwarden 1.37.3[7], [4] Pull request 7265 de Vaultwarden sobre MariaDB 12.2.2[9], [5] Notas de la versión 2.16.0 de Pocket ID[2], [6] Grupos permitidos en Pocket ID[5], [7] Instalación de Pocket ID[3], [8] Ejemplo de Vaultwarden en la documentación de Pocket ID[8], [9] HTTPS automático en Caddy[4].
Fuentes
- wiki de Vaultwarden sobre SSO
- notas de versión
- documentación de instalación de Pocket ID
- documentación de HTTPS automático de Caddy
- documentación de grupos permitidos de Pocket ID
- versión 1.37.3 de Vaultwarden
- código de identity.rs de la 1.37.3
- ejemplo de Vaultwarden en la documentación de Pocket ID
- arreglo de la migración para MariaDB 12.2.2
Código fuente
Accede a todo el código fuente de este artículo en GitHub.
Ver en GitHub