diff --git a/pretix_oidc/auth.py b/pretix_oidc/auth.py index 38c117113d5d3970385b4c7344e5a684000bf21d..8111d6dafa76bbeb93e5e7cf21f1096db64ebac2 100644 --- a/pretix_oidc/auth.py +++ b/pretix_oidc/auth.py @@ -1,4 +1,5 @@ import logging +import time from django.urls import reverse from oic import rndstr from oic.oic import Client @@ -57,17 +58,24 @@ class OIDCAuthBackend(BaseAuthBackend): return self.title def authentication_url(self, request): - request.session["oidc_state"] = rndstr() - request.session["oidc_nonce"] = rndstr() + oidc_state = rndstr() + oidc_nonce = rndstr() + request.session["oidc_state"] = { + oidc_state: { + "nonce": oidc_nonce, + "next": "", + "generated_on": int(time.time()), + } + } auth_req = self.client.construct_AuthorizationRequest( request_args={ "client_id": self.client.client_id, "response_type": "code", "scope": self.scopes, - "nonce": request.session["oidc_nonce"], + "nonce": oidc_nonce, "redirect_uri": self.redirect_uri(request), - "state": request.session["oidc_state"], + "state": oidc_state, } ) @@ -76,6 +84,9 @@ class OIDCAuthBackend(BaseAuthBackend): def redirect_uri(self, request): return request.build_absolute_uri(reverse("plugins:pretix_oidc:oidc_callback")) + def get_next_url(self, request): + return request.session.pop("oidc_next_url", None) + def process_callback(self, request): auth_response = self.client.parse_response( AuthorizationResponse, @@ -83,12 +94,24 @@ class OIDCAuthBackend(BaseAuthBackend): sformat="urlencoded", ) - # if auth_response is not AuthorizationResponse: - # raise Exception('Invalid authorization response') + request.session["oidc_next_url"] = None + oidc_state = request.session.pop("oidc_state", None) + response_state = auth_response.get("state", None) + + if not oidc_state or not response_state: + return [None, None] + + if response_state not in oidc_state: + return [None, None] - if auth_response["state"] != request.session["oidc_state"]: + if auth_response["nonce"] != oidc_state[response_state]["nonce"]: return [None, None] + if oidc_state[response_state]["generated_on"] < time.time() + 5 * 60: + return [None, None] + + request.session["oidc_next_url"] = oidc_state[response_state]["next"] + access_token_response = self.client.do_access_token_request( state=auth_response["state"], scope=self.scopes,