Discourse OpenID Connect (OIDC)

:discourse2: Summary Discourse OpenID Connect allows an OpenID Connect provider to be used as an authentication provider for Discourse.
:open_book: Install Guide This plugin is bundled with Discourse core. There is no need to install the plugin separately.

Features

The plugin aims to provide a minimal implementation of the specification. Specifically, it supports the “Authorization Code Flow”. To get started, follow the plugin installation instructions, or contact your hosting provider.

Our oauth2-basic plugin can be used for connecting to some openid-connect providers (OpenID Connect is based on OAuth2). However, this plugin should require far less manual configuration, and can make use of the JWT “ID Token” if a JSON API is not available.

Configuration is automatically performed using an OpenID Connect Discovery Document. According to the specification, this should be located at <issuer domain>/.well-known/openid-configuration, but Discourse supports any path to allow for non-compliant implementations (e.g. Azure B2C). The discovery document is cached for 10 minutes, to improve performance on high-traffic sites.

If the discovery document includes a userinfo_endpoint parameter, then the plugin will use that to collect user metadata. If not, the plugin will extract metadata from the id_token (A JWT) supplied by the token endpoint. The plugin DOES NOT verify the authenticity of the JWT signature, as this would significantly increase complexity. This decision is supported by the specification:

If the ID Token is received via direct communication between the Client and the Token Endpoint (which it is in this flow), the TLS server validation MAY be used to validate the issuer in place of checking the token signature.

Configuration

Basic Configuration Options

  • openid_connect_enabled: Enable OpenID Connect authentication

  • openid_connect_discovery_document: OpenID Connect discovery document URL. Normally located at https://your.domain/.well-known/openid-configuration

  • openid_connect_client_id: OpenID Connect client ID

  • openid_connect_client_secret: OpenID Connect client secret

  • openid connect rp initiated logout: Redirect the user to end_session_endpoint after logout. Must be supported by your identity provider and included in the discovery document.

  • openid connect rp initiated logout redirect: (optional) The post_logout_redirect_uri which will be passed to the logout endpoint. If provided, it must be registered with the identity provider.

  • openid_connect_authorize_scope: The scopes sent to the authorize endpoint. This must include ‘openid’

  • openid_connect_use_pkce: Enable Proof Key for Code Exchange (PKCE) for OpenID Connect authentication.

  • openid_connect_verbose_logging: Log detailed openid-connect authentication information to /logs. Keep this disabled during normal use.

Advanced Configuration Options

  • openid_connect_token_scope: The scopes sent when requesting the token endpoint. The official specification does not require this.

  • openid_connect_error_redirects: If the callback error_reason contains the first parameter, the user will be redirected to the URL in the second parameter. Used for unusual implementations that send errors in response to user input (e.g. Azure B2C)

  • openid_connect_allow_association_change: Allow users to disconnect and reconnect their Discourse accounts from the OpenID Connect provider

Example setup

Here we will set up the openid-connect plugin to connect to Google’s OpenID Connect provider. This replicates functionality that already exists in the core of Discourse, but it serves as an accessible example.

  1. Head to OpenID Connect  |  Sign in with Google  |  Google for Developers and follow the instructions to obtain OAuth Credentials.

  2. On the same page, follow the instructions to add a redirect URI. This should be https://<your_forum>/auth/oidc/callback (without a trailing slash)

  3. Go to your Discourse site settings and search for “openid_connect”

    • openid connect enabled:

    • openid connect discovery document: https://accounts.google.com/.well-known/openid-configuration

    • openid connect client id: <client-id>

    • openid connect client secret: <client-secret>

    • openid connect authorize scope: openid email (with a space in between)

  4. You’re done. The “Login with OpenID Connect” button will now log in using Google :tada:. These same steps can be applied to other providers, with very minimal changes.

Debugging

In addition to the verbose_logging setting described above, you can access data about OIDC associations using the data-explorer plugin:

SELECT user_id, provider_name, provider_uid
FROM user_associated_accounts
WHERE provider_name = 'oidc'

Or on the rails console:

User.find_by_username("david").user_associated_accounts.where(provider_name: 'oidc')

Provider Specific Notes

Please feel free to update this if you find any provider-specific quirks relating to this integration:

Entra ID (formerly Azure AD)

Add the email scope, and make sure you’re using the version 2 endpoint configuration document. For example

https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration
Azure B2C

The discovery document URL details can be found here: Web sign in with OpenID Connect - Azure AD B2C | Microsoft Learn

To make emails work:

