From ba032e8d7fb22002af915f74de8122c60d2b33e2 Mon Sep 17 00:00:00 2001 From: Snehil Kishore Date: Wed, 4 Jun 2025 13:48:47 +0530 Subject: [PATCH] fix: handle `authorization_details` in back_channel_login (#695) ### Changes - Add support for `authorization_details `parameter in back_channel_login method - Serialize `authorization_details` to JSON strings before sending requests - Update docstrings to clarify expected formats for `authorization_details` - Modify tests to expect serialized JSON strings for `authorization_details` ### References - [Back-Channel Login](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-initiated-backchannel-authentication-flow/user-authentication-with-ciba) - [Back Channel Login Auth API](https://auth0.com/docs/api/authentication/login/start-back-channel-login) ### Testing - [x] This change adds test coverage - [x] This change has been tested on the latest version of the platform/language or why not ### Contributor Checklist - [x] I agree to adhere to the [Auth0 General Contribution Guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md). - [x] I agree to uphold the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md). --- .github/workflows/test.yml | 4 +- auth0/authentication/back_channel_login.py | 38 +++++++++++++++---- .../authentication/test_back_channel_login.py | 20 +++++----- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 020bad5f..8db7e526 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,7 @@ jobs: strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - name: Checkout code @@ -82,4 +82,4 @@ jobs: name: Upload coverage uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # pin@5.4.2 with: - token: ${{ secrets.CODECOV_TOKEN }} + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/auth0/authentication/back_channel_login.py b/auth0/authentication/back_channel_login.py index 1dc7d69f..e275cde4 100644 --- a/auth0/authentication/back_channel_login.py +++ b/auth0/authentication/back_channel_login.py @@ -1,13 +1,20 @@ -from typing import Any +from typing import Any, Optional, Union, List, Dict from .base import AuthenticationBase +import json + class BackChannelLogin(AuthenticationBase): """Back-Channel Login endpoint""" def back_channel_login( - self, binding_message: str, login_hint: str, scope: str, **kwargs + self, + binding_message: str, + login_hint: str, + scope: str, + authorization_details: Optional[Union[str, List[Dict]]] = None, + **kwargs ) -> Any: """Send a Back-Channel Login. @@ -15,24 +22,39 @@ def back_channel_login( binding_message (str): Human-readable string displayed on both the device calling /bc-authorize and the user’s authentication device to ensure the user is approves the correct request. - login_hint (str): String containing information about the user to contact for authentication. + login_hint (str): JSON string containing user details for authentication in the iss_sub format.Ensure + serialization before passing. scope(str): "openid" is a required scope.Multiple scopes are separated with whitespace. - **kwargs: Other fields to send along with the PAR. + authorization_details (str, list of dict, optional): JSON string or a list of dictionaries representing + Rich Authorization Requests (RAR) details to include in the CIBA request. + + **kwargs: Other fields to send along with the request. Returns: auth_req_id, expires_in, interval """ - return self.authenticated_post( - f"{self.protocol}://{self.domain}/bc-authorize", - data={ + + data = { "client_id": self.client_id, "binding_message": binding_message, "login_hint": login_hint, "scope": scope, **kwargs, - }, + } + + if authorization_details is not None: + if isinstance(authorization_details, str): + data["authorization_details"] = authorization_details + elif isinstance(authorization_details, list): + data["authorization_details"] = json.dumps(authorization_details) + + data.update(kwargs) + + return self.authenticated_post( + f"{self.protocol}://{self.domain}/bc-authorize", + data = data, headers={"Content-Type": "application/x-www-form-urlencoded"}, ) diff --git a/auth0/test/authentication/test_back_channel_login.py b/auth0/test/authentication/test_back_channel_login.py index 18206b17..049477ac 100644 --- a/auth0/test/authentication/test_back_channel_login.py +++ b/auth0/test/authentication/test_back_channel_login.py @@ -80,7 +80,7 @@ def test_with_authorization_details(self, mock_post): g = BackChannelLogin("my.domain.com", "cid", client_secret="clsec") g.back_channel_login( binding_message="This is a binding message.", - login_hint={"format": "iss_sub", "iss": "https://my.domain.auth0.com/", "sub": "auth0|USER_ID"}, + login_hint= json.dumps({"format": "iss_sub", "iss": "https://my.domain.auth0.com/", "sub": "auth0|USER_ID"}), scope="openid", authorization_details=[ { @@ -106,9 +106,9 @@ def test_with_authorization_details(self, mock_post): "client_id": "cid", "client_secret": "clsec", "binding_message": "This is a binding message.", - "login_hint": {"format": "iss_sub", "iss": "https://my.domain.auth0.com/", "sub": "auth0|USER_ID" }, + "login_hint": json.dumps({"format": "iss_sub", "iss": "https://my.domain.auth0.com/", "sub": "auth0|USER_ID"}), "scope": "openid", - "authorization_details": [ + "authorization_details": json.dumps([ { "type":"payment_initiation","locations":["https://example.com/payments"], "instructedAmount": @@ -122,17 +122,17 @@ def test_with_authorization_details(self, mock_post): "iban":"DE021001001093071118603" }, "remittanceInformationUnstructured":"Ref Number Merchant" - }], + } + ]), } actual_data = kwargs["data"] - + self.assertEqual(args[0], "https://my.domain.com/bc-authorize") - + self.assertEqual( - json.dumps(actual_data, sort_keys=True), - json.dumps(expected_data, sort_keys=True) + actual_data, + expected_data, + "Request data does not match expected data after JSON serialization." ) - -