Ir al contenido

Flow de autenticación

Prysm:ID habla OIDC estándar (perfil OAuth 2.0 de OpenID Connect). Si tu librería favorita habla OIDC, habla con nosotros sin glue code propietario.

El flow estándar (Authorization Code + PKCE)

Sección titulada «El flow estándar (Authorization Code + PKCE)»

Es el flow recomendado para apps web, móviles y SPAs. Para apps puramente backend-to-backend usás client credentials (ver al final).

┌──────────┐ ┌────────────────────┐
│ Tu app │ │ auth.acme. │
│ (browser │ │ prysmid.com │
│ o BE) │ │ (instancia) │
└────┬─────┘ └─────────┬──────────┘
│ │
│ 1. usuario clic "Login" │
│ → redirect a /authorize │
│ con client_id, redirect_uri, │
│ scope=openid profile email, │
│ state, code_challenge (PKCE) │
├──────────────────────────────────────────────────▶│
│ │
│ 2. login UI: usuario ingresa email/pwd │
│ o elige IdP social (Google/GitHub) │
│ │
│ 3. instance autentica │
│ → redirect a redirect_uri │
│ con code + state │
│◀──────────────────────────────────────────────────┤
│ │
│ 4. POST /token │
│ code, code_verifier, client_id+secret │
├──────────────────────────────────────────────────▶│
│ │
│ 5. responde id_token (JWT) │
│ + access_token + refresh_token │
│◀──────────────────────────────────────────────────┤
│ │
│ 6. tu BE valida id_token con JWKS │
│ (verifica firma, aud, exp, iss) │
│ │

El id_token es un JWT firmado (RS256 por default). Decodificado, el payload típico:

{
"iss": "https://auth.acme.prysmid.com",
"sub": "294857293874598734",
"aud": "275893745987345987@my-saas-dev",
"exp": 1738000000,
"iat": 1737996400,
"auth_time": 1737996398,
"email": "fernando@ganemo.co",
"email_verified": true,
"name": "Fernando",
"preferred_username": "fernando"
}
  • sub: identificador estable del usuario en tu workspace. Persistilo. No uses email como clave — los emails cambian.
  • iss: el issuer. Debe ser exactamente https://auth.<slug>.prysmid.com. Si validás contra otro string, vas a aceptar tokens forjados.
  • aud: tu client_id. Si recibís un token con aud distinto al tuyo, lo rechazás.

Cómo validar el JWT en tu backend →

ScopeQué te da
openidObligatorio. Sin esto no recibís id_token.
profilename, preferred_username, picture.
emailemail, email_verified.
offline_accessTe devuelve refresh_token para sesiones largas.
urn:zitadel:iam:org:project:rolesRoles del usuario en el project asociado a tu app. (Es la URN canónica del claim, no la cambies en tu validador.)

Si pediste offline_access, recibís un refresh_token además del id_token. Lo intercambiás por un nuevo id_token cuando el actual expira:

Ventana de terminal
curl -X POST https://auth.acme.prysmid.com/oauth/v2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=refresh_token" \
-d "refresh_token=$REFRESH_TOKEN"

El refresh token rota en cada uso. Guardá el nuevo, descartá el viejo.

Si tu app llama a otra app sin un humano detrás (machine-to-machine), usás client_credentials:

Ventana de terminal
curl -X POST https://auth.acme.prysmid.com/oauth/v2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=client_credentials" \
-d "scope=openid"

No vas a recibir id_token (no hay usuario), solo access_token. Ver también machine keys para agentes si lo que querés es que un agente IA opere el plano de control.

GET https://auth.acme.prysmid.com/oidc/v1/end_session
?id_token_hint=<id_token>
&post_logout_redirect_uri=https://yourapp.com/logout

El post_logout_redirect_uri debe estar registrado en tu app. La instance termina la sesión en su lado, después rebota a tu URI.