Snelstart: elke OIDC-bibliotheek
Usher is een standaard OpenID Connect-provider. Heeft je taal een gecertificeerde OIDC-client, dan heb je al alles wat je nodig hebt: richt die op het discovery-document van je omgeving en gebruik de autorisatiecodeflow met PKCE.
De instellingen
| Instelling | Waarde |
|---|---|
| Issuer | https://<handle>.usherid.com |
| Discovery-URL | https://<handle>.usherid.com/.well-known/openid-configuration |
| Flow | Autorisatiecode (response_type=code) |
| PKCE | Verplicht, code_challenge_method=S256 |
| Scopes | openid profile email offline_access |
| Clientauthenticatie | Zoals vermeld in token_endpoint_auth_methods_supported |
De handle van je omgeving staat in Usher Console, naast de issuer. Ontwikkelomgevingen krijgen een willekeurige handle, zoals wise-otter-42; productieomgevingen hebben de handle die je hebt gekozen. Een productieomgeving kan ook op je eigen domein staan, zoals login.acme.com: dan is dat de issuer, zodra je het domein met een CNAME-record naar Usher laat verwijzen.
Lees het discovery-document
Elk eindpunt en elke sleutel die je client nodig heeft, staat hierin. Laat je bibliotheek het lezen in plaats van URL’s in je code te kopiëren.
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"]
}De flow
Stuur de persoon naar het autorisatie-eindpunt
Maak een willekeurige PKCE-verifier en bewaar die, samen met een willekeurige state, op een plek die alleen de sessie van deze browser kan bereiken (een kortlevende httpOnly-cookie werkt goed). Stuur daarna door met response_type=code, je client_id en redirect_uri, de scopes hierboven, de state en de S256-code_challenge van je verifier.
Laat iemand inloggen
Vanaf hier neemt de Lobby het over: ze noemt je app, biedt de inlogmethoden die je omgeving toestaat, en vraagt de eerste keer om toestemming.
Controleer de callback
Usher stuurt door naar je redirect_uri met code en state. Weiger het antwoord, tenzij state overeenkomt met de waarde die je hebt bewaard. De code is eenmalig te gebruiken en vijf minuten geldig.
Ruil de code in voor tokens
Post vanaf je server de code en de PKCE-verifier naar het tokeneindpunt:
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"Valideer het ID-token
Controleer de handtekening tegen de sleutels op jwks_uri, en controleer of iss je issuer is, aud je client-ID en exp in de toekomst ligt. Je bibliotheek doet dit voor je; zorg dat het niet is uitgeschakeld.
In Node.js
openid-client doet al het bovenstaande, inclusief de validatie:
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()!In andere talen
Deze veelgebruikte bibliotheken spreken allemaal standaard OpenID Connect en werken met Usher zonder iets wat specifiek voor Usher is:
| Taal | Bibliotheek |
|---|---|
| Python | Authlib |
| Go | coreos/go-oidc met 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 |
Ingelogd blijven
Met de scope offline_access bevat het tokenantwoord een vernieuwingstoken. Gebruik het met grant_type=refresh_token om een nieuw toegangstoken te krijgen als het oude verloopt. Vernieuwingstokens roteren: elk gebruik levert een nieuw token op, en het oude werkt dan niet meer.
Uitloggen
Wis eerst je eigen sessie en stuur dan door naar het end_session_endpoint met post_logout_redirect_uri (en id_token_hint als je die hebt), zodat de Lobby de persoon ook vergeet.