Skip to content

Commit 53134d3

Browse files
gjtorikianclaude
andauthored
feat: add get_jwks_url helper to UserManagement (#644)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7ecb2e9 commit 53134d3

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

src/workos/user_management/_resource.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,6 +2098,23 @@ def delete_user_authorized_application(
20982098

20992099
# @oagen-ignore-start
21002100

2101+
def get_jwks_url(self, client_id: Optional[str] = None) -> str:
2102+
"""Get the JWKS URL used to verify access tokens.
2103+
2104+
Use this when integrating with a JWT library that fetches and caches
2105+
the JWKS itself (e.g. ``PyJWKClient``). For the JWKS document, call
2106+
:meth:`get_jwks` instead.
2107+
2108+
Args:
2109+
client_id: The WorkOS client ID. Defaults to the client's
2110+
configured client_id.
2111+
2112+
Returns:
2113+
The JWKS URL.
2114+
"""
2115+
resolved_client_id = client_id or self._client._require_client_id()
2116+
return f"{self._client.base_url}sso/jwks/{resolved_client_id}"
2117+
21012118
def load_sealed_session(
21022119
self,
21032120
*,
@@ -4266,6 +4283,23 @@ async def delete_user_authorized_application(
42664283

42674284
# @oagen-ignore-start
42684285

4286+
def get_jwks_url(self, client_id: Optional[str] = None) -> str:
4287+
"""Get the JWKS URL used to verify access tokens.
4288+
4289+
Use this when integrating with a JWT library that fetches and caches
4290+
the JWKS itself (e.g. ``PyJWKClient``). For the JWKS document, call
4291+
:meth:`get_jwks` instead.
4292+
4293+
Args:
4294+
client_id: The WorkOS client ID. Defaults to the client's
4295+
configured client_id.
4296+
4297+
Returns:
4298+
The JWKS URL.
4299+
"""
4300+
resolved_client_id = client_id or self._client._require_client_id()
4301+
return f"{self._client.base_url}sso/jwks/{resolved_client_id}"
4302+
42694303
def load_sealed_session(
42704304
self,
42714305
*,

tests/test_inline_helpers.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,35 @@ async def test_sends_code_verifier(self, async_workos, httpx_mock):
271271
request = httpx_mock.get_request()
272272
body = json.loads(request.content)
273273
assert body["code_verifier"] == "test_verifier_abc"
274+
275+
276+
class TestGetJwksUrl:
277+
def test_uses_configured_client_id(self, workos):
278+
url = workos.user_management.get_jwks_url()
279+
assert url == "https://api.workos.com/sso/jwks/client_test"
280+
281+
def test_explicit_client_id_overrides_default(self, workos):
282+
url = workos.user_management.get_jwks_url("client_other")
283+
assert url == "https://api.workos.com/sso/jwks/client_other"
284+
285+
def test_raises_when_no_client_id_configured(self):
286+
from workos import WorkOSClient
287+
from workos._errors import ConfigurationError
288+
289+
client = WorkOSClient(api_key="sk_test_abc")
290+
try:
291+
with pytest.raises(ConfigurationError):
292+
client.user_management.get_jwks_url()
293+
finally:
294+
client.close()
295+
296+
297+
@pytest.mark.asyncio
298+
class TestAsyncGetJwksUrl:
299+
async def test_uses_configured_client_id(self, async_workos):
300+
url = async_workos.user_management.get_jwks_url()
301+
assert url == "https://api.workos.com/sso/jwks/client_test"
302+
303+
async def test_explicit_client_id_overrides_default(self, async_workos):
304+
url = async_workos.user_management.get_jwks_url("client_other")
305+
assert url == "https://api.workos.com/sso/jwks/client_other"

0 commit comments

Comments
 (0)