Skip to content

Commit 13f2eb0

Browse files
vilmar-hillowDmitry Supranovichazmeuk
authored
fix(client): Added client_id parameter to AssertionClient (#476)
* Added client_id parameter to AssertionClient Per https://datatracker.ietf.org/doc/html/rfc7521#section-4.1, client_id parameter, although optional, can still be passed when using assertions as authorization grants. Adding a way to pass that id to refresh token body. * chore: prek autoupdate --------- Co-authored-by: Dmitry Supranovich <[email protected]> Co-authored-by: Éloi Rivard <[email protected]>
1 parent dde5b7a commit 13f2eb0

6 files changed

Lines changed: 58 additions & 0 deletions

File tree

‎authlib/integrations/httpx_client/assertion_client.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def __init__(
3131
claims=None,
3232
token_placement="header",
3333
scope=None,
34+
client_id=None,
3435
**kwargs,
3536
):
3637
client_kwargs = extract_client_kwargs(kwargs)
@@ -47,6 +48,7 @@ def __init__(
4748
claims=claims,
4849
token_placement=token_placement,
4950
scope=scope,
51+
client_id=client_id,
5052
**kwargs,
5153
)
5254

@@ -88,6 +90,7 @@ def __init__(
8890
claims=None,
8991
token_placement="header",
9092
scope=None,
93+
client_id=None,
9194
**kwargs,
9295
):
9396
client_kwargs = extract_client_kwargs(kwargs)
@@ -104,6 +107,7 @@ def __init__(
104107
claims=claims,
105108
token_placement=token_placement,
106109
scope=scope,
110+
client_id=client_id,
107111
**kwargs,
108112
)
109113

‎authlib/integrations/requests_client/assertion_session.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def __init__(
3939
claims=None,
4040
token_placement="header",
4141
scope=None,
42+
client_id=None,
4243
default_timeout=None,
4344
leeway=60,
4445
**kwargs,
@@ -57,6 +58,7 @@ def __init__(
5758
claims=claims,
5859
token_placement=token_placement,
5960
scope=scope,
61+
client_id=client_id,
6062
leeway=leeway,
6163
**kwargs,
6264
)

‎authlib/oauth2/rfc7521/client.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(
2525
claims=None,
2626
token_placement="header",
2727
scope=None,
28+
client_id=None,
2829
leeway=60,
2930
**kwargs,
3031
):
@@ -46,6 +47,7 @@ def __init__(
4647
self.audience = audience
4748
self.claims = claims
4849
self.scope = scope
50+
self.client_id = client_id
4951
if self.token_auth_class is not None:
5052
self.token_auth = self.token_auth_class(None, token_placement, self)
5153
self._kwargs = kwargs
@@ -79,6 +81,8 @@ def refresh_token(self):
7981
}
8082
if self.scope:
8183
data["scope"] = self.scope
84+
if self.client_id:
85+
data["client_id"] = self.client_id
8286

8387
return self._refresh_token(data)
8488

‎docs/upgrades/changelog.rst‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ Version 1.7.0
9090
- RFC7523 accepts the issuer URL as a valid audience. :issue:`730`
9191
- Fix ``InvalidTokenError`` extra attributes being wrapped instead of passed as
9292
individual key=value pairs in the ``WWW-Authenticate`` header. :pr:`872`
93+
- Add optional ``client_id`` parameter to ``AssertionClient`` (and its
94+
``AssertionSession`` / httpx wrappers) so it can be sent in the token
95+
endpoint request body per :rfc:`7521` §4.1 and :rfc:`6749` §3.2.1. :pr:`476`
9396

9497
Upgrade Guide: :ref:`joserfc_upgrade`.
9598

‎tests/clients/test_httpx/test_assertion_client.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,28 @@ def verifier(request):
5252
client.get("https://provider.test")
5353

5454

55+
def test_client_id():
56+
"""client_id is included in the token request body when provided."""
57+
58+
def verifier(request):
59+
if str(request.url) == "https://provider.test/token":
60+
content = request.form
61+
assert "assertion" in content
62+
assert content["client_id"] == "my-client"
63+
64+
with AssertionClient(
65+
"https://provider.test/token",
66+
issuer="foo",
67+
subject="foo",
68+
audience="foo",
69+
alg="HS256",
70+
key="secret",
71+
client_id="my-client",
72+
transport=WSGITransport(MockDispatch(default_token, assert_func=verifier)),
73+
) as client:
74+
client.get("https://provider.test")
75+
76+
5577
def test_without_alg():
5678
with AssertionClient(
5779
"https://provider.test/token",

‎tests/clients/test_httpx/test_async_assertion_client.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,29 @@ async def verifier(request):
5454
await client.get("https://provider.test")
5555

5656

57+
@pytest.mark.asyncio
58+
async def test_client_id():
59+
"""client_id is included in the token request body when provided."""
60+
61+
async def verifier(request):
62+
if str(request.url) == "https://provider.test/token":
63+
content = await request.body()
64+
assert b"assertion=" in content
65+
assert b"client_id=my-client" in content
66+
67+
async with AsyncAssertionClient(
68+
"https://provider.test/token",
69+
issuer="foo",
70+
subject="foo",
71+
audience="foo",
72+
alg="HS256",
73+
key="secret",
74+
client_id="my-client",
75+
transport=ASGITransport(AsyncMockDispatch(default_token, assert_func=verifier)),
76+
) as client:
77+
await client.get("https://provider.test")
78+
79+
5780
@pytest.mark.asyncio
5881
async def test_without_alg():
5982
async with AsyncAssertionClient(

0 commit comments

Comments
 (0)