Skip to content

Commit

Permalink
More refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljcollinsuk committed Apr 2, 2024
1 parent fa7e3ef commit cd80876
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 15 deletions.
24 changes: 14 additions & 10 deletions controlpanel/frontend/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,29 @@
UserDetail,
UserList,
)
from controlpanel.oidc import OIDCLoginRequiredMixin, oauth
from controlpanel.oidc import OIDCLoginRequiredMixin, get_code_challenge, oauth


class IndexView(OIDCLoginRequiredMixin, TemplateView):
template_name = "home.html"

def get_template_names(self):
"""
Returns the template to instruct users to authenticate with their Justice
account, unless this has already been captured.
"""
if not self.request.user.justice_email:
return ["justice_email.html"]

return [self.template_name]

def get(self, request, *args, **kwargs):
"""
If the user is a superuser display the home page (containing useful
admin related links). Otherwise, redirect the user to the list of the
tools they currently have available on the platform.
If the user has not authenticated with their Justice account, displays page to
ask them to authenticate, to allow us to capture their email address.
If their Justice email has been captured, normal users are redirected to their
tools. Superusers are displayed the home page (containing useful
admin related links).
"""

if request.user.is_superuser:
Expand All @@ -115,18 +121,16 @@ def get(self, request, *args, **kwargs):
return HttpResponseRedirect(reverse("list-tools"))

def post(self, request):
code_challenge = self._get_code_challenge()
"""
Redirects user to authenticate with Azure EntraID.
"""
redirect_uri = request.build_absolute_uri(reverse("entraid-auth"))
return oauth.azure.authorize_redirect(
request,
redirect_uri,
code_challenge=code_challenge,
code_challenge=get_code_challenge(),
)

def _get_code_challenge(self):
code_verifier = generate_token(64)
digest = hashlib.sha256(code_verifier.encode()).digest()
return base64.urlsafe_b64encode(digest).rstrip(b"=").decode()

class LogoutView(OIDCLogoutView):
def get(self, request):
Expand Down
24 changes: 19 additions & 5 deletions controlpanel/frontend/views/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@


class EntraIdAuthView(OIDCLoginRequiredMixin, View):
"""
This view is used as the callback after a user authenticates with their Justice
identity via Azure EntraID, in order to capture a users Justice email address.
"""
http_method_names = ["get"]

def _authorize_token(self):
"""
Attempts to valiate and return the access token
"""
try:
token = oauth.azure.authorize_access_token(self.request)
except OAuthError as error:
Expand All @@ -24,19 +31,26 @@ def _authorize_token(self):
return token

def get(self, request, *args, **kwargs):
"""
Attempts to retrieve the auth token, and update the user.
"""
token = self._authorize_token()
if not token:
messages.error(self.request, "Something went wrong, please try again soon")
messages.error(request, "Something went wrong, please try again")
return HttpResponseRedirect(reverse("index"))

self.update_user(token=token)
messages.success(
request=request,
message=f"Successfully authenticated with your email {request.user.justice_email}",
)
return HttpResponseRedirect(reverse("index"))

def update_user(self, token):
"""
Update user with details from the ID token returned by the provided EntraID
access token
"""
email = token["userinfo"]["email"]
self.request.user.justice_email = email
self.request.user.save()
messages.success(
request=self.request,
message=f"Successfully authenticated with your email {email}",
)
9 changes: 9 additions & 0 deletions controlpanel/oidc.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Standard library
import base64
import hashlib
from urllib.parse import urlencode

# Third-party
import structlog
from authlib.common.security import generate_token
from authlib.integrations.django_client import OAuth
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
Expand Down Expand Up @@ -99,6 +102,12 @@ def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)


def get_code_challenge():
code_verifier = generate_token(64)
digest = hashlib.sha256(code_verifier.encode()).digest()
return base64.urlsafe_b64encode(digest).rstrip(b"=").decode()


oauth = OAuth()
oauth.register(
name="azure",
Expand Down

0 comments on commit cd80876

Please sign in to comment.