OAuth2 di base per Discourse

:discourse2: Sintesi Discourse OAuth2 Basic supporta provider OAuth2 di base, assumendo che dispongano di un endpoint API JSON dove è possibile recuperare i dettagli dell’utente tramite token.
:open_book: Guida all’installazione Questo plugin è incluso nel nucleo di Discourse. Non è necessario installarlo separatamente.

Funzionalità

Questo plugin ti consente di utilizzare un provider OAuth2 di base come metodo di autenticazione per Discourse. Dovrebbe funzionare con molti provider, con la precisazione che devono fornire un endpoint JSON per recuperare informazioni sull’utente che sta effettuando il login.

Ciò è principalmente utile per chi utilizza provider di login non molto diffusi. Se desideri utilizzare Google, Facebook o Twitter, questi sono già inclusi e non hai bisogno di questo plugin. Puoi anche cercare altri provider di login nel nostro repository Github.

Configurazione

Configurazione di base

  1. Prima di tutto, registra la tua applicazione Discourse presso il tuo provider OAuth2. Ti verrà richiesto un Redirect URI che sarà:

    http://DISCOURSE_HOST/auth/oauth2_basic/callback

:information_source: Sostituisci DISCOURSE_HOST con il valore appropriato e assicurati di utilizzare https se abilitato. Il provider OAuth2 dovrebbe fornirti un client ID e un secret, oltre a un paio di URL.

  1. Visita AdminImpostazioniLogin OAuth2 e compila la configurazione di base per il provider OAuth2:
  • oauth2_enabled - seleziona questa opzione per abilitare la funzionalità
  • oauth2_client_id - il client ID fornito dal tuo provider
  • oauth2_client_secret - il client secret fornito dal tuo provider
  • oauth2_authorize_url - l’URL di autorizzazione del tuo provider
  • oauth2_token_url - l’URL del token del tuo provider.

:information_source: Se non riesci a determinare i valori per le impostazioni sopra indicate, consulta la documentazione per sviluppatori del tuo provider o contatta il loro supporto clienti.

Configurazione dell’endpoint JSON per l’utente

Discourse è ora in grado di ricevere un token di autorizzazione dal tuo provider OAuth2. Purtroppo, Discourse richiede ulteriori informazioni per completare l’autenticazione.

È necessario un endpoint API a cui è possibile contattare per recuperare informazioni sull’utente in base al token.

Ad esempio, il provider OAuth2 SoundCloud fornisce un URL del genere. Se disponi di un token OAuth2 per SoundCloud, puoi effettuare una richiesta GET a https://api.soundcloud.com/me?oauth_token=A_VALID_TOKEN e riceverai un oggetto JSON contenente informazioni sull’utente.

Per configurare ciò su Discourse, dobbiamo impostare il valore dell’impostazione oauth2_user_json_url. In questo caso, inseriremo il valore:

https://api.soundcloud.com/me?oauth_token=:token

La parte con :token indica a Discourse che deve sostituire quel valore con il token di autorizzazione ricevuto al termine dell’autenticazione.

C’è un ultimo passo da completare. Dobbiamo indicare a Discourse quali attributi sono disponibili nel JSON ricevuto. Ecco un esempio di risposta da SoundCloud:

{
  "id": 3207,
  "permalink": "jwagener",
  "username": "Johannes Wagener",
  "uri": "https://api.soundcloud.com/users/3207",
  "permalink_url": "http://soundcloud.com/jwagener",
  "avatar_url": "http://i1.sndcdn.com/avatars-000001552142-pbw8yd-large.jpg?142a848",
  "country": "Germany",
  "full_name": "Johannes Wagener",
  "city": "Berlin"
}

Le variabili oauth2_json_user_id_path, oauth2_json_username_path, oauth2_json_name_path e oauth2_json_email_path devono essere impostate per puntare agli attributi appropriati nel JSON.

L’unico attributo obbligatorio è id - ne abbiamo bisogno affinché, quando l’utente effettuerà il login in futuro, possiamo recuperare l’account corretto. Gli altri sono utili se disponibili: accelereranno il processo di registrazione per l’utente poiché verranno precompilati nel modulo.

Ecco come ho configurato le impostazioni dei percorsi JSON:

  oauth2_json_user_id_path: 'id'
  oauth2_json_username_path: 'permalink'
  oauth2_json_name_path: 'full_name'

