Skip to content

Commit 97904cf

Browse files
feat(event_handler): add support for persisting authorization session in OpenAPI (aws-powertools#4312)
* feat(event_handler): add support for persisting authorization data in Swagger UI * docs(event_handler): update docs for Swagger UI persist authorization feature --------- Signed-off-by: Nicolas Lykke Iversen <[email protected]> Co-authored-by: Leandro Damascena <[email protected]>
1 parent 5b15744 commit 97904cf

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

Diff for: aws_lambda_powertools/event_handler/api_gateway.py

+4
Original file line numberDiff line numberDiff line change
@@ -1753,6 +1753,7 @@ def enable_swagger(
17531753
security_schemes: Optional[Dict[str, "SecurityScheme"]] = None,
17541754
security: Optional[List[Dict[str, List[str]]]] = None,
17551755
oauth2_config: Optional["OAuth2Config"] = None,
1756+
persist_authorization: bool = False,
17561757
):
17571758
"""
17581759
Returns the OpenAPI schema as a JSON serializable dict
@@ -1793,6 +1794,8 @@ def enable_swagger(
17931794
A declaration of which security mechanisms are applied globally across the API.
17941795
oauth2_config: OAuth2Config, optional
17951796
The OAuth2 configuration for the Swagger UI.
1797+
persist_authorization: bool, optional
1798+
Whether to persist authorization data on browser close/refresh.
17961799
"""
17971800
from aws_lambda_powertools.event_handler.openapi.compat import model_json
17981801
from aws_lambda_powertools.event_handler.openapi.models import Server
@@ -1871,6 +1874,7 @@ def swagger_handler():
18711874
swagger_css,
18721875
swagger_base_url,
18731876
oauth2_config,
1877+
persist_authorization,
18741878
)
18751879

18761880
return Response(

Diff for: aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def generate_swagger_html(
1010
swagger_css: str,
1111
swagger_base_url: str,
1212
oauth2_config: Optional[OAuth2Config],
13+
persist_authorization: bool = False,
1314
) -> str:
1415
"""
1516
Generate Swagger UI HTML page
@@ -28,6 +29,8 @@ def generate_swagger_html(
2829
The base URL for Swagger UI
2930
oauth2_config: OAuth2Config, optional
3031
The OAuth2 configuration.
32+
persist_authorization: bool, optional
33+
Whether to persist authorization data on browser close/refresh.
3134
"""
3235

3336
# If Swagger base URL is present, generate HTML content with linked CSS and JavaScript files
@@ -86,6 +89,7 @@ def generate_swagger_html(
8689
SwaggerUIBundle.plugins.DownloadUrl
8790
],
8891
withCredentials: true,
92+
persistAuthorization: {str(persist_authorization).lower()},
8993
oauth2RedirectUrl: baseUrl + "?format=oauth2-redirect",
9094
}}
9195

Diff for: docs/core/event_handler/api_gateway.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -524,12 +524,13 @@ Behind the scenes, the [data validation](#data-validation) feature auto-generate
524524

525525
There are some important **caveats** that you should know before enabling it:
526526

527-
| Caveat | Description |
528-
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
529-
| Swagger UI is **publicly accessible by default** | When using `enable_swagger` method, you can [protect sensitive API endpoints by implementing a custom middleware](#customizing-swagger-ui) using your preferred authorization mechanism. |
530-
| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. |
531-
| You need to expose a **new route** | You'll need to expose the following path to Lambda: `/swagger`; ignore if you're routing this path already. |
532-
| JS and CSS files are **embedded within Swagger HTML** | If you are not using an external CDN to serve Swagger UI assets, we embed JS and CSS directly into the HTML. To enhance performance, please consider enabling the `compress` option to minimize the size of HTTP requests. |
527+
| Caveat | Description |
528+
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
529+
| Swagger UI is **publicly accessible by default** | When using `enable_swagger` method, you can [protect sensitive API endpoints by implementing a custom middleware](#customizing-swagger-ui) using your preferred authorization mechanism. |
530+
| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. |
531+
| You need to expose a **new route** | You'll need to expose the following path to Lambda: `/swagger`; ignore if you're routing this path already. |
532+
| JS and CSS files are **embedded within Swagger HTML** | If you are not using an external CDN to serve Swagger UI assets, we embed JS and CSS directly into the HTML. To enhance performance, please consider enabling the `compress` option to minimize the size of HTTP requests. |
533+
| Authorization data is **lost** on browser close/refresh | Use `enable_swagger(persist_authorization=True)` to persist authorization data, like OAuath 2.0 access tokens. |
533534

534535
```python hl_lines="12-13" title="enabling_swagger.py"
535536
--8<-- "examples/event_handler_rest/src/enabling_swagger.py"

Diff for: tests/functional/event_handler/test_openapi_swagger.py

+12
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ def test_openapi_swagger_with_rest_api_stage():
118118
assert "ui.specActions.updateUrl('/prod/swagger?format=json')" in result["body"]
119119

120120

121+
def test_openapi_swagger_with_persist_authorization():
122+
app = APIGatewayRestResolver(enable_validation=True)
123+
app.enable_swagger(persist_authorization=True)
124+
125+
event = load_event("apiGatewayProxyEvent.json")
126+
event["path"] = "/swagger"
127+
128+
result = app(event, {})
129+
assert result["statusCode"] == 200
130+
assert "persistAuthorization: true" in result["body"]
131+
132+
121133
def test_openapi_swagger_oauth2_without_powertools_dev():
122134
with pytest.raises(ValueError) as exc:
123135
OAuth2Config(app_name="OAuth2 app", client_id="client_id", client_secret="verysecret")

0 commit comments

Comments
 (0)