Discourse OAuth2 di base

:discourse2: Summary Discourse OAuth2 Basic supports basic OAuth2 providers, assuming they have a JSON API endpoint where user details can be retrieved by token.
:open_book: Install Guide This plugin is bundled with Discourse core. There is no need to install the plugin separately.

Features

This plugin allows you to use a basic OAuth2 provider as authentication for Discourse. It should work with many providers, with the caveat that they must provide a JSON endpoint for retrieving information about the user you are logging in.

This is mainly useful for people who are using login providers that aren’t very popular. If you want to use Google, Facebook or Twitter, those are included out of the box and you don’t need this plugin. You can also look for other login providers in our Github Repo.

Configuration

Basic Configuration

  1. First, register your Discourse application with your OAuth2 provider. It will require a Redirect URI which will be:

    http://DISCOURSE_HOST/auth/oauth2_basic/callback

:information_source: Replace DISCOURSE_HOST with the appropriate value, and make sure you are using https if enabled. The OAuth2 provider should supply you with a client ID and secret, as well as a couple of URLs.

  1. Visit your Admin → Settings → OAuth2 Login and fill in the basic configuration for the OAuth2 provider:
  • oauth2_enabled - check this off to enable the feature
  • oauth2_client_id - the client ID from your provider
  • oauth2_client_secret - the client secret from your provider
  • oauth2_authorize_url - your provider’s authorization URL
  • oauth2_token_url - your provider’s token URL.

:information_source: If you can’t figure out the values for the above settings, check the developer documentation from your provider or contact their customer support.

Configuring the JSON User Endpoint

Discourse is now capable of receiving an authorization token from your OAuth2 provider. Unfortunately, Discourse requires more information to be able to complete the authentication.

We require an API endpoint that can be contacted to retrieve information about the user based on the token.

For example, the OAuth2 provider SoundCloud provides such a URL. If you have an OAuth2 token for SoundCloud, you can make a GET request to https://api.soundcloud.com/me?oauth_token=A_VALID_TOKEN and will get back a JSON object containing information on the user.

To configure this on Discourse, we need to set the value of the oauth2_user_json_url setting. In this case, we’ll input the value of:

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

The part with :token tells Discourse that it needs to replace that value with the authorization token it received when the authentication completed.

There is one last step to complete. We need to tell Discourse what attributes are available in the JSON it received. Here’s a sample response from 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"
}

The oauth2_json_user_id_path, oauth2_json_username_path, oauth2_json_name_path and oauth2_json_email_path variables should be set to point to the appropriate attributes in the JSON.

The only mandatory attribute is id - we need that so when the user logs on in the future that we can pull up the correct account. The others are great if available – they will make the signup process faster for the user as they will be pre-populated in the form.

Here’s how I configured the JSON path settings:

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

I used permalink because it seems more similar to what Discourse expects for a username than the username in their JSON. Notice I omitted the email path: SoundCloud do not provide an email so the user will have to provide and verify this when they sign up the first time on Discourse.

If the properties you want from your JSON object are nested, you can use periods. So for example if the API returned a different structure like this:

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

You could use user.id for the oauth2_json_user_id_path and user.email.address for oauth2_json_email_path.

If the key itself includes periods, you will need to put double quotes around it, or escape the periods with a backslash. For example, given this JSON:

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

You would specify the path as example\.com/uid or "example.com/uid"

:warning: If you set oauth2_json_email_path, the OAuth2 provider must confirm the user owns that email address. Failure to do this can result in account takeover in Discourse!

:discourse2: Hosted by us? This plugin is available on our Business and Enterprise plans. OAuth 2.0 & OpenID Connect Support | Discourse - Civilized Discussion

Last edited by @tobiaseigen 2025-07-16T21:39:12Z

Check documentPerform check on document:
28 Mi Piace

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?