Skip to content

Instantly share code, notes, and snippets.

@shahinism
Last active June 13, 2018 14:49
Show Gist options
  • Save shahinism/1f41366a625a4367f75538b81ce215a6 to your computer and use it in GitHub Desktop.
Save shahinism/1f41366a625a4367f75538b81ce215a6 to your computer and use it in GitHub Desktop.
Handeling Discourse SSO using Python 3
# Sources:
# 1. https://meta.discourse.org/t/using-discourse-as-a-sso-provider/32974
# 2. https://meta.discourse.org/t/official-single-sign-on-for-discourse-sso/13045
import hmac
import hashlib
import random
import base64
from urllib import parse
# credits to: https://stackoverflow.com/a/28186447/1573477
def generate_nonce(length=8):
"""Generate pseudorandom number."""
return ''.join([str(random.randint(0, 9)) for i in range(length)])
class Discourse:
def __init__(self, base_url, sso_secret, return_url):
self.encoding = 'utf-8'
self.base_url = base_url
self.sso_secret = bytes(sso_secret, encoding=self.encoding)
self.return_url = return_url
self.__nonce = None
self.__payload = None
@property
def nonce(self):
if not self.__nonce:
self.__nonce = generate_nonce(20)
return self.__nonce
@property
def payload(self):
if not self.__payload:
payload = parse.urlencode({
'nonce': self.nonce,
'return_sso_url': self.return_url
})
self.__payload = bytes(payload, encoding=self.encoding)
return self.__payload
@property
def base64_payload(self):
return base64.encodestring(self.payload)
@property
def hmac(self):
h = hmac.new(
self.sso_secret, self.base64_payload, digestmod=hashlib.sha256)
return h.hexdigest()
@property
def auth_request(self):
params = parse.urlencode({
'sso': self.base64_payload,
'sig': self.hmac
})
return f'{self.base_url}/session/sso_provider?{params}'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment