Skip to content

Commit 34db3e8

Browse files
committed
Allow reuse of stored tokens if tokenset scopes are a superset of requested scopes
1 parent 49ae6b4 commit 34db3e8

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

src/auth0_server_python/auth_server/server_client.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -677,10 +677,9 @@ def _find_matching_token_set(
677677
match = None
678678
for token_set in token_sets:
679679
token_set_audience = token_set.get("audience")
680-
matches_audience = token_set_audience == audience
681680
token_set_scopes = set(token_set.get("scope", "").split())
682-
matches_scope = not scope or token_set_scopes == set(scope.split())
683-
if matches_audience and matches_scope:
681+
requested_scopes = set(scope.split()) if scope else set()
682+
if token_set_audience == audience and token_set_scopes.issuperset(requested_scopes):
684683
match = token_set
685684
break
686685

src/auth0_server_python/tests/test_server_client.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,45 @@ async def test_get_access_token_from_store_with_multiple_audiences(mocker):
657657
assert token == "other_token_from_store"
658658
get_refresh_token_mock.assert_not_awaited()
659659

660+
@pytest.mark.asyncio
661+
async def test_get_access_token_from_store_with_a_superset_of_requested_scopes(mocker):
662+
mock_state_store = AsyncMock()
663+
mock_state_store.get.return_value = {
664+
"refresh_token": None,
665+
"token_sets": [
666+
{
667+
"audience": "default",
668+
"access_token": "token_from_store",
669+
"expires_at": int(time.time()) + 500
670+
},
671+
{
672+
"audience": "some_audience",
673+
"access_token": "other_token_from_store",
674+
"scope": "read:foo write:foo read:bar write:bar",
675+
"expires_at": int(time.time()) + 500
676+
}
677+
]
678+
}
679+
680+
client = ServerClient(
681+
domain="auth0.local",
682+
client_id="client_id",
683+
client_secret="client_secret",
684+
transaction_store=AsyncMock(),
685+
state_store=mock_state_store,
686+
secret="some-secret"
687+
)
688+
689+
get_refresh_token_mock = mocker.patch.object(client, "get_token_by_refresh_token")
690+
691+
token = await client.get_access_token(
692+
audience="some_audience",
693+
scope="read:foo read:bar"
694+
)
695+
696+
assert token == "other_token_from_store"
697+
get_refresh_token_mock.assert_not_awaited()
698+
660699
@pytest.mark.asyncio
661700
async def test_get_access_token_for_connection_cached():
662701
mock_state_store = AsyncMock()

0 commit comments

Comments
 (0)