Yahoo
  1. Head to Login - Sign in to Yahoo and create a new app

  2. Enter the Application Name, and set the callback domain to your forum domain (e.g. meta.discourse.org)

  3. Under API Permissions, choose Profiles: Read/Write Public and Private. This is the only way I know of to obtain the user email address

  4. Save the app

  5. In the Discourse OIDC settings, set the discovery document to

    https://login.yahoo.com/.well-known/openid-configuration
    
  6. Enter the client ID and secret from Yahoo

  7. Enable the OIDC plugin

AWS Cognito
  1. Go to Cognito and select or create a new user pool.
  2. Define an app in App clients.
  3. Leave everything to default, but change Auth Flows Configuration to only select ALLOW_REFRESH_TOKEN_AUTH.
  4. Go to app client settings and select the new app.
  5. Change the callback URL to https://yoursite.example.com/auth/oidc/callback.
  6. Only check the Authorization code grant flow among “Allowed OAuth Flows”.
  7. Check all scopes needed (I have all checked).
Okta
  1. Configure Discourse with your Okta app client ID and secret

  2. Set the discovery document URL to

    https://{your-app}.okta.com/.well-known/openid-configuration
    
  3. In Discourse, set the openid connect authorize scope to openid email

: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 @pedro 2025-08-29T23:26:31Z

Check documentPerform check on document:
51 curtidas

Olá,\nestamos usando o Plugin de Autenticação OpenID Connect com uma instalação do Discourse na AWS.
Temos os contêineres Discourse, Discourse Sidekiq e Redis implantados (baseados no Bitnami, mas por favor, não me expulsem ;)). O banco de dados está rodando na AWS RDS. Usamos o KeyCloak.

As coisas funcionam.

Mas às vezes, após uma reinicialização da Tarefa AWS do Discourse, acontece que ele pensa que tem o documento de descoberta em cache, mas não há nenhum documento lá. E ele não tenta recuperá-lo novamente do KeyCloak:

OIDC Log: Discovery document loaded from cache
OIDC Log: Discovery document is
---
(oidc) Request phase initiated.
(oidc) Authentication failure! openid_connect_discovery_error: OmniAuth::OpenIDConnect::DiscoveryError, Discovery document is missing

No aplicativo do navegador, vejo: Incapaz de buscar configuração do provedor de identidade. Por favor, tente novamente.

O que você pode aconselhar?

2 curtidas

Olá,

Existe uma maneira de definir a origem do avatar do usuário do Discourse para um campo especificado no serviço openID?

Editar: estamos usando keycloak

1 curtida

Olá,

Tenho um requisito semelhante ao do @Tomáš_Guba: gostaria de obter um valor de uma entrada personalizada no perfil do usuário e usá-lo em um campo de usuário [personalizado].

No meu caso particular, tenho um documento de descoberta com um userinfo_endpoint

Existe algo assim no roteiro do plugin?

Obrigado

1 curtida

Olá, consegui fazer o plugin funcionar com meu SSO openID mas ele não vem preenchido no campo de nome de usuário do outro sistema ou e-mail entre outros campos…\n\nImagino que deva configurar algo no campo "openid connect claims", mas não sei como configurar este campo diretamente. Alguém pode me dar um exemplo? Seguem alguns prints de como está meu projeto:\nhttps://imgur.com/gallery/LWvkJUV

1 curtida

Existe alguma forma de evitar “perder” a rota original ao fazer login em uma postagem privada?

Se visitarmos uma página privada e clicarmos em um dos botões de login nessa página, ao sermos redirecionados de volta para o site, acabamos na página de categorias.

Olá @david,

Você pode, por favor, dar uma olhada no problema mencionado na postagem a seguir? Eu gostaria de usar o plugin OIDC em vez do OAuth básico. Mas eu enfrento o mesmo problema - não consigo passar parâmetros para a solicitação /authorize. Eu coloco o valor no plugin no formato foo=bar.

Não consegui fazer isso funcionar no LinkedIn. Alguém mais conseguiu? Consigo fazer login no LinkedIn após ser redirecionado para lá ao clicar no botão “entrar com…” e depois “permitir” que meu aplicativo use meu e-mail do LinkedIn, então recebo “Desculpe, ocorreu um erro ao autorizar sua conta. Por favor, tente novamente.”

https:/discourse.mysite.com/auth/failure?message=invalid_credentials&origin=https%3A%2F%2Fdiscourse.mysite.com%2F&strategy=oidc

Ainda estou com problemas. Estou recebendo o seguinte erro:

