Background
In our business we operate a number of customer-facing web services which use an IdentityServer3 identity provider as the single source of identity. We have customised our setup to allow two sources of federated identity, and to pull certain claims from our CRM.
We have a new requirement to integrate a hosted instance of the excellent Discourse discussion forum, also using the same single source of identity.
Discourse does not support OpenId Connect, rather its own particular form of SSO.
Using IdentityServer3 as SSO source for Discourse
John Korsnes wrote the core of this approach, documented in his Medium article and on Github. In his article he gives a good overview of how the Discourse SSO works, and explains his approach:
- a custom endpoint on the IdentityServer, running in the same Owin context as the main IdP
- configure Discourse to redirect a login to the custom endpoint
- in the custom endpoint check if the user has a current authenticated session with IdentityServer
- if they have, generate a Discourse SSO payload from the user properties, and return to Discourse
- if they haven’t, display a simple login form, and once they have authenticated, generate and return the Discourse SSO payload as before
Our modifications
From our perspective the only drawback of John’s approach was that it only allowed for user authentication against the local IdentityServer accounts (username / password). Although that covers most of our customer accounts, we have extended our IdP with federated identity against our own company Office365 (Azure AD), and against Google, as some of our customers use Google Apps corporately.
To extend John’s approach we modified it so that instead of displaying a local login form we:
- register an application in our IdentityServer as a proxy for Discourse
- carry out an (almost) standard Authorization Code authentication process from our custom controller against the Identity Server
- the only difference is that because we are running inside the IdentityServer web pipeline we don’t need to redeem the authorization code against the token endpoint, but can ignore any generated tokens and query the OWIN Context in the same way John does.
Our version is shown below