aws / aws/serverless-application-model
HttpApi: explicit AuthorizationScopes: [] is silently overridden by the authorizer's default scopes
- Dominant language
- Python
- Stars
- 9.6k
- Forks
- 2.5k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 7
Description
### Describe the bug
For `AWS::Serverless::HttpApi`, setting `Auth.AuthorizationScopes: []` on an individual function/event's `Auth` block is documented and (for `AWS::Serverless::Api`, i.e. REST APIs) implemented to mean "require no scopes for this method, overriding the named authorizer's default `AuthorizationScopes`."
For HTTP APIs this override is silently dropped: the authorizer's default scopes are applied anyway, as if `AuthorizationScopes` had not been set at all.
### Root cause
`OpenApiEditor.add_auth_to_method` (`samtranslator/open_api/open_api.py`):
```python
authorization_scopes = auth.get("AuthorizationScopes", [])
```
defaults an unset value to `[]`. This is then passed into `_set_method_authorizer`, which checks it with:
```python
if authorization_scopes:
method_authorization_scopes = authorization_scopes
```
Since `[]` is falsy, this can't distinguish "the user didn't set `AuthorizationScopes`" from "the user explicitly set `AuthorizationScopes: []`" — both take the "not set" branch, so the authorizer's own default `AuthorizationScopes` is used instead of the empty override.
The REST API equivalent, `SwaggerEditor.add_auth_to_method`/`_set_method_authorizer` in `samtranslator/swagger/swagger.py`, gets this right:
```python
method_scopes = auth and auth.get("AuthorizationScopes") # None, not [], when unset
...
if method_scopes is not None:
method_auth_scopes = method_scopes
```
which correctly distinguishes "unset" (`None`) from "explicitly cleared" (`[]`).
### Reproduction
```yaml
Resources:
MyApi:
Type: AWS::Serverless::HttpApi
Properties:
Auth:
Authorizers:
MyAuth:
JwtConfiguration: {...}
IdentitySource: $request.header.Authorization
AuthorizationScopes: [default.delete, default.update]
MyFn:
Type: AWS::Serverless::Function
Properties:
...
Events:
Api:
Type: HttpApi
Properties:
ApiId: !Ref MyApi
Path: /x
Method: get
Auth:
Authorizer: MyAuth
AuthorizationScopes: []
```
### Expected behavior
The generated OpenAPI `security` block for `GET /x` should be `{"MyAuth": []}` — no required scopes, matching what the equivalent REST API (`AWS::Serverless::Api`) template already produces (see `tests/translator/input/api_with_auth_with_default_scopes.yaml`, cases `CognitoDefaultScopesNone` / `CognitoDefaultAuthDefaultScopesNone`).
### Actual behavior
The generated `security` block is `{"MyAuth": ["default.delete", "default.update"]}` — the authorizer's default scopes are enforced anyway, silently ignoring the explicit override. This causes requests the user intended to allow without those scopes to be rejected by API Gateway.
### Fix
PR incoming.
Contributor guide
Research direction
Start in samtranslator/open_api/open_api.py at OpenApiEditor.add_auth_to_method and _set_method_authorizer, comparing the REST equivalent in samtranslator/swagger/swagger.py. Inspect the documented cases in tests/translator/input/api_with_auth_with_default_scopes.yaml and run the relevant HTTP API authorization-scope tests; done means an explicit [] produces an empty security scope while an unset value preserves authorizer defaults.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 82/100