-
-
Save jeromecc/a50a2bfef4ce654318091a660959f76f to your computer and use it in GitHub Desktop.
Django Discourse SSO endpoint adapted from https://meta.discourse.org/t/sso-example-for-django/14258 - depends on settings.py DISCOURSE_BASE_URL and DISCOURSE_SSO_SECRET
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
import base64 | |
import hmac | |
import hashlib | |
from urllib import parse | |
from django.contrib.auth.decorators import login_required | |
from django.http import HttpResponseBadRequest, HttpResponseRedirect | |
from django.conf import settings | |
@login_required | |
def discourse_sso(request): | |
''' | |
Code adapted from https://meta.discourse.org/t/sso-example-for-django/14258 | |
''' | |
payload = request.GET.get('sso') | |
signature = request.GET.get('sig') | |
if None in [payload, signature]: | |
return HttpResponseBadRequest('No SSO payload or signature. Please contact support if this problem persists.') | |
# Validate the payload | |
payload = bytes(parse.unquote(payload), encoding='utf-8') | |
decoded = base64.decodebytes(payload).decode('utf-8') | |
if len(payload) == 0 or 'nonce' not in decoded: | |
return HttpResponseBadRequest('Invalid payload. Please contact support if this problem persists.') | |
key = bytes(settings.DISCOURSE_SSO_SECRET, encoding='utf-8') # must not be unicode | |
h = hmac.new(key, payload, digestmod=hashlib.sha256) | |
this_signature = h.hexdigest() | |
if not hmac.compare_digest(this_signature, signature): | |
return HttpResponseBadRequest('Invalid payload. Please contact support if this problem persists.') | |
# Build the return payload | |
qs = parse.parse_qs(decoded) | |
user = request.user | |
params = { | |
'nonce': qs['nonce'][0], | |
'email': user.email, | |
'external_id': user.id, | |
'username': user.username, | |
'require_activation': 'true', | |
'name': user.get_full_name(), | |
} | |
return_payload = base64.encodebytes(bytes(parse.urlencode(params), 'utf-8')) | |
h = hmac.new(key, return_payload, digestmod=hashlib.sha256) | |
query_string = parse.urlencode({'sso': return_payload, 'sig': h.hexdigest()}) | |
# Redirect back to Discourse | |
discourse_sso_url = '{0}/session/sso_login?{1}'.format(settings.DISCOURSE_BASE_URL, query_string) | |
logger.warning("discourse redirect url: %s", discourse_sso_url) | |
return HttpResponseRedirect(discourse_sso_url) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment