OAuth2 and Microsoft ADFS

Hi All,

I’ve been working with Discourse for a few weeks now and loving it, but the one thing I can’t get to work is OAuth2 with Microsoft Active Directory Federation Services (2016). The problem I have is that from tracing the code in the plugin on GitHub, the process is trying to make a secondary call to retrieve the user JSON Data and ADFS doesn’t like that as it’s included in the main Auth Token.

I’ve tried https://<auth_url>/adfs/userinfo and other combinations but they all error.

Has anybody managed to get this working as I’m out of ideas? I’ve taken a look at Auth0 which would work, but I want to use Discourse for an office Buy/Sell and general chat board for Employees so the cost is prohibitive.

Any ideas or suggestions would be welcomed!

Oh, I’ve also tried this https://meta.discourse.org/t/active-directory-sso-aka-integrated-windows-login/26548 which does work, but unfortunately the standard windows style login box can’t be changed and that’s really unfriendly to some of our less “technical” users.

Thanks

Andy

I am not familiar with ADFS, but I have just finished setting up an integration with Azure B2C, which is likely very similar.

It looks like ADFS supports openid_connect: Build a web application using OpenID Connect with AD FS 2016 and later | Microsoft Docs

So in theory, you can use the new discourse-openid-connect plugin. After completing the setup on the ADFS end, you just input the ‘discovery document’ URL into Discourse, along with the client id/secret. If the discovery document does not contain a “user info endpoint”, then the user information will be extracted from the JSON Web Token obtained from the “token endpoint”.

I will be adding some documentation for this new openid connect plugin this week, so please do let me know if you get it working for ADFS!

5 Likes

Hi David,

Firstly, thanks for the quick response!

I have removed the Oauth-basic plugin and installed the OpenID as suggested and it certainly got a lot further than the OAuth one did in a single step! I am getting an error when trying to login which you may be able to advise on? I’m using my own domain account so I know that the creds are correct.

From shared/standalone/log/rails/production.log

(oidc) Setup endpoint detected, running now.
(oidc) Request phase initiated.
Started GET "/auth/oidc/callback?code=t43rNvqNsk2lyQV91F0QOg.YqkNMDtZ1ghkACQIgPZC7OK5dB4.QFwAW_4H9PkcvkZF2Oe6AU9fb7R_JnbFxia5ozlYs6qr6AJfHvLkkgOV9ConwoffwHeRf53AqXvBz5yfIb4TNBW0TWOPZJamS7yXti13hj-f0u_UQgCAMXHOYzCp4kQBH_PwUI9uvxYNU5Igc3pLiF2VaVHVtvAbrBUzPydPZ9eMbr3g-sbZPbPXb4BSnB9wgWHwpZBn3qjwBppBC7BsluC2snqQDiwNtG6t19PgcK51dpePEfAkSiKNISyxJTOj3X27H8wdAXe81sDeyrmSbcm2RROuc4vCKMgUQSY6AcK6wC_hUhZOnP-loHRGVYo0CmhX8FqS4GsQtCtxsRP89g&state=65c967333cc12c178a89d613adb02195013eabe86a047603" for 127.0.0.1 at 2018-12-03 16:20:06 +0000
(oidc) Setup endpoint detected, running now.
(oidc) Callback phase initiated.
(oidc) Authentication failure! invalid_credentials: OAuth2::Error, 
Started GET "/auth/failure?message=invalid_credentials&origin=https%3A%2F%2F<ADFS_FQDN>%2Flogin&strategy=oidc" for 127.0.0.1 at 2018-12-03 16:20:06 +0000
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"message"=>"invalid_credentials", "origin"=>"https://<Discourse_FQDN>/login", "strategy"=>"oidc"}
  Rendering users/omniauth_callbacks/failure.html.erb within layouts/no_ember
  Rendered users/omniauth_callbacks/failure.html.erb within layouts/no_ember (0.6ms)
  Rendered layouts/_head.html.erb (6.0ms)
  Rendered common/_discourse_stylesheet.html.erb (41.1ms)
  Rendered application/_header.html.erb (0.7ms)
Completed 200 OK in 65ms (Views: 44.1ms | ActiveRecord: 12.0ms)

