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: con false, 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=true quita 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í:

  1. escribes tu correo en la web de Vaultwarden y pulsas Usar inicio de sesión único
  2. el navegador va a Pocket ID, que te pide la passkey y el consentimiento
  3. Pocket ID devuelve un código a https://tu_dominio/identity/connect/oidc-signin
  4. 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.crt en el contenedor y apunta SSL_CERT_FILE a é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 certutil para 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 de DOMAIN
  • PKCE: activado, a juego con SSO_PKCE=true en 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 único
  • SSO_AUTHORITY: la URL base del proveedor, sin /.well-known/openid-configuration; tiene que coincidir exactamente con el issuer del descubrimiento, barra final incluida o excluida
  • SSO_SCOPES: por defecto email profile; openid se añade solo
  • SSO_PKCE: activo por defecto desde que existe la opción
  • SSO_SIGNUPS_ALLOWED: nueva en la 1.37.3, decide si el SSO puede crear cuentas
  • SSO_ONLY: desactiva el login con correo y contraseña maestra
  • SSO_SIGNUPS_MATCH_EMAIL: por defecto true, 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=false y sin invitación, Vaultwarden rechazó el alta con Signups are disabled. You will need an invitation
  • después lo invité desde el panel /admin y 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.

Pantalla de inicio de sesión de Vaultwarden con SSO_ONLY activado: solo quedan el campo de correo y el botón de inicio de sesión único, sin la opción de entrar con contraseña maestra ni el enlace para crear cuenta.

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

  1. wiki de Vaultwarden sobre SSO
  2. notas de versión
  3. documentación de instalación de Pocket ID
  4. documentación de HTTPS automático de Caddy
  5. documentación de grupos permitidos de Pocket ID
  6. versión 1.37.3 de Vaultwarden
  7. código de identity.rs de la 1.37.3
  8. ejemplo de Vaultwarden en la documentación de Pocket ID
  9. arreglo de la migración para MariaDB 12.2.2