Discourse OAuth2 Básico

: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 AdminSettingsOAuth2 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 Me gusta

Hola,
Estamos intentando integrar Discourse con nuestra aplicación usando OAuth2 Basic pero estamos recibiendo el siguiente error en los registros:
Nota: Estamos usando NGROK ya que estamos depurando la conexión.

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 S2k2SFZtTVpuSTFHUExiRXVlWVJDN4CbOkNvb1k0anlQemt3dWNRV21Sa2FWOVNnbHZLbjJFT3cxc3BIMmtMck9yY21vNDM4Tg=="}

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}

Dejamos los parámetros “oauth2 callback user id path” y “oauth2 callback user info paths” vacíos.

Cualquier idea es apreciada.

¿Puedo usar esto para autenticarme con el servicio XBL de Microsoft?

Supongo que la lógica sería similar a esta?

Hola a todos. Intento configurar este plugin con nuestro servidor Oauth2 interno con el flujo de código de autorización.

Cuando un usuario hace clic en “Conectar con Oauth”, el endpoint /authorize funciona y se devuelve un código al callback. Pero luego Discourse muestra un error genérico 500 “Oops. El software que impulsa este foro de discusión encontró un problema inesperado” y el endpoint /token no se accede.

El registro de errores dice esto:
OAuth2::ConnectionError (FinalDestination: todas las IPs resueltas fueron desautorizadas) 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 10:25 pm
params
code def50200babf84f7376f99fefa34369d876566b6bc0a341d8fba431999a72549ac06f6aad01df6fa43061707c525ba5d725ad
state 20139e0a134a5972566d4ddb6f7f9092a2cddb9e5216973a

Según entiendo, ¿hay un problema con alguna dirección IP? Actualmente el servidor Oauth2 está alojado en mi entorno de desarrollo (localhost) y los endpoints de autorización y token están configurados en consecuencia. ¿Es un problema?

Encontré el problema:

  1. Por alguna razón, el endpoint /token nunca se llamó. Después de configurar el máximo de opciones en los parámetros de administrador relacionados con oauth, el endpoint se llamó sin respuesta.
  2. Olvidé que era el servidor Discourse el que llamaría al endpoint /token y no el webclient. Por lo tanto, el servidor no pudo alcanzar mi servidor Oauth2 localhost. Poner nuestro servidor Oauth2 detrás de un dominio resolvió el problema.

Ahora, puedo conectar usuarios existentes pero no entiendo cómo iniciar sesión con nuevos usuarios a través de este plugin.
Si el usuario inicia sesión con oauth, recibe un error que dice que no tiene una cuenta activa en el servidor Discourse. Lo cual es normal ya que es un nuevo usuario.

¿Hay un callback dedicado para iniciar sesión en lugar de iniciar sesión? ¿O un parámetro específico para configurar para permitir la creación de cuentas?

Mi servidor oauth de la empresa generaba una respuesta JSON de /profile con un pequeño error tipográfico en un campo. Todo estuvo bien después de corregir el error tipográfico.
¡Pero tengo que decir que los registros de Discourse pueden ser muy engañosos! No había nada malo con la devolución de llamada.

Hola equipo:

Tengo un problema al extraer el ID que necesito para mi solicitud JSON de usuario de la respuesta de autorización. Al leer la documentación, parece que el ID de cuenta se envía en una matriz anidada:

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"]
      }
   ]
}

He intentado establecer la ruta del ID de usuario de la devolución de llamada oauth2 en permissions[0].accountId, pero el valor de mi uid siempre está en blanco. Desafortunadamente, las llamadas para extraer el JSON de usuario requieren este accountId en la URL JSON.

Pude hacer que esto funcionara pasando permissions.first.accountId. Descubrí que cuando pasé permissions a una propiedad de prueba, la matriz ya se analizó como una matriz de Ruby. Desafortunadamente, los campos parecen rechazar la sintaxis de Ruby para llamar a elementos de matriz y cualquier intento de usar la sintaxis de Javascript resultaría en un TypeError String a Integer. Afortunadamente, Ruby tenía la sintaxis anterior, ¿es este el método previsto?

Acabo de hacer que esto funcione con Authentik OAuth2, sin embargo, hubo algunos problemas con la configuración de oauth2 user json url. Usé el endpoint user_info de Authentik para eso (/application/o/userinfo/), sin embargo, no sabía cómo mapear los campos. Para cualquiera que busque cómo configurar Discourse con OAuth2 de Authentik, aquí está el resumen:

  • Ruta del ID de usuario: preferred_username
  • Ruta del nombre de usuario: preferred_username
  • Ruta del nombre: name
  • Ruta del correo electrónico: email
  • Ruta de verificación del correo electrónico: email_verified
  • Avatar: vacío.

