Guia rápido: qualquer biblioteca OIDC
O Usher é um fornecedor OpenID Connect normalizado. Se a sua linguagem tem um cliente OIDC certificado, já tem tudo o que precisa: aponte-o para o documento de descoberta do seu ambiente e use o fluxo de código de autorização com PKCE.
As definições
| Definição | Valor |
|---|---|
| Emissor | https://<handle>.usherid.com |
| URL de descoberta | https://<handle>.usherid.com/.well-known/openid-configuration |
| Fluxo | Código de autorização (response_type=code) |
| PKCE | Obrigatório, code_challenge_method=S256 |
| Âmbitos | openid profile email offline_access |
| Autenticação do cliente | Conforme indicado em token_endpoint_auth_methods_supported |
O identificador (handle) do seu ambiente está na Usher Console, ao lado do seu emissor. Os ambientes de desenvolvimento recebem um aleatório, como wise-otter-42; os ambientes de produção têm o identificador que escolheu. Em alternativa, um ambiente de produção pode ficar no seu próprio domínio, como login.acme.com: esse passa então a ser o seu emissor, depois de apontar o domínio para o Usher com um registo CNAME.
Leia o documento de descoberta
Todos os endpoints e chaves de que o seu cliente precisa estão aqui. Deixe que a sua biblioteca o leia, em vez de copiar URLs para o seu código.
curl -s https://acme.usherid.com/.well-known/openid-configuration | jq{
"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"]
}O fluxo
Envie a pessoa para o endpoint de autorização
Crie um verificador PKCE aleatório e guarde-o, com um state aleatório, num sítio a que só a sessão deste navegador tenha acesso (um cookie httpOnly de curta duração funciona bem). Depois, redirecione com response_type=code, o seu client_id e redirect_uri, os âmbitos acima, o state e o code_challenge S256 do seu verificador.
Deixe a pessoa iniciar sessão
A partir daqui, é com o Lobby: indica a sua app, oferece os métodos de início de sessão que o seu ambiente permite e pede consentimento da primeira vez.
Verifique o callback
O Usher redireciona para o seu redirect_uri com code e state. Recuse a resposta se o state não corresponder ao que guardou. O código é de utilização única e dura cinco minutos.
Troque o código por tokens
A partir do seu servidor, envie o código e o verificador PKCE para o endpoint 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"Valide o token de ID
Verifique a assinatura com as chaves em jwks_uri, e confirme que iss é o seu emissor, que aud é o seu ID de cliente e que exp está no futuro. A sua biblioteca faz isto por si; certifique-se de que não está desativado.
Em Node.js
O openid-client faz tudo o que está acima, incluindo a validação:
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()!Noutras linguagens
Estas bibliotecas, muito usadas, falam todas OpenID Connect normalizado e funcionam com o Usher sem nada específico do Usher:
| Linguagem | Biblioteca |
|---|---|
| Python | Authlib |
| Go | coreos/go-oidc com golang.org/x/oauth2 |
| Java | Spring Security OAuth 2.0 Client |
| .NET | Microsoft.AspNetCore.Authentication.OpenIdConnect |
| Ruby | omniauth_openid_connect |
| PHP | jumbojett/openid-connect-php |
Manter a sessão iniciada
Com o âmbito offline_access, a resposta de token inclui um token de atualização. Use-o com grant_type=refresh_token para obter um novo token de acesso quando o antigo expirar. Os tokens de atualização mudam: cada utilização devolve um novo, e o antigo deixa de funcionar.
Terminar a sessão
Limpe primeiro a sua própria sessão e depois redirecione para o end_session_endpoint com post_logout_redirect_uri (e id_token_hint, se o tiver), para que o Lobby também se esqueça da pessoa.