Since the provider and the non-provider settings are for opposite use cases—using Discourse to manage users for something else versus using something else to manage users for Discourse—displaying these settings mixed together invites misconfiguration. It would be less confusing if the two provider settings were consecutive and either entirely before or entirely after the non-provider settings.
@techAPJ Can this be used with AWS Cognito? I want to create an app in AWS Amplify for my discourse community and want my app to be authenticated through discourse.
@mdoggydog Thanks for the recent update to the DiscourseSsoConsumer MediaWiki extension. We’d been puzzling over what to do about users being logged out of our wiki without having logged out of Discourse, and $wgPluggableAuth_EnableAutoLogin was definitely not what we wanted, since it prevents anonymous access to the wiki. The $wgDiscourseSsoConsumer_AutoRelogin setting you added is exactly what we needed.
I am trying to use the PHP example from the original post, but the way they’re storing stuff doesn’t make sense. They’re just storing values in an SQL database with the keys login and nonce. If I want to use SQL to store the nonces what would my SQL database look like exactly?
Some other info that might help is what I’m using this for - I am hoping to link a Discourse user to a Minecraft account by generating an SSO link which is tied to their UUID. Upon successfully logging in with Discourse, I’m going to store their UUID and Discourse ID in a table.
So far, I was able to get the PHP example working, but I guess I’m not fully understanding how I’d have to modify it to work for my use-case. Ideally, I want to generate the link through a GET request and send it to the user, so the UUID is already associated with the nonce.
Thank you for this post, as I would be even more lost without it!
Edit: For nonces would I just be better off storing nonces in the table and look up by that? I know I need to match the nonce but, unless I can pass additional information through in the redirect URL (which I haven’t been successful doing so) I’m not sure how to reference the nonce properly.
I edited out some of the value of the sso param that you had provided. Unless someone knew your secret key they would not be able to decode the value, but it still seemed safer to not provide the full value. It won’t be related to the 502 error that you are getting.
It seems that trying to authenticate into discourse-auth-proxy with non-ASCII usernames or group names (Chinese in my case) leads to an error due to cookies cannot contain these characters. This is my fix: (disclaimer: I’m not really familiar with golang)
diff --git a/main.go b/main.go
index 1b1dc28..18f8c9e 100644
--- a/main.go
+++ b/main.go
@@ -154,7 +154,12 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
var username, groups string
if err == nil && cookie != nil {
- username, groups, err = parseCookie(cookie.Value, config.CookieSecret)
+ var value string
+ value, err = url.QueryUnescape(cookie.Value)
+ if err != nil {
+ return
+ }
+ username, groups, err = parseCookie(value, config.CookieSecret)
}
if err == nil {
@@ -224,7 +229,7 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
cookieData := strings.Join([]string{username, strings.Join(groups, "|")}, ",")
http.SetCookie(w, &http.Cookie{
Name: cookieName,
- Value: signCookie(cookieData, config.CookieSecret),
+ Value: url.QueryEscape(signCookie(cookieData, config.CookieSecret)),
Expires: expiration,
HttpOnly: true,
Path: "/",
I was able to use this to create an account linking system for my Minecraft server! Thought I’d share what it looks like! This was my first time working with Discourse SSO, so I might’ve overcomplicated everything. However, it works, which is the main thing.
Hi i did all these correctly. but when the user is not logged in discourse it will show user login popup. when I fill username and password, it does not redirect me back to return_url. can you please help me?
I assume the nonce is there to prevent replay attacks. I read online that replay attacks aren’t possible with HTTPS, which is what I’m using. So do I still need to do the nonce? I ask because I’m not sure where to store it. Does it make sense to store it as a secure, plain text cookie in the user’s browser? and then read it from the browser along with the return payload?
Yes, you still need to validate the nonce because it prevents reusing payloads that Discourse sends when it redirects users back to your site.
For example, let’s your site has some content behind a paywall that only members of the subscribers group on Discourse can access and you use the groups field in the payload that Discourse sends to your site to display the paid content only to members of the subscribers group. If you don’t validate the nonce, a user who is no longer in the subscribers could use an old payload from when they were a member to login to your site and see the paid content.
It’s best to store the nonce in a database with a short expiration date and delete the nonce from the database as soon as it’s used. However, if you can’t use a database, then you can use a cookie to store the nonce, but you need to do some additional steps to prevent payload reuse:
attach an expiration date to the nonce when you generate it, for example 10 minutes from the current time
sign the whole cookie (nonce + expiration date) to prevent users from modifying the nonce and/or the expiration date
verify the signature of the cookie and ensure the nonce isn’t expired
That should give you a good enough protection against payload reuse. Keep in mind that technically it remains possible to reuse a payload, but it’ll be limited to a 10 minutes window instead of forever.
A simpler solution that doesn’t need a cookie is to include the expiration date in a custom field in the payload that you generate. Then when Discourse redirects users back to your site with a payload, your custom fields will be included and you can retrieve the expiration date and you verify it’s not expired. To include a custom field in the payload, you need to include a field prefixed with custom., so your payload would look like this:
Can someone tell me (@pfaffman or @tobiaseigen or @iamntz) what the Discourse SSO provider returns? I know I can “try it and see” but it would be nice to have it documented. The github PHP sample code doesn’t trally have any other fields even mentioned.
Ideally, it would send the same fields as when Discourse uses the external script for SSO, such as external id, email, username, name, avatar photo etc. So we can import this and create a user on our side!
Does it also tell Wordpress the email?
How about groups, badges etc? Can we find this information by making REST calls?
Finally, what about the user’s private messages and other stuff? I guess if Discord was an oAuth provider and allowed our apps to consume this sruff, that would be awesome.
When trying to enable Discourse Connect I get this error: enable_discourse_connect: You cannot enable DiscourseConnect and invite only at the same time.
The enable discourse connect provider setting is for when you want to use your Discourse site as the identity provider for another site. The enable discourse connect setting is for when you want to log users into Discourse via an external site.
I’ve implemented the procedure in Python for a Flask application I am building. Here is some boilerplate code for anyone who needs it. The steps laid out in this topic were pretty simple to follow but I’m not a security specialist so if I overlooked anything please let me know!