(oidc) Falha na autenticação! credenciais inválidas: OAuth2::Error, invalid_request: Um parâmetro obrigatório "client_secret" está faltando {"error":"invalid_request","error_description":"Um parâmetro obrigatório

É um erro do omniauth e parece estar relacionado [potencialmente] a isto: No longer works with oauth2 gem v2.0+ · Issue #68 · decioferreira/omniauth-linkedin-oauth2 · GitHub

Ajuda é apreciada!

Estou recebendo os seguintes erros:

(oidc) Falha na autenticação! openid_connect_discovery_error: OmniAuth::OpenIDConnect::DiscoveryError, Documento de descoberta está faltando

Log OIDC: Buscar documento de descoberta gerou erro Faraday::ConnectionFailed FinalDestination: falha na consulta

Tenho a configuração do meu plugin “documento de descoberta de conexão openid” definida em Configurações do Administrador como: https://<auth_provider>/.well-known/openid-configuration e consigo acessá-lo com sucesso no contêiner Docker do aplicativo que está em execução com um comando Curl e até mesmo no console Rails.

Alguma ideia de por que estou recebendo esses erros? Não consigo integrar corretamente por causa disso. Além disso, estou atrás da intranet e usando um proxy da empresa, se isso ajudar. Como eu disse, com o proxy habilitado no ENV do contêiner, consigo acessar corretamente o URL “documento de descoberta de conexão openid”.

1 curtida

2 posts foram divididos em um novo tópico: Permitindo múltiplas fontes OIDC

Uma postagem foi dividida em um novo tópico: Substituindo avatares com OIDC

Olá!

Nova pergunta: este plugin lida com gerenciamento de sessão? (Final: OpenID Connect Session Management 1.0).
Eu não acho, porque mesmo que o OP envie os dados session_state, não vejo em nenhum lugar no código onde eles são armazenados como cookie ou algo assim.

Então esta é uma pergunta/solicitação de recurso :slight_smile: Seria fantástico!

2 curtidas

Ao usar este plugin com o AWS Cognito, para fazer logout, o Cognito exige a passagem de um parâmetro client_id para a URL de logout. Pelo que pude apurar, não há como adicionar parâmetros de consulta adicionais à URL de logout - isso está correto? Caso contrário, é possível adicionar essa funcionalidade?

Olá pessoal :wave:t3:

Escrevi uma pequena extensão para este plugin (tecnicamente na forma de um tema/componente) - para ocultar o botão “Login via OIDC” no pop-up de login, mas iniciar o fluxo de login via OIDC acessando um URL especial.

discourse-autooidc.zip (1,0 KB)

O caso de uso para este recurso é fornecer um login seguro e conveniente (automático) via oauth para os membros da nossa empresa, sem expor um link público para o provedor OAuth (Authentik no nosso caso, mas também deve funcionar com Authelia, Keycloak, Auth0, Okta,…) e sem incomodar todos os outros usuários com um botão de login via OIDC que eles nunca podem ou devem usar.

Para fazer login via OIDC, basta chamar https://<sua-url-base-do-discourse>/login#autooidc

3 curtidas

Você pode se interessar por GitHub - discourse/discourse-hide-auth-method: A theme component which allows hiding a specific login method from the UI, without fully disabling it, que faz algo semelhante

3 curtidas

O Keycloak suporta Backchannel logout URL (URL de logout do canal posterior):

URL que fará com que o cliente se desconecte quando uma solicitação de logout for enviada para este realm (via end_session_endpoint). Se omitido, nenhuma solicitação de logout será enviada ao cliente neste caso.

Seria ótimo se este plugin expusesse algum endpoint que aceitasse um payload do Keycloak e desconectasse imediatamente algum usuário de todas as sessões. Caso contrário, quando desabilitarmos um usuário no Keycloak, teremos que esperar o maximum session age (idade máxima da sessão) (que é bem grande por padrão).

Você também pode desconectá-los de todas as sessões usando a página de administração do usuário (por exemplo, /admin/-1/system) e clicar no botão Sair na parte superior da página.

Olá,

Quando a busca do documento de descoberta falha (por exemplo, em caso de timeout), o plugin armazena o erro em cache, o que significa que a autenticação fica indisponível por 10 minutos. É possível não armazenar o erro em cache para que a busca seja tentada novamente mais cedo?

Atenciosamente

Desculpe o ping, mas há um PR aberto para isso que deve ser trivial de mesclar para adicionar suporte a PKCE.

@nbianca Vi que você foi o último a commitar no repositório, você poderia dar uma olhada, talvez? :folded_hands:

1 curtida