# OpenID Connect Plugin Refactor (OIDC Implicit Flow)

**URL:** https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884
**Category:** Development
**Created:** [October 28, 2025, 12:19am UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884 "2025-10-28T00:19:52Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![justinm](https://avatars.discourse-cdn.com/v4/letter/j/47e85d/32.png) [@justinm](https://meta.discourse.org/u/justinm)
#### Post date: [October 28, 2025, 12:19am UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884/1 "2025-10-28T00:19:52Z")

</div>

Hey everyone,

I’m looking to improve our security posture, and part of that means that we need to avoid using secret credentials whenever we can.  
Unfortunately the OIDC plugin required a client secret credential to hit the `/userinfo` endpoint, and I couldn’t set up my forum with it enabled.

Fortunately, the OIDC specification is actually defined in a way that doesn’t require the use of any secret tokens.  
If we stick to the [`id_token` flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc#send-the-sign-in-request), the IdP will send us all of the information we need to authenticate a user without having to reach back out to the IdP.

This is secure because the redirect is configured in the IdP, and we don’t have to worry about the bearer token being forwarded to the wrong destination.

I went ahead and created a patch for the OIDC plugin to support the `id_token` flow and submitted a pull request here:  
[https://github.com/discourse/discourse/pull/35606](https://github.com/discourse/discourse/pull/35606)

The PR isn’t _quite_ complete since it still needs unit tests, but it’s pretty much there and I’ve confirmed that this works properly with Azure AD (Entra ID).

For ref, here is the documentation for the OIDC plugin:

> [@Discourse OpenID Connect (OIDC)](https://meta.discourse.org/t/discourse-openid-connect-oidc/103632):
>
> discourse2Summary Discourse OpenID Connect allows an OpenID Connect provider to be used as an authentication provider for Discourse.open_bookInstall 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](https://openid.net/specs/openid-connect-basic-1_0.html). Specifically, it supports the “Authorization Code Flow”. To get started, follow [the plugin installation instructions](https://meta.discourse.org/t/install-plugins-in-discourse/19157), or contact your hosti…

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [October 29, 2025, 1:00pm UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884/2 "2025-10-29T13:00:26Z")

</div>

I think what you’re describing here is the OpenID Connect [“Implicit Flow”](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth), which works without any server-\>server communication, and therefore doesn’t need a shared secret. Instead, all information is transmitted via the HTTP redirects, and the ID token is cryptographically verified using the public keys from the Discovery Document.

That’s fine, and I think it’s a valid feature request. But it’s a very different system to our current plugin, which uses [the authorization code flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth). This flow uses server-\>server communication with a shared secret, and therefore no cryptographic verification of the id\_token is needed. This is simpler in some ways, but more complex in others.

Importantly: we can’t just change the default implementation in the plugin. Sites which are using the authorization-code flow need to keep using that. IIRC many identity providers don’t even support the Implicit Flow.

So I think there are two paths forward here:

1. We add support for the “implicit flow” in the OIDC plugin, but make it an **opt-in** thing. I think it’s unlikely we’ll accept a PR which introduce the openid-connect gem as a dependency of Discourse core, so therefore it would need to be implemented within our current strategy.

or alternatively

1. You build the implicit flow as a totally new plugin. In this case you’d be free to do whatever you like in terms of implementation (but you’d also have to maintain it yourself)

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [October 29, 2025, 1:19pm UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884/3 "2025-10-29T13:19:37Z")

</div>

Also worth noting that the OIDC “Implicit Flow” does increase the surface area for CSRF attacks and token exposure:

> **[Implicit flow vs. Authorization code flow: Why implicit flow is dead? · Logto...](https://blog.logto.io/implicit-flow-is-dead)**
>
> Why is there an "Authorization code flow" in OAuth 2.0 when we already have the "Implicit flow"? Let's dive into the details of these two grant types and find out why you should avoid using the implicit flow.

I think it can still make sense for some situations. But it seems like the Authorization Code flow (Discourse’s default) with PKCE (optional in Discourse) is the most-recommended way to use OIDC.

So it may be worth reconsidering this statement:

> [@justinm](#):
>
> I’m looking to improve our security posture, and part of that means that we need to avoid using secret credentials

Is switching to the OIDC implicit flow, and therefore transmitting all your user information via the client, really an improved security posture? 🤔

---

<div class="post-metadata">

### Author: ![justinm](https://avatars.discourse-cdn.com/v4/letter/j/47e85d/32.png) [@justinm](https://meta.discourse.org/u/justinm)
#### Post date: [October 31, 2025, 1:17am UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884/4 "2025-10-31T01:17:19Z")

</div>

Thank you for the detailed reply!

> I think it can still make sense for some situations. But it seems like the Authorization Code flow (Discourse’s default) with PKCE (optional in Discourse) is the most-recommended way to use OIDC.

This is very interesting - I didn’t fully grasp PKCE until now. Based on my reading of [auth0’s documentation](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce), it seems like (in certain configurations) this flow has the advantages of the implicit flow (no client secret) with none of the downsides.

> **[Get Rid Of Client Secrets With OAuth Authorization Code PKCE Flow | Xebia](https://xebia.com/blog/get-rid-of-client-secrets-with-oauth-authorization-code-pkce-flow/)**
>
> In this article, we'll dive into the OAuth 2.0 Proof Key for Code Exchange (PKCE) flow, an extension of the Authorization Code flow that helps prevent CSRF

Is this perhaps something that can be done instead? It looks like it’s simple as removing the client secret parameter from the `/token` endpoint.

And ultimately, my main concern is just eliminating the requirement for a client secret 🙂

---

<div class="post-metadata">

### Author: ![justinm](https://avatars.discourse-cdn.com/v4/letter/j/47e85d/32.png) [@justinm](https://meta.discourse.org/u/justinm)
#### Post date: [October 31, 2025, 5:57pm UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884/5 "2025-10-31T17:57:25Z")

</div>

Okay - this works with the following configuration:

```plaintext
"DISCOURSE_OPENID_CONNECT_ENABLED": "true",
"DISCOURSE_OPENID_CONNECT_DISCOVERY_DOCUMENT": "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration",
"DISCOURSE_OPENID_CONNECT_CLIENT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"DISCOURSE_OPENID_CONNECT_CLIENT_SECRET": "",
"DISCOURSE_OPENID_CONNECT_VERBOSE_LOGGING": "true",
"DISCOURSE_OPENID_CONNECT_USE_PKCE": "true"

```

And the following change to the code:

```diff
diff --git a/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb b/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
index 410a88f46dc..e74ee360aae 100644
--- a/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
+++ b/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
@@ -73,6 +73,11 @@ module OmniAuth
              )
           options[:client_options][:auth_scheme] = :request_body
         end
+
+ # If we're using PKCE _and_ there is no client_secret, use the request_body auth_scheme.
+ if options[:pkce] && options[:client_secret].empty?
+ options[:client_options][:auth_scheme] = :request_body
+ end
       end
 
       def request_phase

```

The redirect URI is configured in the Azure control panel as follows:

 ![image](https://global.discourse-cdn.com/meta/original/4X/6/5/5/655ae1c7271cb4e99dc35cacb0a12714523067a6.png)

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [January 16, 2026, 1:29pm UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884/6 "2026-01-16T13:29:39Z")

</div>

Thanks for this @justinm. I’ve merged the PR, and added a section to the docs:

> [@Discourse OpenID Connect (OIDC)](https://meta.discourse.org/t/discourse-openid-connect-oidc/103632/1):
>
> For identity providers which support secret-less authorization using the [“Authorization Code Flow with Proof Key for Code Exchange”](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce), PKCE should be enabled, and the `client_secret` configuration can be omitted.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [January 26, 2026, 8:00am UTC](https://meta.discourse.org/t/openid-connect-plugin-refactor-oidc-implicit-flow/386884/7 "2026-01-26T08:00:15Z")

</div>

This topic was automatically closed after 9 days. New replies are no longer allowed.