Ho utilizzato permalink perché sembra più simile a ciò che Discourse si aspetta per un nome utente rispetto al campo username nel loro JSON. Notate che ho omesso il percorso email: SoundCloud non fornisce un’email, quindi l’utente dovrà fornirla e verificarla al momento della prima registrazione su Discourse.

Se le proprietà che desideri dal tuo oggetto JSON sono nidificate, puoi utilizzare i punti. Quindi, ad esempio, se l’API restituisse una struttura diversa come questa:

{
  "user": {
    "id": 1234,
    "email": {
      "address": "test@example.com"
    }
  }
}

Potresti utilizzare user.id per oauth2_json_user_id_path e user.email.address per oauth2_json_email_path.

Se la chiave stessa include punti, dovrai racchiuderla tra virgolette doppie o escapare i punti con una barra rovesciata. Ad esempio, dato questo JSON:

{
  "example.com/uid": "myuid"
}

Dovresti specificare il percorso come example\.com/uid o "example.com/uid".

:warning: Se imposti oauth2_json_email_path, il provider OAuth2 deve confermare che l’utente possiede quell’indirizzo email. Il mancato rispetto di questa regola può portare al takeover dell’account su Discourse!

:discourse2: Ospitato da noi? Questo plugin è disponibile nei nostri piani Business e Enterprise. OAuth 2.0 & OpenID Connect Support | Discourse - Civilized Discussion

:spiral_notepad: Devi automatizzare le registrazioni degli utenti? Consulta Auto-provisioning user accounts when SSO is enabled

28 Mi Piace
Keycloak with Discourse
Discourse SSO with OAuth2
Login from another user database
Shopify Integration
How can we enable Auth0 SSO in Discourse
OAuth2 integration with Drupal
OAuth connection of discourse
Login flow (Flask -> Discourse -> Flask) with OAuth
How to use Oauth2 service provided by discourse?
How to login to discourse from external website
Is "partial" SSO possible?
Set up Salesforce auth using OAuth2 basic support plugin
How to force users link phone number when they using Discourse?
OAuth2 Custom Redirects Plugin
Custom Login / Registration from another API
Login on discourse using mastodon credentials
Open source will support customized provider SSO
Oauth2 with fusionauth cert issues
Migrate a Jive Clearspace forum to Discourse
Configure sign up and log in with Auth0 using the OAuth2 Basic Plugin
Error during SSO integration - Wholistic Minds
What is supposed to go in “DISCOURSE_HOST”?
Custom Provider log-in with OAuth only sign-up/log-in
Discord, Google and Microsoft login, is oAuth2 enough?
Populating email field on login page
CodeBerg support
Gate our community to just members of our Shopify site?
Intergrate Discourse with keycloak
Integration into custom auth system where emails are not unique?
Twitter login doesn't work on meta
Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso)
Question about Docker Manager?
Discourse OpenID Connect (OIDC)
🧩 How to Build an Android App User Community with Discourse? [HeyApks Project]
Bundling more popular plugins with Discourse core
Drupal 8 and Discourse shared SSO
Discourse for self hosting
Discourse + Intercom (Current User Id)
Auto-provisioning user accounts when SSO is enabled
ADFS Authentication
Pulling user auth0 sub from OAuth2.0 plugin
Suggestion for improving Integrated Authentication development
Github and Twitter Login/Sign-Up Functionality?
Automatically creating a user when logging in with Webflow/Memberspace
Switching out authentication for a passwordless alternative
Removing Yahoo login from Core, and deprecating OpenID 2.0
Shopify Integration
SSO with TownNews CMS
SSO and Auth0

Ciao,
Stiamo cercando di integrare Discourse con la nostra applicazione utilizzando OAuth2 Basic ma stiamo riscontrando il seguente errore nei log:
Nota: Stiamo utilizzando NGROK poiché stiamo eseguendo il debug della connessione.

OAuth2 Debugging: request POST https://formshare.ngrok.io/oauth2/token

Headers: {"User-Agent"=>"Faraday v1.9.3", "Content-Type"=>"application/x-www-form-urlencoded", "Authorization"=>"Basic S2k2SFZtTVpuSTFHUExiRXVlWVJDNENiOkNvb1k0anlQemt3dWNRV21Sa2FWOVNnbHZLbjJFT3cxc3BIMmtMck9yY21vNDM4Tg=="}

