From 9bfa7464226408f06b01cdaf29d4f299c4e10305 Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Mon, 4 Dec 2023 15:19:15 +0000 Subject: [PATCH] Add support for Pushed Authorization Requests (PAR) --- .../pushed_authorization_requests.py | 30 ++++++++++++ .../test_pushed_authorization_requests.py | 47 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 auth0/authentication/pushed_authorization_requests.py create mode 100644 auth0/test/authentication/test_pushed_authorization_requests.py diff --git a/auth0/authentication/pushed_authorization_requests.py b/auth0/authentication/pushed_authorization_requests.py new file mode 100644 index 00000000..2b543fce --- /dev/null +++ b/auth0/authentication/pushed_authorization_requests.py @@ -0,0 +1,30 @@ +from typing import Any + +from .base import AuthenticationBase + + +class PushedAuthorizationRequests(AuthenticationBase): + """Pushed Authorization Request (PAR) endpoint""" + + def pushed_authorization_request( + self, response_type: str, redirect_uri: str, **kwargs + ) -> Any: + """Send a Pushed Authorization Request (PAR). + + Args: + response_type (str): Indicates to Auth0 which OAuth 2.0 flow you want to perform. + redirect_uri (str): The URL to which Auth0 will redirect the browser after authorization has been granted + by the user. + **kwargs: Other fields to send along with the PAR. + + See: https://www.rfc-editor.org/rfc/rfc9126.html + """ + return self.authenticated_post( + f"{self.protocol}://{self.domain}/oauth/par", + data={ + "client_id": self.client_id, + "response_type": response_type, + "redirect_uri": redirect_uri, + **kwargs, + }, + ) diff --git a/auth0/test/authentication/test_pushed_authorization_requests.py b/auth0/test/authentication/test_pushed_authorization_requests.py new file mode 100644 index 00000000..8dee0b78 --- /dev/null +++ b/auth0/test/authentication/test_pushed_authorization_requests.py @@ -0,0 +1,47 @@ +import unittest +from unittest import mock + +from ...authentication.pushed_authorization_requests import PushedAuthorizationRequests + + +class TestRevokeToken(unittest.TestCase): + @mock.patch("auth0.rest.RestClient.post") + def test_par(self, mock_post): + a = PushedAuthorizationRequests("my.domain.com", "cid", client_secret="sh!") + a.pushed_authorization_request( + response_type="code", redirect_uri="https://example.com/callback" + ) + + args, kwargs = mock_post.call_args + + self.assertEqual(args[0], "https://my.domain.com/oauth/par") + self.assertEqual( + kwargs["data"], + { + "client_id": "cid", + "client_secret": "sh!", + "response_type": "code", + "redirect_uri": "https://example.com/callback", + }, + ) + + @mock.patch("auth0.rest.RestClient.post") + def test_par_custom_params(self, mock_post): + a = PushedAuthorizationRequests("my.domain.com", "cid", client_secret="sh!") + a.pushed_authorization_request( + response_type="code", redirect_uri="https://example.com/callback", foo="bar" + ) + + args, kwargs = mock_post.call_args + + self.assertEqual(args[0], "https://my.domain.com/oauth/par") + self.assertEqual( + kwargs["data"], + { + "client_id": "cid", + "client_secret": "sh!", + "response_type": "code", + "redirect_uri": "https://example.com/callback", + "foo": "bar", + }, + )