Continuando da Future Social Authentication Improvements…
Stiamo ora procedendo alla migrazione di tutte le informazioni di ‘account associato’ in un’unica tabella di database. Questo aiuterà a ridurre significativamente la logica duplicata e consentirà uno sviluppo più rapido in futuro. Ad esempio, la migrazione della nostra logica principale di Twitter al nuovo sistema ha ridotto il numero di righe di codice da 136 a sole 24
.
Questo post non è concepito come un manuale di istruzioni passo passo per aggiungere un nuovo provider di autenticazione, ma mira a fornire una panoramica, indicando il codice sorgente pertinente ove necessario.
Implementazione di un autenticatore
Ogni autenticatore deve implementare una sottoclasse di Auth::Authenticator. Per utilizzare la nuova logica condivisa, l’autenticatore può invece estendere Auth::ManagedAuthenticator. Un esempio di implementazione di base si trova nell’autenticatore Facebook principale:
Le classi che implementano devono sovrascrivere name, enabled? e register_middleware.
Nota a margine: per la compatibilità multisito, è importante che qualsiasi informazione specifica del sito venga fornita a omniauth in una lambda
setup, anziché essere fissa al momento della definizione. Vedi tutti gli autenticatori principali per esempi di questo.
Tutta la logica per collegare gli account esterni agli account Discourse è gestita da Auth::ManagedAuthenticator. Questo si basa sul provider omniauth che restituisce dati nel formato definito nella loro documentazione. Se è necessaria una qualsiasi manipolazione di questi dati, gli autenticatori possono sovrascrivere il metodo after_authenticate e manipolare il token di autenticazione come richiesto. Ad esempio, l’autenticatore Twitter principale rimuove tutte le informazioni extra dal token:
I dati vengono memorizzati nella tabella del database user_associated_accounts. provider_uid, info, credentials ed extra vengono presi direttamente dai dati restituiti da omniauth.
Una volta definita una classe Authenticator, deve essere registrata. Ciò deve avvenire all’inizio del ciclo di vita dell’applicazione e non può avvenire all’interno del metodo after_initialize di un plugin. La registrazione minima può contenere semplicemente un riferimento all’autenticatore. In un plugin, la registrazione può essere eseguita utilizzando la funzione auth_provider. Ad esempio:
auth_provider authenticator: OpenIDConnectAuthenticator.new()
Nel codice principale, la registrazione avviene in discourse.rb. Un elenco completo delle possibili opzioni AuthProvider è disponibile qui. Il contenuto testuale può essere definito utilizzando queste opzioni, ma è preferibile fornire stringhe localizzabili in client.en.yml seguendo le chiavi standard. Ad esempio:
Note aggiuntive su ManagedAuthenticator di @fantasticfears
ManagedAuthenticator in dettaglio
Potrebbe essere necessario lavorare su qualcosa di speciale per l’autenticazione. E potresti voler sapere di più su ManagedAuthenticator. In sostanza, ha diverse operazioni, opzioni e controlla come verranno utilizzati i dati.
Discourse gestisce le informazioni utente con due controller. Users::OmniauthCallbacksController gestisce il payload una volta completata l’autenticazione OAuth2. after_authenticate viene chiamato qui. Anche can_connect_existing_user? viene utilizzato qui.
Ci sono alcuni metodi privati che puoi leggere per capire come funzionano i diversi campi dati.
if authenticator.can_connect_existing_user? && current_user
@auth_result = authenticator.after_authenticate(auth, existing_account: current_user)
else
@auth_result = authenticator.after_authenticate(auth)
end
UsersController ha revoke_account che utilizza can_revoke? e revoke. Ma affinché il metodo revoke funzioni da remoto, devi creare la tua implementazione.
UserAuthenticator è una classe di servizio che aiuta ad autenticare (verificando la conferma dell’email o il percorso OAuth2) gli utenti. after_create_account viene chiamato qui.
La logica principale rimane in after_authenticate con la classe dati Auth::Result. Seguiamo la struttura dei dati qui. extra_data verrà passato a after_create_account per la creazione di record correlati.
result.extra_data = {
provider: auth_token[:provider],
uid: auth_token[:uid],
info: auth_token[:info],
extra: auth_token[:extra],
credentials: auth_token[:credentials]
}
Tenterà di trovare e collegare un account esistente.
Potresti chiederti perché la creazione automatica dell’account è possibile ma non c’è User.create. Questo viene fatto in UsersController#create.
authentication = UserAuthenticator.new(user, session)
L’utente è una nuova istanza che verrà popolata dai dati di sessione preparati dal provider di autenticazione. Fidati, è solo magia.
Migrazione al nuovo sistema
Per fornire un passaggio senza interruzioni al nuovo sistema, i dati dovrebbero essere migrati dalla vecchia posizione di archiviazione. Per i provider di autenticazione principali, questa potrebbe essere una tabella dedicata. Per i plugin, potrebbe essere plugin_store_rows o oauth2_user_infos. I dati minimi richiesti in una riga di user_associated_accounts sono provider_name, provider_uid e user_id. Per un esempio di migrazione vedere:
Una volta che il sistema ManagedAuthenticator sarà rilasciato sul ramo stabile con la v2.2.0, inizieremo a migrare i plugin di autenticazione ufficiali. A quel punto, un esempio di migrazione di plugin_store_row verrà aggiunto qui.
Questo documento è controllato tramite versione - suggerisci modifiche su github.