Body: {"client_id"=>"Ki6HVmMZnI1GPLbEueYRC4Cb", "client_secret"=>"...some_secret_...", "grant_type"=>"authorization_code", "code"=>"5pPCrsp0pZ84373MNaHh2cuskfc8AlbfmdwMBFIVW4n4z9aX", :redirect_uri=>"https://community.formshare.org/auth/oauth2_basic/callback"}

------------------

OAuth2 Debugging: response status 200

From POST https://formshare.ngrok.io/oauth2/token

Headers: {"content-length"=>"108", "content-type"=>"text/html; charset=UTF-8", "date"=>"Thu, 01 Sep 2022 21:42:08 GMT", "ngrok-trace-id"=>"79cdc3f1c3eae5e37a30796aebbf9bd6", "server"=>"gunicorn"}

Body: {"token_type": "Bearer", "access_token": "p0FVuwjSXL1ZINEklMAVqUlpZxSll1SgnbpE8YWP4C", "expires_in": 864000}

-----------------------------------

(oauth2_basic) Authentication failure! invalid_credentials: OAuth2::Error, {"token_type": "Bearer", "access_token": "p0FVuwjSXL1ZINEklMAVqUlpZxSll1SgnbpE8YWP4C", "expires_in": 864000}

Abbiamo lasciato vuoti i parametri “oauth2 callback user id path” e “oauth2 callback user info paths”.

Qualsiasi idea è apprezzata.

Posso usarlo per autenticarmi con il servizio XBL di Microsoft?

Presumo che la logica sarebbe simile a questa?

Ciao a tutti. Sto cercando di configurare questo plugin con il nostro server Oauth2 interno con il flusso di autorizzazione del codice.

Quando un utente fa clic su “Connetti con Oauth”, l’endpoint /authorize funziona e un codice viene restituito al callback. Ma poi Discourse mostra un errore generico 500 “Oops. Il software che alimenta questo forum di discussione ha riscontrato un problema imprevisto” e l’endpoint /token non viene raggiunto.

Il log degli errori dice così:
OAuth2::ConnectionError (FinalDestination: tutti gli IP risolti non erano consentiti) lib/final_destination/ssrf_detector.rb:74:in lookup_and_filter_ips' lib/final_destination/http.rb:13:in connect’ lib/midd

hostname discourse-app
process_id 653
application_version 702f27e6ee10ac257f5fee3f331d05f5fa5d7a45
HTTP_HOST *****
REQUEST_METHOD GET
HTTP_USER_AGENT Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
HTTP_REFERER *****
HTTP_X_FORWARDED_FOR *****
HTTP_X_REAL_IP *****
time 22:25
params
code def50200babf84f7376f99fefa34369d876566b6bc0a341d8fba431999a72549ac06f6aad01df6fa43061707c525ba5d725ad
state 20139e0a134a5972566d4ddb9e5216973a

Per quanto capisco, c’è un problema con qualche indirizzo IP? Attualmente il server Oauth2 è ospitato nel mio ambiente di sviluppo (localhost) e gli endpoint authorize e token sono configurati di conseguenza. È un problema?

Trovato il problema:

  1. Per qualche motivo, l’endpoint /token non è mai stato chiamato. Dopo aver impostato il massimo delle opzioni nei parametri di amministrazione relativi a oauth, l’endpoint è stato chiamato senza risposta.
  2. Ho dimenticato che sarebbe stato il server Discourse a chiamare l’endpoint /token e non il webclient. Pertanto, il server non poteva raggiungere il mio server Oauth2 localhost. Mettere il nostro server Oauth2 dietro un dominio ha risolto il problema.

Ora posso connettere utenti esistenti ma non capisco come accedere a nuovi utenti tramite questo plugin.
Se l’utente accede con oauth, riceve un errore che indica che non ha un account attivo sul server Discourse. Il che è normale dato che è un nuovo utente.

Esiste un callback dedicato per accedere all’utente invece di effettuare il login? O un parametro specifico da impostare per consentire la creazione dell’account?

Il mio server oauth aziendale generava una risposta JSON /profile con un piccolo errore di battitura in un campo. Tutto è andato bene dopo aver corretto l’errore di battitura.
Ma devo dire che i log di Discourse possono essere molto fuorvianti! Non c’era niente di sbagliato nel callback.

Ciao team,

