Skip to content

Commit 4ba7b28

Browse files
authored
Remove 'aud' field checking and fields (#171)
Removing audience checking is safe, in that we remain fully spec compliant. The field is optional for servers and optional for clients to validate even when it's present. The source for the expected audience value is typically the same as that of the client credentials, and therefore there is no additional safety (e.g., against credential confusion bugs) being added by requiring this field. It only serves to add surface area and therefore complexity. This is a breaking change, in that the interfaces for the library are changing to remove a field.
1 parent f00718e commit 4ba7b28

File tree

12 files changed

+22
-76
lines changed

12 files changed

+22
-76
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Changes
2+
-------
3+
4+
- The ``aud`` field of token introspect responses is no longer validated and
5+
fields associated with it have been removed. This includes changes to
6+
function and class initializer signatures.
7+
8+
- The ``expected_audience`` field is no longer supported in ``AuthState`` and
9+
``TokenChecker``. It has been removed from the initializers for these
10+
classes.
11+
12+
- ``globus_auth_client_name`` has been removed from ``ActionProviderBlueprint``.
13+
14+
- ``client_name`` has been removed from ``add_action_routes_to_blueprint``.

examples/watchasay/app/config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@
33
our_scope = (
44
"https://auth.globus.org/scopes/d3a66776-759f-4316-ba55-21725fe37323/action_all"
55
)
6-
token_audience = None

examples/watchasay/app/provider.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,6 @@ def create_app():
233233
blueprint=skeleton_blueprint,
234234
client_id=config.client_id,
235235
client_secret=config.client_secret,
236-
client_name=None,
237236
provider_description=provider_description,
238237
action_run_callback=action_run,
239238
action_status_callback=action_status,

examples/whattimeisitrightnow/app/app.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@
2626
app = Flask(__name__)
2727
assign_json_provider(app)
2828

29-
token_checker = TokenChecker(
30-
config.client_id, config.client_secret, [config.our_scope], config.token_audience
31-
)
29+
token_checker = TokenChecker(config.client_id, config.client_secret, [config.our_scope])
3230

3331
COMPLETE_STATES = (ActionStatusValue.SUCCEEDED, ActionStatusValue.FAILED)
3432
INCOMPLETE_STATES = (ActionStatusValue.ACTIVE, ActionStatusValue.INACTIVE)
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
client_id = "16e16447-209a-4825-ae19-25e279d91642"
22
client_secret = "SECRET"
33
our_scope = "https://auth.globus.org/scopes/16e16447-209a-4825-ae19-25e279d91642/action_all_with_groups"
4-
token_audience = None

src/globus_action_provider_tools/authentication.py

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,12 @@ def __init__(
5050
auth_client: ConfidentialAppAuthClient,
5151
bearer_token: str,
5252
expected_scopes: Iterable[str],
53-
expected_audience: str | None = None,
5453
) -> None:
5554
self.auth_client = auth_client
5655
self.bearer_token = bearer_token
5756
self.sanitized_token = self.bearer_token[-7:]
5857
self.expected_scopes = expected_scopes
5958

60-
# Default to client_id unless expected_audience has been explicitly
61-
# provided (supporting legacy clients that may have a different
62-
# client name registered with Auth)
63-
if expected_audience is None:
64-
self.expected_audience = auth_client.client_id
65-
else:
66-
self.expected_audience = expected_audience
6759
self.errors: list[Exception] = []
6860
self._groups_client: GroupsClient | None = None
6961

@@ -99,12 +91,6 @@ def introspect_token(self) -> GlobusHTTPResponse | None:
9991
"Token invalid scopes. "
10092
f"Expected one of: {self.expected_scopes}, got: {scopes}"
10193
)
102-
aud = resp.get("aud", [])
103-
if self.expected_audience not in aud:
104-
raise AssertionError(
105-
"Token not intended for us: "
106-
f"audience={aud}, expected={self.expected_audience}"
107-
)
10894
if "identity_set" not in resp:
10995
raise AssertionError("Missing identity_set")
11096
except AssertionError as err:
@@ -366,27 +352,16 @@ def check_authorization(
366352

367353
class TokenChecker:
368354
def __init__(
369-
self,
370-
client_id: str,
371-
client_secret: str,
372-
expected_scopes: Iterable[str],
373-
expected_audience: str | None = None,
355+
self, client_id: str, client_secret: str, expected_scopes: Iterable[str]
374356
) -> None:
375357
self.auth_client = ConfidentialAppAuthClient(client_id, client_secret)
376358
self.default_expected_scopes = frozenset(expected_scopes)
377359

378-
if expected_audience is None:
379-
self.expected_audience = client_id
380-
else:
381-
self.expected_audience = expected_audience
382-
383360
def check_token(
384361
self, access_token: str, expected_scopes: Iterable[str] | None = None
385362
) -> AuthState:
386363
if expected_scopes is None:
387364
expected_scopes = self.default_expected_scopes
388365
else:
389366
expected_scopes = frozenset(expected_scopes)
390-
return AuthState(
391-
self.auth_client, access_token, expected_scopes, self.expected_audience
392-
)
367+
return AuthState(self.auth_client, access_token, expected_scopes)

src/globus_action_provider_tools/flask/api_helpers.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ def add_action_routes_to_blueprint(
106106
blueprint: flask.Blueprint,
107107
client_id: str,
108108
client_secret: str,
109-
client_name: str | None,
110109
provider_description: ActionProviderDescription,
111110
action_run_callback: ActionRunCallback,
112111
action_status_callback: ActionStatusCallback,
@@ -142,13 +141,6 @@ def add_action_routes_to_blueprint(
142141
A Globus Auth generated ``client_secret`` which will be used when validating input
143142
request tokens.
144143
145-
``client_name`` (*string*) Most commonly, this will be a None value. In the rare,
146-
legacy case where a name has been associated with a client_id, it can be provided
147-
here. If you are not aware of a name associated with your client_id, it most likely
148-
doesn't have one and the value should be None. This will be passed to the
149-
(:class:`TokenChecker<globus_action_provider_tools.authentication>`) as the
150-
`expected_audience`.
151-
152144
``provider_description`` (:class:`ActionProviderDescription\
153145
<globus_action_provider_tools.data_types>`)
154146
A structure describing the provider to be returned by the provider introspection
@@ -190,7 +182,6 @@ def add_action_routes_to_blueprint(
190182
client_id=client_id,
191183
client_secret=client_secret,
192184
expected_scopes=all_accepted_scopes,
193-
expected_audience=client_name,
194185
)
195186

196187
assign_json_provider(blueprint)

src/globus_action_provider_tools/flask/apt_blueprint.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ def __init__(
5353
self,
5454
provider_description: ActionProviderDescription,
5555
*args,
56-
globus_auth_client_name: t.Optional[str] = None,
5756
additional_scopes: t.Iterable[str] = (),
5857
action_repository: t.Optional[AbstractActionRepository] = None,
5958
request_lifecycle_hooks: t.Optional[t.List[t.Any]] = None,
@@ -66,13 +65,6 @@ def __init__(
6665
:param provider_description: A Provider Description which will be
6766
returned from introspection calls to this Blueprint.
6867
69-
:param globus_auth_client_name: The name of the Globus Auth Client (also
70-
known as the resource server name). This will be used to validate the
71-
intended audience for tokens passed to the operations on this
72-
Blueprint. By default, the client id will be used for checkign audience,
73-
and unless the client has explicitly been given a resource server name
74-
in Globus Auth, this will be proper behavior.
75-
7668
:param additional_scopes: Additional scope strings the Action Provider
7769
should allow scopes in addition to the one specified by the
7870
``globus_auth_scope`` value of the input provider description. Only
@@ -93,7 +85,6 @@ def __init__(
9385
provider_description,
9486
config=config,
9587
)
96-
self.globus_auth_client_name = globus_auth_client_name
9788
self.additional_scopes = additional_scopes
9889
self.config = config
9990

@@ -170,7 +161,6 @@ def _create_token_checker(self, setup_state: blueprints.BlueprintSetupState):
170161
client_id=client_id,
171162
client_secret=client_secret,
172163
expected_scopes=scopes,
173-
expected_audience=self.globus_auth_client_name,
174164
)
175165

176166
def _action_introspect(self):

tests/conftest.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ def config():
2525
"client_id": canned_responses.mock_client_id(),
2626
"client_secret": canned_responses.mock_client_secret(),
2727
"expected_scopes": (canned_responses.mock_scope(),),
28-
"expected_audience": canned_responses.mock_expected_audience(),
2928
}
3029

3130

@@ -53,7 +52,6 @@ def auth_state(MockAuthClient, config, monkeypatch) -> AuthState:
5352
client_id=config["client_id"],
5453
client_secret=config["client_secret"],
5554
expected_scopes=config["expected_scopes"],
56-
expected_audience=config["expected_audience"],
5755
)
5856
auth_state = checker.check_token("NOT_A_TOKEN")
5957

tests/data/canned_responses.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,3 @@ def mock_client_secret():
117117

118118
def mock_effective_identity() -> str:
119119
return "00000000-0000-0000-0000-000000000000"
120-
121-
122-
def mock_expected_audience() -> str:
123-
return "action_provider_tools_automated_tests"

0 commit comments

Comments
 (0)