Last active
August 30, 2022 12:03
-
-
Save MGough/2100b56232fe4159ffcaadabfe4c38b8 to your computer and use it in GitHub Desktop.
Discourse Connect SSO Auth Action - Based on: https://blog.leog.me/discourse-sso-with-auth0-e49486d0294a
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on: https://blog.leog.me/discourse-sso-with-auth0-e49486d0294a | |
// This must be the last action in the flow, as it potentially redirects the user to discourse and doesn't have a `onContinuePostLogin` hook as we're not expecting Discourse to return them | |
const DISCOURSE_AUTH0_CLIENT_ID = "<Your client ID>"; | |
const DISCOURSE_DOMAIN = "<Your Discourse Domain>"; | |
// We use this to avoid sending users to Discourse with unverified emails | |
// As we want Auth0 to handle email verification by default, not Discourse. | |
// If they're sent to discourse then they'll receive an email from discourse as well as Auth0 asking to independently verify their emails. | |
const DISCOURSE_NON_VERIFIED_EMAIL_REDIRECT_URL = "<A URL for users with unverified emails>"; | |
/** | |
* Handler that will be called during the execution of a PostLogin flow. | |
* | |
* @param {Event} event - Details about the user and the context in which they are logging in. | |
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login. | |
*/ | |
exports.onExecutePostLogin = async (event, api) => { | |
// Check whether the Auth0 client is the one we want to apply this rule to | |
if (event.client.client_id === DISCOURSE_AUTH0_CLIENT_ID) { | |
// If they're verified it's safe to send them through to discourse | |
if (event.user.email_verified) { | |
// Check out Discourse's SSO implementation requirements already in discourse-sso package | |
// at https://meta.discourse.org/t/official-single-sign-on-for-discourse-sso/13045#heading--implement | |
const DiscourseSSO = require('discourse-sso'); | |
// Setup sso_secret variable on your client variables on Auth0 so you don't need to have it inline in your code | |
const sso = new DiscourseSSO(event.secrets.sso_secret); | |
// Validate the query payload with its signature (it uses the sso_secret passed to the DiscourseSSO instance) | |
if (sso.validate(event.request.query.sso, event.request.query.sig)) { | |
// Extract nonce information | |
const nonce = sso.getNonce(event.request.query.sso); | |
const userparams = { | |
// Required, will throw exception otherwise | |
"nonce": nonce, | |
"external_id": event.user.user_id, | |
"email": event.user.email, | |
// Optional | |
"username": event.user.nickname, | |
// Just in case we somehow make a mistake one day... | |
// If we send a user that doesn't have a verified email then we tell Discourse to use its own email verification flow | |
"require_activation": !event.user.email_verified, | |
"suppress_welcome_message": false | |
}; | |
const query = sso.buildLoginString(userparams); | |
api.redirect.sendUserTo(`https://${DISCOURSE_DOMAIN}/session/sso_login?${query}`); | |
return; | |
} | |
} | |
// They're trying to login to the forum, but their email isn't verified! | |
api.redirect.sendUserTo(DISCOURSE_NON_VERIFIED_EMAIL_REDIRECT_URL); | |
} | |
}; |
Also worth noting some of the behaviour around redirects and email verification. I'm probably not going to update this gist to do more than the original, but I've rewritten my own action to redirect the user to our generic 'Please verify email' URL if their email if not verified for this specific Discourse application.
Subsequently I've updated our 'Verification Email' redirect URL to send the user directly to Discourse if they originally registered via this Discourse application. This avoids the case where we send two verification emails, one via Auth0 and one via Discourse
Edited: I've updated this to capture my email verification changes
I've updated for now not to use:
api.redirect.sendUserTo(`https://${DISCOURSE_DOMAIN}/session/sso_login?${query}`);
as I'm seeing issues with this, need to revisit the docs.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Oh perfect, thank you for pointing that out. I should've spent slightly longer reading those docs... I'll get it updated when I have a moment.