Sto riscontrando un problema nell’estrazione dell’ID di cui ho bisogno per la mia richiesta JSON utente dalla risposta di autorizzazione. Leggendo la documentazione, sembra che l’ID dell’account venga inviato in un array nidificato:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
   "access_token":"2YotnFZFEjr1zCsicMWpAA",
   "token_type":"Bearer",
   "expires_in":1800,
   "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
   "permissions":[
      {
        "accountId":123,
        "availableScopes":["contacts_view", "contacts_me", 
"contacts_edit", "finances_view", "events_view"]
      }
   ]
}

Ho provato a impostare il percorso dell’ID utente della callback oauth2 su permissions[0].accountId, ma il mio valore uid è sempre vuoto. Sfortunatamente, le chiamate per estrarre il JSON utente richiedono questo accountId nell’URL JSON.

Sono riuscito a farlo funzionare passando permissions.first.accountId, ho scoperto che quando ho passato le autorizzazioni a una proprietà di test, l’array era già stato analizzato come un array Ruby. Sfortunatamente, i campi sembrano rifiutare la sintassi Ruby per chiamare gli elementi dell’array e qualsiasi tentativo di utilizzare la sintassi Javascript comporterebbe un TypeError String to Integer. Fortunatamente Ruby aveva la sintassi sopra, questo è il metodo previsto?

Ho appena fatto funzionare questo con Authentik OAuth2, tuttavia ci sono stati alcuni intoppi con l’impostazione oauth2 user json url. Ho usato l’endpoint user_info di Authentik per quello (/application/o/userinfo/), tuttavia non sapevo come mappare i campi. Per chiunque cerchi come configurare Discourse con OAuth2 di Authentik, ecco il riassunto:

  • Percorso ID utente: preferred_username
  • Percorso nome utente: preferred_username
  • Percorso nome: name
  • Percorso email: email
  • Percorso email verificata: email_verified
  • Avatar: vuoto.

Ho avuto i seguenti problemi:

  1. All’inizio, ho dimenticato lo slash finale nell’URL json https://DOMAIN/application/o/userinfo/. Questo ha portato la richiesta di informazioni utente (permalink alla sorgente) a restituire un codice HTTP 301, che ha causato il fallimento del login. Non so se lo slash finale debba esserci per specifica, ma forse sarebbe bene gestire correttamente il 301.
  2. Il debug di questo si è rivelato complicato. Le impostazioni oauth2 debug auth sono state una manna dal cielo ma… Logster tronca il log di debug prima di scaricare effettivamente i dati di risposta significativi. Ho dovuto modificare manualmente nel container la riga di log per
    log("user_json_response: #{user_json_response.status} #{user_json_response.headers} #{user_json_response.body}")
    
    Forse quella riga di log potrebbe essere aggiornata? Immagino che potrebbe aiutare altre persone a capire il percorso degli attributi json.
4 Mi Piace

Ho appena configurato Auth0 con il plugin e ho scoperto che gli avatar non vengono acquisiti.

Queste sono le impostazioni pertinenti:

  DISCOURSE_OAUTH2_ENABLED: true
  DISCOURSE_OAUTH2_CLIENT_ID: '${DISCOURSE_OAUTH2_CLIENT_ID}'
  DISCOURSE_OAUTH2_CLIENT_SECRET: '${DISCOURSE_OAUTH2_CLIENT_SECRET}'
  DISCOURSE_OAUTH2_AUTHORIZE_URL: '${DISCOURSE_OAUTH2_ISSUER}/authorize?connection=xxx&login_options=yyy'
  DISCOURSE_OAUTH2_TOKEN_URL: '${DISCOURSE_OAUTH2_ISSUER}/oauth/token'
  DISCOURSE_OAUTH2_USER_JSON_URL: '${DISCOURSE_OAUTH2_ISSUER}/userinfo'
  DISCOURSE_OAUTH2_SCOPE: 'email openid profile'
  DISCOURSE_OAUTH2_JSON_USER_ID_PATH: 'sub'
  DISCOURSE_OAUTH2_JSON_USERNAME_PATH: 'nickname'
  DISCOURSE_OAUTH2_JSON_NAME_PATH: 'name'
  DISCOURSE_OAUTH2_JSON_EMAIL_PATH: 'email'
  DISCOURSE_OAUTH2_JSON_EMAIL_VERIFIED_PATH: 'email_verified'
  DISCOURSE_OAUTH2_JSON_AVATAR_PATH: 'picture'
  DISCOURSE_OAUTH2_EMAIL_VERIFIED: true
  DISCOURSE_OAUTH2_OVERRIDES_EMAIL: true
  DISCOURSE_OAUTH2_ALLOW_ASSOCIATION_CHANGE: false