If this thread should be posted elsewhere please let me know ;o)

Many thanks

Andy

1 Like

More followup! The only error in the ADFS Tracing debug log is:

UserInfoListener.ValidateAccessToken: The access token in the request doesn’t have required audience ‘urn:microsoft:userinfo’.

But the almost last entry is a success:

An OAuth Authorization Code: ‘oSTUfjxZ1ghmAJp0gfEEodZKo7o’ was successfully issued to client: ‘87c22285-8e7a-4c88-afb3-3c533031a129’ with redirectUri: …

Andy

It’s fine to keep it in this topic - I’ve moved us to #support instead of #plugin:oauth2-basic (no openid-connect category yet :wink: )

Would you be able to share the openid-connect discovery document? The key thing I want to check is whether it contains a “userinfo_endpoint” URL?

Shouldn’t be an issue as the url is only accessible LAN side…

It does include the userinfo_endpoint url and here is a link to the file as I can’t attach a file where I’m a new user. Dropbox Link

1 Like

Thanks, so it looks like there is a userinfo endpoint specified in the document. Since it is specified, the plugin will try and use it to collect metadata about the user, rather than using the data in the token. It sounds like ADFS is issuing a token which does not have permission to access the userinfo URL. That might be configurable, but I’m afraid I don’t know anything about ADFS.

If that can’t be fixed, I can add a configuration option to the plugin so that you can force the plugin to ignore the userinfo endpoint - it sounds like this could be a useful preference for other people as well.

Hi David,

Thanks for reviewing the document and your suggestions. I will take a look into ADFS to see if that section is protected (most likely needs unlocking through PowerShell) and if I crack it I will let you know what I needed to do for your reference. If that doesn’t turn anything up I will most likely fork your project so I can put a load of debugging logs in it to try to narrow down where it’s getting the error from ADFS.

Andy

1 Like

If you do end up doing this, it would be a very welcome pull request. We have this ‘verbose logging’ functionality in the OAuth2-basic plugin behind a site setting

2 Likes

Hey,

I’ve been doing some more work on this today but not making a whole lot of progress as this is my first foray into ROR code as I’m a .Net Developer. Whilst the logging is working it’s taking me a huge amount of time to do any debugging as I have to change a line, commit, upgrade the plugin in Discourse, try again and round and round from there.

Before I spend any more time doing that same process, is there any way to do inline debugging for a Discourse plugin as I would be used to in Visual Studio? I appreciate that there are complexities and potentially some restrictions with it being hosted in Docker, but there must be a better way. I’ve done a search on this forum but not really turned anything up, so any advice would be appreciated!

Thanks

Inline debugging in an IDE is tricky to get set up. The best way is to set up a local development copy of Discourse. When developing locally, changes to code update live, so you don’t even have to restart the server! The easiest way to get started with that is:

Alternatively…

This is not ‘recommended’, but if you want to stick with making changes on your production instance, you can speed things up by getting a terminal inside the docker container

/var/discourse/launcher enter app

and then editing files directly

vi /var/www/discourse/plugins/discourse-openid-connect/......

and then restarting the server manually from within the container

sv restart unicorn
3 Likes

Hi David,

I thought I was making progress then I hit against yet another problem! This time it’s to do with Cookies and it would seem that OmniAuth is trying to store the entire JWT response which is too long. To be honest it could be something to do with what I’ve done but I can’t make any further progress as this is too deep into RoR for me :wink:

ActionDispatch::Cookies::CookieOverflow (ActionDispatch::Cookies::CookieOverflow)
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.0/lib/action_dispatch/middleware/cookies.rb:649:in `commit’

Any advice would be appreciated before I throw in the towel with this one…

Thanks

Andy

1 Like

Hi Andy - I actually just fixed that issue about an hour ago - so updating to the latest version of Discourse should help :slight_smile:

https://meta.discourse.org/t/openid-connect-authentication-plugin/103632/6?u=david

As you noted, it occurred when the response was too big for the CookieStore - now it saves the data in the database during the registration flow.

3 Likes

Fantastic, I will update my test install now and give it another shot!

Thanks.

4 Likes