Tuve los siguientes problemas:

  1. Al principio, olvidé la barra diagonal al final en la URL JSON https://DOMAIN/application/o/userinfo/. Esto llevó a que la solicitud de información del usuario (enlace permanente a la fuente) devolviera un código HTTP 301, lo que provocó que el inicio de sesión fallara. No sé si la barra diagonal al final debería estar allí por especificación, pero quizás sería bueno manejar correctamente los 301.
  2. Depurar esto resultó complicado. La configuración oauth2 debug auth fue un salvavidas, pero… Logster trunca el registro de depuración antes de volcar realmente los datos de respuesta significativos. Tuve que modificar manualmente en el contenedor la línea de registro a
    log("user_json_response: #{user_json_response.status} #{user_json_response.headers} #{user_json_response.body}")
    
    ¿Quizás esa línea de registro podría actualizarse? Supongo que podría ayudar a otras personas a descubrir la ruta de los atributos JSON.
4 Me gusta

Acabo de configurar Auth0 con el plugin y he descubierto que los avatares no se obtienen.

Estas son las configuraciones relevantes:

  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

En el registro de depuración, puedo ver que el elemento picture está configurado en la respuesta JSON, pero el avatar del usuario no cambia, ni para usuarios nuevos ni para los existentes.

¿Qué me he perdido?

¿Cuál es la mejor manera de reemplazar el icono en el botón de inicio de sesión con otro icono o una imagen?

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

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

parece suficiente pero un poco improvisado.

2 Me gusta

Parece que el plugin solo actualiza el avatar/nombre de usuario al crear el usuario inicialmente, no cada vez que inicia sesión.

¿Hay alguna forma de solucionar esto y hacer que el plugin también actualice el avatar al iniciar sesión/reconectar?

Puedes usar la configuración auth overrides email, auth overrides username y auth overrides name para que esas cosas se apliquen en futuros inicios de sesión. Me temo que actualmente no tenemos una configuración similar para avatares, pero sería pr-welcome

2 Me gusta

¡Gracias! De hecho, los encontré más tarde. Hice un fork del repositorio y agregué mis propias versiones para que esto funcionara con Roblox, lo que incluyó la anulación para los avatares. Que creo que simplemente usa la anulación de avatar de DiscourseConnect para que la gente no pueda cambiarla.

Sin embargo, desearía que Roblox no proporcionara un correo electrónico en OAuth, así que lamentablemente necesito que se registren con un correo electrónico. Pero eso no es un problema para ustedes, jaja.

Se dividió una publicación a un nuevo tema: El inicio de sesión de Twitter no funciona en meta

¿Alguien sabe si esto todavía funciona?

Sí. Estoy seguro de que este plugin funciona. :+1:

1 me gusta

Hola, pude integrar este plugin en mi discourse discuss.frontendlead.com, estoy usando teachable oauth https://docs.teachable.com/docs/oauth-quickstart-guide

Sin embargo, solo quiero permitir que las personas se registren exitosamente si y solo si tienen una cuenta de pago activa en teachable. Me imagino que necesito agregar funcionalidad personalizada en el plugin para manejar esto. Me pregunto si ustedes o incluso yo podemos introducir otro campo en la configuración llamado código personalizado después de oauth, que permita a los desarrolladores realizar acciones específicas después del registro. O si hay mejores sugerencias, por favor házmelo saber.

Editar: Hice un fork del repositorio y lo hice funcionar aquí:

Si alguien más que usa teachable está intentando hacer lo mismo, mi repositorio funcionará de inmediato, lo único es que si no compraste un curso, dirá que necesitas ir a mi dominio para comprarlo. Es posible que desees actualizar eso para tu propio caso de uso.

2 Me gusta

¡Eso es genial!

Existe una situación similar con el registro OAuth2 con el plugin Discourse Patreon. Cuando se habilita “Iniciar sesión con Patreon”, permite que cualquier persona con una cuenta de Patreon se registre en el sitio de Discourse. Lo que los propietarios del sitio generalmente quieren es permitir que solo sus patrocinadores puedan registrarse en cuentas de Discourse. Me pregunto si Patreon devuelve detalles que permitirían agregar una lógica similar a la autenticación de Patreon.

1 me gusta

Tengo el mismo error que @qlands arriba.

Mi plan inicial era enviar la información del perfil en el token. Al ver que no funcionó, lo simplifiqué para intentar el enfoque JSON. Pero ni siquiera llega al punto de llamar al archivo JSON.

El mensaje de error es:

(oauth2_basic) Fallo de autenticación! invalid_credentials: OAuth2::Error, {
  "access_token":"fa79b6fe0763862f5a8fd8",
  "token_type":"Bearer",
  "expires_in":3600,
  "scope":"profile"
}

¿Ves algo malo en la respuesta anterior?
¿Por qué el plugin generaría un error invalid_credentials mientras que el servidor OAuth2 respondió con un 200 y un token?