Ir al contenido
Documentación · Cualquier biblioteca OIDC

Inicio rápido: cualquier biblioteca OIDC

Usher es un proveedor estándar de OpenID Connect. Si tu lenguaje tiene un cliente OIDC certificado, ya tienes todo lo que necesitas: apúntalo al documento de descubrimiento de tu entorno y usa el flujo de código de autorización con PKCE.

La configuración

ParámetroValor
Emisorhttps://<handle>.usherid.com
URL de descubrimientohttps://<handle>.usherid.com/.well-known/openid-configuration
FlujoCódigo de autorización (response_type=code)
PKCEObligatorio, code_challenge_method=S256
Alcancesopenid profile email offline_access
Autenticación del clienteSegún token_endpoint_auth_methods_supported

El identificador de tu entorno aparece en Usher Console, junto a su emisor. Los entornos de desarrollo reciben uno aleatorio, como wise-otter-42; los de producción tienen el que elegiste. Un entorno de producción también puede estar en tu propio dominio, como login.acme.com: en ese caso, ese es su emisor, una vez que apuntes el dominio a Usher con un registro CNAME.

Lee el documento de descubrimiento

Aquí aparecen todos los endpoints y las claves que necesita tu cliente. Deja que tu biblioteca lo lea, en lugar de copiar URL en tu código.

Terminal
curl -s https://acme.usherid.com/.well-known/openid-configuration | jq
Respuesta (resumida)
{
  "issuer": "https://acme.usherid.com",
  "authorization_endpoint": "https://acme.usherid.com/api/auth/oauth2/authorize",
  "token_endpoint": "https://acme.usherid.com/api/auth/oauth2/token",
  "userinfo_endpoint": "https://acme.usherid.com/api/auth/oauth2/userinfo",
  "jwks_uri": "https://acme.usherid.com/api/auth/jwks",
  "introspection_endpoint": "https://acme.usherid.com/api/auth/oauth2/introspect",
  "revocation_endpoint": "https://acme.usherid.com/api/auth/oauth2/revoke",
  "end_session_endpoint": "https://acme.usherid.com/api/auth/oauth2/end-session",
  "scopes_supported": ["openid", "profile", "email", "offline_access"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
  "code_challenge_methods_supported": ["S256"]
}

El flujo

Envía a la persona al endpoint de autorización

Crea un verificador PKCE aleatorio y guárdalo, junto con un state aleatorio, en un lugar al que solo pueda acceder la sesión de este navegador (una cookie httpOnly de corta duración funciona bien). Luego redirige con response_type=code, tu client_id y tu redirect_uri, los alcances de arriba, el state y el code_challenge S256 de tu verificador.

Deja que inicie sesión

A partir de aquí se encarga el Lobby: muestra el nombre de tu app, ofrece los métodos de inicio de sesión que permite tu entorno y pide el consentimiento la primera vez.

Comprueba el callback

Usher redirige a tu redirect_uri con code y state. Rechaza la respuesta a menos que el state coincida con el que guardaste. El código es de un solo uso y dura cinco minutos.

Cambia el código por tokens

Desde tu servidor, envía el código y el verificador PKCE al endpoint de tokens:

Solicitud de token
curl -s -X POST https://acme.usherid.com/api/auth/oauth2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=authorization_code \
-d code="$CODE" \
-d redirect_uri=https://app.acme.example/callback \
-d code_verifier="$CODE_VERIFIER"

Valida el token de ID

Comprueba su firma con las claves de jwks_uri, y que iss sea tu emisor, aud sea tu ID de cliente y exp esté en el futuro. Tu biblioteca lo hace por ti; asegúrate de que esa comprobación no esté desactivada.

En Node.js

openid-client hace todo lo anterior, validación incluida:

openid-client
import * as client from 'openid-client'

// discovery: every endpoint and key comes from the issuer
const config = await client.discovery(
  new URL('https://acme.usherid.com'),
  process.env.USHER_CLIENT_ID!,
  process.env.USHER_CLIENT_SECRET!,
)

// 1. send them to the Lobby, with PKCE (S256) and a state to check later
const codeVerifier = client.randomPKCECodeVerifier()
const state = client.randomState()
const url = client.buildAuthorizationUrl(config, {
  redirect_uri: 'https://app.acme.example/callback',
  scope: 'openid profile email offline_access',
  code_challenge: await client.calculatePKCECodeChallenge(codeVerifier),
  code_challenge_method: 'S256',
  state,
})
// keep codeVerifier and state in a short-lived httpOnly cookie, then redirect to url

// 2. back at /callback: swap the code for tokens
const tokens = await client.authorizationCodeGrant(config, new URL(request.url), {
  pkceCodeVerifier: codeVerifier,
  expectedState: state,
})
const { sub, email, name } = tokens.claims()!

En otros lenguajes

Estas bibliotecas de uso extendido hablan OpenID Connect estándar y funcionan con Usher sin nada específico de Usher:

LenguajeBiblioteca
PythonAuthlib
Gocoreos/go-oidc con golang.org/x/oauth2
JavaSpring Security OAuth 2.0 Client
.NETMicrosoft.AspNetCore.Authentication.OpenIdConnect
Rubyomniauth_openid_connect
PHPjumbojett/openid-connect-php

Mantener la sesión iniciada

Con el alcance offline_access, la respuesta de tokens incluye un token de actualización. Úsalo con grant_type=refresh_token para obtener un nuevo token de acceso cuando venza el anterior. Los tokens de actualización rotan: cada uso devuelve uno nuevo, y el anterior deja de funcionar.

Cerrar sesión

Primero borra tu propia sesión y luego redirige al end_session_endpoint con post_logout_redirect_uri (y id_token_hint, si lo tienes), para que el Lobby también olvide a la persona.