Implementa un semplice SDK OIDC lato client
Logto offre una varietà di SDK per diverse piattaforme. Oltre ai nostri SDK ufficiali, incoraggiamo gli sviluppatori della comunità a creare i propri SDK user-friendly. Questo articolo ti guiderà nella costruzione di un SDK base lato client per OIDC.
Introduzione
Logto fornisce ai nostri sviluppatori e gruppi aziendali una soluzione completa di gestione dell'identità e dell'accesso del cliente (CIAM). Forniamo una vasta gamma di SDK pronti all'uso per diverse piattaforme e framework di applicazioni. Combinato con il nostro servizio cloud Logto, è possibile stabilire facilmente un flusso di autorizzazione utente altamente sicuro per la tua applicazione in pochi minuti. In quanto azienda che è nata dalla comunità degli sviluppatori, Logto abbraccia e valorizza il nostro coinvolgimento della comunità. Oltre a quelli sviluppati ufficialmente da Logto SDK, continuiamo a incoraggiare e dare il benvenuto calorosamente agli sviluppatori della comunità a contribuire con la loro competenza creando SDK più diversi e user-friendly, soddisfacendo le esigenze uniche di varie piattaforme e framework. In questo articolo, dimostreremo brevemente come implementare un SDK di autenticazione standard OIDC passo dopo passo.
Contesto
Il flusso OpenID Connect (OIDC) è un protocollo di autenticazione che si basa sul framework OAuth 2.0 per fornire la verifica dell'identità e le capacità di single sign-on. Permette agli utenti di autenticarsi con un'applicazione e ottenere l'autorizzazione per ulteriori accessi a qualsiasi risorsa privata in modo sicuro. Si prega di fare riferimento alle specifiche OIDC per ulteriori dettagli.
Flusso di lavoro
Un flusso standard di codice di autorizzazione include i seguenti passaggi:
Flusso di autenticazione
- L'utente avvia la richiesta di accesso: Un utente anonimo arriva all'applicazione da un'entrata pubblica. Cerca di ottenere l'autenticazione e forse ulteriori richieste per accedere a una risorsa protetta su un'applicazione o servizio di terze parti.
- Autenticazione dell'utente: L'app client genera un URI di autenticazione e invia una richiesta al server di autorizzazione, che reindirizza l'utente alla sua pagina di accesso. L'utente interagisce con la pagina di accesso utilizzando una vasta gamma di metodi di accesso e viene autenticato dal server di autorizzazione.
- Gestisci il callback di accesso: Dopo un'autenticazione di successo, l'utente verrà reindirizzato di nuovo alla tua applicazione con un
authorization_code
concesso. Questoauthorization_code
contiene tutte le autorizzazioni pertinenti legate allo stato di autenticazione e ai dati di autorizzazione richiesti. - Scambio token: Richiesta per lo scambio di token utilizzando l'
authorization_code
estratto dal sopra indirizzo di reindirizzamento. In cambio:id_token
: Un JWT firmato digitalmente che contiene informazioni sull'identità dell'utente autenticato.access_token
: Unaccess_token
opaco che può essere utilizzato per accedere all'endpoint delle informazioni dell'utente di base.refresh_token
: Token di credenziale che permette all'utente di mantenere uno scambio continuo per unaccess_token
Flusso di autorizzazione
- Accesso alle informazioni dell'utente: Per accedere a più informazioni sull'utente, l'applicazione può effettuare ulteriori richieste all'endpoint UserInfo, utilizzando l'
access_token
opaco ottenuto dal flusso di scambio di token iniziale. Questo permette di recuperare ulteriori dettagli sull'utente, come il suo indirizzo email o la foto del profilo. - Concessione dell'accesso alla risorsa protetta: Se necessario, l'applicazione può effettuare ulteriori richieste all'endpoint di scambio token, utilizzando il
refresh_token
combinato con i parametriresource
escope
, per ottenere unaccess_token
dedicato per l'utente per accedere alla risorsa target. Questo processo risulta nell'emissione di unaccess_token
in formato JWT contenente tutte le informazioni di autorizzazione necessarie per accedere alla risorsa protetta.
Implementazione
Seguiremo alcune strategie di progettazione all'interno del nostro SDK JavaScript @logto/client per dimostrare il processo di implementazione di un semplice SDK per la tua applicazione client. Tieni presente che la struttura del codice dettagliata può variare a seconda del framework client con cui stai lavorando. Sentiti libero di scegliere uno qualsiasi degli SDK ufficiali di Logto come esempio per il tuo progetto di SDK.
Anteprima
Costruttore
Il costruttore dovrebbe prendere un logtoConfig come input. Questo fornisce tutte le configurazioni necessarie di cui avrai bisogno per stabilire una connessione di autenticazione attraverso questo SDK.
A seconda della piattaforma o del framework che stai utilizzando per l'SDK, potresti passare un'istanza di memoria locale persistente al costruttore. Questa istanza di stoccaggio sarà utilizzata per memorizzare tutti i token e i segreti relativi all'autorizzazione.
Inizializza l'autenticazione dell'utente
Prima di generare un URL di richiesta di autenticazione, è essenziale completare diverse fasi di preparazione per garantire un processo sicuro.
Prendi le configurazioni OIDC dal server di autorizzazione
Definisci un metodo privato `getOidcConfigs`` per recuperare le configurazioni OIDC dal punto di scoperta del server di autorizzazione. La risposta delle configurazioni OIDC contiene tutte le informazioni sui metadati che il client può utilizzare per interagire con il server di autorizzazione, compresi i suoi punti di accesso e le capacità del server. (Si prega di fare riferimento a OAuth OAuth Authorization Server Metadata Specs per ulteriori dettagli.)
Generatore PKCE
Un flusso di validazione PKCE(Proof Key for Code Exchange) è essenziale per tutti i flussi di scambio di codice di autorizzazione del client pubblico. Mitiga il rischio di attacco di intercettazione dell'authorization_code. Così un code_challenge
e un code_verifier
sono richiesti per tutte le richieste di autorizzazione del client pubblico (ad es. app native e SPA).
I metodi di implementazione possono variare a seconda delle lingue e dei framework che stai utilizzando. Si prega di fare riferimento alla specifica code_challenge e code_verifier per le definizioni dettagliate.
Genera parametro dello stato
Nel flusso di autorizzazione, il parametro dello stato è un valore generato casualmente che viene incluso nella richiesta di autorizzazione inviata dal client. Funziona come una misura di sicurezza per prevenire gli attacchi di falsificazione di richieste inter-siti (CSRF).
Memorizza le informazioni della sessione intermedia
Ci sono diversi parametri che devono essere preservati nello storage per scopo di convalida dopo che l'utente ottiene l'autenticazione e viene reindirizzato nuovamente lato client. Stiamo per implementare un metodo per impostare quei parametri intermedi nello storage.
Accesso
Riassumiamo tutto ciò che abbiamo implementato sopra, definiamo un metodo che genera un URL di accesso per l'utente e reindirizza l'utente al server di autorizzazione per ottenere l'autenticazione.
Gestisci il callback di accesso dell'utente
Nella sezione precedente, abbiamo creato un metodo di accesso che genera un URL per l'autenticazione dell'utente. Questo URL contiene tutti i parametri richiesti necessari per avviare un flusso di autenticazione da un'app client. Il metodo reindirizza l'utente alla pagina di accesso del server di autorizzazione per l'autenticazione. Dopo un accesso di successo, l'utente finale verrà reindirizzato di nuovo alla posizione redirect_uri fornita sopra. Tutti i parametri necessari saranno portati nel redirect_uri per completare i seguenti flussi di scambio token.
Estrai e verifica l'URL di callback
Questo passaggio di convalida è estremamente importante per prevenire qualsiasi forma di attacchi di callback di autorizzazione falsificati. L'URL di callback DEVE essere attentamente verificato prima di inviare una ulteriore richiesta di scambio di codice al server di autorizzazione. Prima di tutto, dobbiamo recuperare i dati signInSession che abbiamo memorizzato dal deposito dell'app.
Poi verifica i parametri dell'URL di callback prima di inviare la richiesta di scambio token.
- Utilizza il
redirectUri
memorizzato in precedenza per verificare se ilcallbackUri
corrisponde a quello che abbiamo inviato al server di autorizzazione. - Utilizzare lo stato memorizzato in precedenza per verificare se lo stato restituito corrisponde a quello che abbiamo inviato al server di autorizzazione.
- Verifica se è riportato un errore dal server di autorizzazione
- Verifica l'esistenza del
authorization_code
restituito
Invia la richiesta di scambio di codice
Come passaggio finale del flusso di autenticazione dell'utente, utilizzeremo il authorization_code
restituito per inviare una richiesta di scambio di token e ottenere i token di autorizzazione richiesti. Per ulteriori dettagli sulle definizioni dei parametri della richiesta, si prega di fare riferimento alla specifica di scambio token.
- code: l'
authorization_code
che abbiamo ricevuto dall'URI di callback - clientId: l'ID dell'applicazione
- redirectUri: Lo stesso valore utilizzato durante la generazione dell'URL di accesso per l'utente.
- codeVerifier: Verificatore di codice PKCE. Simile al redirectUri, il server di autorizzazione confronterà questo valore con quello che abbiamo inviato in precedenza, assicurando la convalida della richiesta di scambio di token in entrata.
Gestisci il callback di accesso
Riassumendo tutto quello che abbiamo. Costruiamo il metodo di gestione del callback di accesso:
Di conseguenza, la richiesta di scambio di token restituirà i seguenti token:
id_token
: OIDC idToken, un token Web JSON (JWT) che contiene informazioni sull'identità dell'utente autenticato. id_token può anche essere utilizzato come Single Source of Truth(SSOT) dello stato di autenticazione dell'utente.access_token
: Il codice di autorizzazione predefinito restituito dal server di autorizzazione. Può essere utilizzato per chiamare l'endpoint delle informazioni dell'utente e recuperare le informazioni dell'utente autenticato.refresh_token
: (se la portata offline_access è presente nella richiesta di autorizzazione): Questo token di aggiornamento consente all'applicazione client di ottenere un nuovo token di accesso senza richiedere all'utente di autenticarsi nuovamente, concedendo l'accesso a lungo termine alle risorse.expires_in
: La durata del tempo, in secondi, per la quale il token di accesso è valido prima che scada.
Verifica del token ID
La verifica e l'estrazione delle affermazioni dal id_token
è un passaggio cruciale nel processo di autenticazione per garantire l'autenticità e l'integrità del token. Ecco i passaggi chiave coinvolti nella verifica di un idToken
.
- Verifica della firma: L'
id_token
è firmato digitalmente dal server di autorizzazione utilizzando la sua chiave privata. L'applicazione client deve convalidare la firma utilizzando la chiave pubblica del server di autorizzazione. Ciò garantisce che il token non sia stato manomesso ed è stato effettivamente emesso dal server di autorizzazione legittimo. - Verifica dell'emittente**:** Controlla che la affermazione "iss" (emittente) nel
id_token
corrisponda al valore atteso, indicando che il token è stato emesso dal corretto server di autorizzazione. - Verifica del pubblico: Assicurati che la affermazione "aud" (pubblico) nel
id_token
corrisponda all'ID del client dell'applicazione client, garantendo che il token sia destinato al client - Controllo della scadenza: verifica che la affermazione "iat" (emessa a) nel
id_token
non sia passata rispetto all'orario attuale, garantendo che il token sia ancora valido. Dato che ci sono costi di transazione della rete è necessario impostare una tolleranza del tempo emesso durante la convalida della affermazione iat del token ricevuto.
Il token id_token restituito è un token Web JSON (JWT) standard. A seconda del framework che stai utilizzando, puoi trovare vari comodi plugin di convalida del token JWT per assistere nella decodifica e convalida del token. Per questo esempio, utilizzeremo jose nel nostro SDK JavaScript per facilitare la convalida e la decodifica del token.
Ottieni le informazioni dell'utente
Dopo un'autenticazione dell'utente di successo, le informazioni di base dell'utente possono essere recuperate dal id_token
OIDC emesso dal server di autorizzazione. Tuttavia, a causa di considerazioni sulle prestazioni, il contenuto del token JWT è limitato. Per ottenere informazioni più dettagliate sul profilo utente, i server di autorizzazione compatibili con OIDC offrono un endpoint utente info fuori dagli schemi. Questo endpoint consente di recuperare ulteriori dati del profilo utente effettuando richieste specifiche delle ambiti del profilo utente.
Quando si chiama un endpoint di scambio di token senza indicare una risorsa API specifica, il server di autorizzazione rilascerà, di default, un access_token
di tipo opaco. Questo access_token
può essere utilizzato solo per accedere all'endpoint delle informazioni dell'utente, consentendo il recupero dei dati di base del profilo utente.
Ottieni il token di accesso per l'autorizzazione delle risorse protette
Nella maggior parte dei casi, un'applicazione client non solo richiede l'autenticazione dell'utente, ma ha anche bisogno dell'autorizzazione dell'utente per accedere a certe risorse protette o a endpoint API. Qui, utilizzeremo il refresh_token
ottenuto durante il login per acquisire access_token
specificamente concesso per gestire particolari risorse. Questo ci permette di ottenere l'accesso a quelle API protette.
Sommario
Abbiamo fornito implementazioni di metodo essenziali per il processo di autenticazione e autorizzazione dell'utente dell'app lato client. A seconda del tuo scenario specifico, puoi organizzare e ottimizzare la logica dell'SDK di conseguenza. Si prega di notare che possono esistere variazioni a causa di diverse piattaforme e framework.
Per ulteriori dettagli, esplora i pacchetti SDK offerti da Logto. Incoraggiamo più utenti a partecipare allo sviluppo e a impegnarsi in discussioni con noi. Il tuo feedback e i tuoi contributi sono molto apprezzati mentre continuiamo a migliorare e ampliare le capacità dell'SDK.
Appendice
Ambiti riservati
Ambiti riservati da Logto che avrai bisogno di passare durante la richiesta di auth iniziale. Questi ambiti sono sia riservati da OIDC sia da Logto per completare un flusso di autorizzazione di successo.
Nome ambito | Descrizione |
---|---|
openid | Richiesto per concedere id_token dopo un'autenticazione di successo. |
offline-access | Richiesto per concedere un refresh_token che permette alla tua applicazione client di scambiare e rinnovare un access_token senza lo schermo dell'utente. |
profile | Richiesto per ottenere l'accesso alle informazioni basiche dell'utente |
Configurazione Logto
Nome proprietà | Tipo | Obbligatorio | Descrizione | Valore predefinito |
---|---|---|---|---|
appId | stringa | true | L'identificatore unico dell'applicazione. Generato dal server di autorizzazione per identificare l'applicazione client. | |
appSecret | stringa | Il segreto dell'applicazione è usato, insieme all'ID dell'applicazione, per verificare l'identità del richiedente. È richiesto per i client confidenziali come le app web Go o le app web Next.js, e opzionale per i client pubblici come le applicazioni native o single-page (SPA) | ||
endpoint | stringa | true | Il tuo endpoint radice del server di autorizzazione. Questa proprietà sarà ampiamente utilizzata per generare richieste di autorizzazione. | |
scopes | lista di stringhe | Indica tutti gli ambiti di risorsa necessari che l'utente potrebbe dover concedere per accedere a qualsiasi risorsa protetta data. | [reservedScopes] | |
resources | lista di stringhe | Tutti gli indicatori di risorsa protetta che l'utente potrebbe richiedere l'accesso |