patrickscottbest / django-commento-sso

A Django Single Sign-On Module for the Popular Commento.io platform
MIT License
2 stars 0 forks source link

Suggested refactoring for views.py #3

Open Wayne-Fagan opened 4 years ago

Wayne-Fagan commented 4 years ago

Hi Patrick, I have refactored the logic in your views.py so that it is a little more Pythonic. The main changes are that I've returned early further up the stack, and updated the formatting. I've left your comments in for completeness.

from django.shortcuts import render, redirect
from django_commento_sso.conf import settings
from django.http import HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth import auth

#import hashlib
import hmac
import json
import logging
logger = logging.getLogger(__name__)

def get_user(request):
    """
    Return active user
    """
    if not hasattr(request, "_cached_user"):
        request._cached_user = auth.get_user(request)
    return request._cached_user

def sso(request):
    """
    Process SSO request
    """
    if settings.SECRET_KEY is None:
        logger.error("django_commento_sso - COMMENTO_SECRET_KEY not found in settings.py")
        return HttpResponse(status=204)

    if not request.GET["token"]:
        return HttpResponse(status=204)
    logger.debug(f"Token as received {request.GET['token']}")

    if not request.GET["hmac"]:
        return HttpResponse(status=204)
    logger.debug(f"Hmac as received {request.GET['hmac']}")

    received_hmac_bytes = bytes.fromhex(request.GET["hmac"])
    token_bytes = bytes.fromhex(request.GET["token"])

    secret_key_bytes = bytes.fromhex(settings.COMMENTO_SECRET_KEY)
    expected_hmac_bytes = hmac.digest(secret_key_bytes, token_bytes, "sha256")
    logger.debug(f"Expected hmac was {expected_hmac_bytes.hex()}")

    is_hmac_true = expected_hmac_bytes == received_hmac_bytes

    if not is_hmac_true:
        # Spoofed token attempt or error
        logger.warning("django_commento_sso SSO HMAC comparison - No match")
        return HttpResponse(status=404)
    logger.debug("HMAC comparison of token - match")

    if not request.user.is_authenticated:
        #return redirect('%s?next=%s%s?hmac=%s&token=%s' % (settings.LOGIN_URL, request.get_host(), request.get_full_path(),request.GET['hmac'],request.GET['token']))
        url = f"{settings.LOGIN_URL}?next={request.get_host()}{request.get_full_path()}?hmac={request.GET['hmac']}&token={request.GET['token']}"
        return redirect(url)
    logger.info(f"django_commento_sso SSO Success for User {request.user.username}")

    if not request.user.email:
        logger.error("django_commento_sso User must have email for Commento SSO")
        return False

    # try:
    #     uid = request.session['mid']
    #     userobj = User.objects.get(id=uid)
    # except User.DoesNotExist as e:
      #     logger.error('Error, user does not exist', e)
    #     return false
    # #
    # thisUser = User.objects.get(username=request.user.username).first()
    # #avoid simplelazyobject

    payload = {
        "token": request.GET["token"],
        "email": request.user.email,
        "name": settings.COMMENTO_USER_NAME_FUNCTION(get_user(request)),
    }

    if settings.COMMENTO_USER_LINK_FUNCTION:
        payload["link"] = settings.COMMENTO_USER_LINK_FUNCTION(get_user(request))
    if settings.COMMENTO_USER_PHOTO_FUNCTION:
        payload["photo"] = settings.COMMENTO_USER_PHOTO_FUNCTION(get_user(request))

    payload_hmac_hex = (hmac.digest(secret_key_bytes, bytes(json.dumps(payload), "utf8"), "sha256")).hex()
    payload_hex = bytes(json.dumps(payload), "utf8").hex()

    url = f"https://commento.io/api/oauth/sso/callback?payload={payload_hex}&hmac={payload_hmac_hex}"
    return redirect(url)
patrickscottbest commented 3 years ago

Wayne - this is awesome. Thanks for this.