Login error while trying to use Discourse as an identity provider (SSO, DiscourseConnect)

I am trying to follow this post: Use Discourse as an identity provider (SSO, DiscourseConnect) using Python code. The Python code below prints a URL that - as far as I can see - should me properly signed to access https://forum.embeetle.com/session/sso_provider on my Discourse instance, but instead, it shows just the text “Login Error”.

There is no error in the logs at https://forum.embeetle.com/logs, so I have no clue how to resolve this. Does this mean that the signature is incorrect? Any other suggestions?

BTW Don’t worry: I will change the SSO secret as soon as this issue is resolved.

import secrets
import base64
import urllib.parse
import hmac
import hashlib

forum_url = 'https://forum.embeetle.com'
target_url = 'https://embeetle.com/#account'
sso_secret = b'JCLSVcqbAnEPXz2p2xBY'

nonce = secrets.token_urlsafe()
payload = f'nonce={nonce}&return_sso_url={target_url}'
payload_base64 = base64.b64encode(payload.encode('utf-8')).decode()
payload_for_url = urllib.parse.quote(payload_base64)
signature = hmac.new(
    sso_secret, payload_for_url.encode('utf-8'), hashlib.sha256
).hexdigest()

print(f'{forum_url}/session/sso_provider?sso={payload_for_url}&sig={signature}')

This code generates a link like the one in the curl command below:

johan@morla:~/sa\> curl 'https://forum.embeetle.com/session/sso_provider?sso=bm9uY2U9bExhRUZjRGFVd0NrNTFkMEVOeGc5dUtKZ0kwNHZNYng5VkpFR0RqRUg0OCZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA%3D%3D&sig=70e647a1baad2e09ef6cdc6d87fae70bc27c6823369be20fd1b11ea536180343'
Login Errorjohan@morla:~/sa\> 

Here is a screenshot of the settings on the site:

What is wrong, or how can I debug this?

One step further: if I turn on verbose loggin for DiscourseConnect, I do get an error in the logs:

Verbose SSO log: Signature parse error Bad signature for payload sso: bm9uY2U9YklKeEU1WWw2OFhjSkJydGlwSU15UTRZeVlMeWd6ZzQyUU9mOFo0SWF5QSZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA= 

One notable point is that the payload mentioned in the log is not URL-encoded (note the ‘=’ at the end) and is missing the second ‘=’ of the URL-encoded data (note the repeated %3D at the end of the original payload).

Got it: the HMAC-SHA256 signature must be computed from the base64 encoded data, not from the url encoded data. So the correct code is:

import secrets
import base64
import urllib.parse
import hmac
import hashlib

forum_url = 'https://forum.embeetle.com'
target_url = 'https://embeetle.com/#account'
sso_secret = b'JCLSVcqbAnEPXz2p2xBY'

nonce = secrets.token_urlsafe()
payload = f'nonce={nonce}&return_sso_url={target_url}'
payload_base64 = base64.b64encode(payload.encode('utf-8')).decode()
payload_for_url = urllib.parse.quote(payload_base64)

signature = hmac.new(
    sso_secret, payload_base64.encode('utf-8'), hashlib.sha256
).hexdigest()

print(f'{forum_url}/session/sso_provider?sso={payload_for_url}&sig={signature}')

Now for the rest of the work: handling the redirect, checking the nonce, etc. To be continued …

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.