Vai al contenuto
Documentazione · Qualsiasi libreria OIDC

Guida rapida: qualsiasi libreria OIDC

Usher è un provider OpenID Connect standard. Se il tuo linguaggio ha un client OIDC certificato, hai già tutto ciò che ti serve: indirizzalo al documento di discovery del tuo ambiente e usa il flusso del codice di autorizzazione con PKCE.

Le impostazioni

ImpostazioneValore
Issuerhttps://<handle>.usherid.com
URL di discoveryhttps://<handle>.usherid.com/.well-known/openid-configuration
FlussoCodice di autorizzazione (response_type=code)
PKCEObbligatorio, code_challenge_method=S256
Ambitiopenid profile email offline_access
Autenticazione del clientCome indicato in token_endpoint_auth_methods_supported

L’handle del tuo ambiente si trova in Usher Console, accanto al suo issuer. Gli ambienti di sviluppo ne ricevono uno casuale, come wise-otter-42; gli ambienti di produzione hanno l’handle che hai scelto. Un ambiente di produzione può risiedere invece su un tuo dominio, come login.acme.com: in quel caso è quello il suo issuer, dopo che hai puntato il dominio verso Usher con un record CNAME.

Leggi il documento di discovery

Qui sono elencati tutti gli endpoint e le chiavi di cui ha bisogno il tuo client. Lascia che sia la tua libreria a leggerlo, invece di copiare gli URL nel tuo codice.

Terminale
curl -s https://acme.usherid.com/.well-known/openid-configuration | jq
Risposta (abbreviata)
{
  "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"]
}

Il flusso

Manda la persona all’endpoint di autorizzazione

Genera un verifier PKCE casuale e conservalo, insieme a uno state casuale, in un posto raggiungibile solo dalla sessione di questo browser (un cookie httpOnly di breve durata va benissimo). Poi reindirizza con response_type=code, il tuo client_id e il tuo redirect_uri, gli ambiti indicati sopra, lo state e la code_challenge S256 del tuo verifier.

Lascia che acceda

Da qui ci pensa la Lobby: indica la tua app, offre i metodi di accesso che il tuo ambiente consente e, la prima volta, chiede il consenso.

Verifica il callback

Usher reindirizza al tuo redirect_uri con code e state. Rifiuta la risposta se lo state non corrisponde a quello che hai salvato. Il codice è monouso e dura cinque minuti.

Scambia il codice con i token

Dal tuo server, invia con una POST il codice e il verifier PKCE all’endpoint del token:

Richiesta di 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"

Convalida il token ID

Verifica la sua firma con le chiavi al jwks_uri, e controlla che iss sia il tuo issuer, che aud sia il tuo client ID e che exp sia nel futuro. La tua libreria lo fa al posto tuo; assicurati che questa verifica non sia disattivata.

In Node.js

openid-client fa tutto quanto descritto sopra, compresa la convalida:

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()!

In altri linguaggi

Queste librerie molto diffuse parlano tutte OpenID Connect standard e funzionano con Usher senza nulla di specifico per Usher:

LinguaggioLibreria
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

Mantenere l’accesso

Con l’ambito offline_access, la risposta del token include un token di aggiornamento. Usalo con grant_type=refresh_token per ottenere un nuovo token di accesso quando quello vecchio scade. I token di aggiornamento cambiano a ogni uso: ogni utilizzo ne restituisce uno nuovo, e quello vecchio smette di funzionare.

Uscire

Prima cancella la tua sessione, poi reindirizza all’end_session_endpoint con post_logout_redirect_uri (e id_token_hint, se lo hai), così anche la Lobby dimentica la persona.