Nel log di debug posso vedere che l’elemento picture è impostato nella risposta JSON, ma l’avatar dell’utente non cambia, né per gli utenti nuovi né per quelli esistenti.

Cosa mi sono perso?

Qual è il modo migliore per sostituire l’icona sul pulsante di accesso con un’altra icona o un’immagine?

.btn-social.oauth2_basic:before {
    content: url('https://www.contoso.com/path/to/image');
}

.btn-social.oauth2_basic > svg {
    display: none;
}

sembra sufficiente ma un po’ macchinoso

2 Mi Piace

Sembra che il plugin aggiorni l’avatar/nome utente solo alla creazione iniziale dell’utente, non ogni volta che accede.

C’è un modo per risolvere questo problema e far sì che il plugin aggiorni anche l’avatar al login/riconnessione?

È possibile utilizzare le impostazioni auth overrides email, auth overrides username e auth overrides name per applicare tali modifiche ai futuri accessi. Temo che al momento non disponiamo di un’impostazione simile per gli avatar, ma sarebbe pr-welcome

2 Mi Piace

Grazie! In realtà li ho trovati più tardi. Ho fatto il fork del repository e ho aggiunto le mie versioni per farlo funzionare con Roblox, che includeva l’override per gli avatar. Che credo utilizzi solo l’override dell’avatar di DiscourseConnect in modo che le persone non possano cambiarlo.

Una cosa che vorrei però è che Roblox non fornisca un’email su OAuth, quindi purtroppo devo farli registrare con un’email. ma questo non è un problema per voi haha.

Un post è stato diviso in un nuovo argomento: Accesso a Twitter non funziona su meta

Qualcuno sa se funziona ancora?

Sì. Sono sicuro che questo plugin funzioni. :+1:

1 Mi Piace

Ciao, sono riuscito a integrare questo plugin nel mio discourse discuss.frontendlead.com, sto usando teachable oauth https://docs.teachable.com/docs/oauth-quickstart-guide

Tuttavia, voglio solo consentire alle persone di registrarsi con successo se e solo se hanno un account a pagamento corrente su teachable. Immaginerei che dovrei aggiungere funzionalità personalizzate nel plugin per gestire questo? Mi chiedo, potete voi o anche io, introdurre un altro campo nelle impostazioni chiamato codice personalizzato dopo oauth, che consente agli sviluppatori di eseguire azioni specifiche dopo la registrazione? O se ci sono suggerimenti migliori, per favore fatemelo sapere.

Modifica: ho forked il repository e l’ho fatto funzionare qui:

Se qualcun altro che usa teachable sta cercando di fare la stessa cosa, il mio repository funzionerà subito, l’unica cosa è che se non hai acquistato un corso, dirà che devi andare sul mio dominio per acquistarlo. potresti voler aggiornare questo per il tuo caso d’uso.

2 Mi Piace

Fantastico!

C’è una situazione simile con la registrazione OAuth2 con il plugin Discourse Patreon. Quando “Accedi con Patreon” è abilitato, consente a chiunque abbia un account Patreon di registrarsi sul sito Discourse. Ciò che i proprietari del sito generalmente desiderano è consentire solo ai loro sostenitori di potersi registrare account Discourse. Mi chiedo se i dettagli vengano restituiti da Patreon che consentirebbero di aggiungere una logica simile all’autenticazione Patreon?

1 Mi Piace

Ho lo stesso identico errore di @qlands sopra.

Il mio piano iniziale era di inviare le informazioni del profilo nel token. Vedendo che non ha funzionato, l’ho ridotto indentando per provare l’approccio JSON. Ma non arriva nemmeno al punto di chiamare il file JSON.

Il messaggio di errore è:

(oauth2_basic) Authentication failure! invalid_credentials: OAuth2::Error, {
  "access_token":"fa79b6fe0763862f5a8fd8",
  "token_type":"Bearer",
  "expires_in":3600,
  "scope":"profile"
}

Vedi qualcosa di sbagliato nella risposta sopra?
Perché il plugin genererebbe un errore invalid_credentials mentre il server OAuth2 ha risposto con un 200 con un token?