diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 18e0475395..26da85679b 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -1753,6 +1753,7 @@ def enable_swagger( security_schemes: Optional[Dict[str, "SecurityScheme"]] = None, security: Optional[List[Dict[str, List[str]]]] = None, oauth2_config: Optional["OAuth2Config"] = None, + persist_authorization: bool = False, ): """ Returns the OpenAPI schema as a JSON serializable dict @@ -1793,6 +1794,8 @@ def enable_swagger( A declaration of which security mechanisms are applied globally across the API. oauth2_config: OAuth2Config, optional The OAuth2 configuration for the Swagger UI. + persist_authorization: bool, optional + Whether to persist authorization data on browser close/refresh. """ from aws_lambda_powertools.event_handler.openapi.compat import model_json from aws_lambda_powertools.event_handler.openapi.models import Server @@ -1871,6 +1874,7 @@ def swagger_handler(): swagger_css, swagger_base_url, oauth2_config, + persist_authorization, ) return Response( diff --git a/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py b/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py index 8b748d9338..85e041f2f5 100644 --- a/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py +++ b/aws_lambda_powertools/event_handler/openapi/swagger_ui/html.py @@ -10,6 +10,7 @@ def generate_swagger_html( swagger_css: str, swagger_base_url: str, oauth2_config: Optional[OAuth2Config], + persist_authorization: bool = False, ) -> str: """ Generate Swagger UI HTML page @@ -28,6 +29,8 @@ def generate_swagger_html( The base URL for Swagger UI oauth2_config: OAuth2Config, optional The OAuth2 configuration. + persist_authorization: bool, optional + Whether to persist authorization data on browser close/refresh. """ # If Swagger base URL is present, generate HTML content with linked CSS and JavaScript files @@ -86,6 +89,7 @@ def generate_swagger_html( SwaggerUIBundle.plugins.DownloadUrl ], withCredentials: true, + persistAuthorization: {str(persist_authorization).lower()}, oauth2RedirectUrl: baseUrl + "?format=oauth2-redirect", }} diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 32789ec09e..aa667f5f16 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -524,12 +524,13 @@ Behind the scenes, the [data validation](#data-validation) feature auto-generate There are some important **caveats** that you should know before enabling it: -| Caveat | Description | -| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 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. | -| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. | -| 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. | -| 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. | +| Caveat | Description | +| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 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. | +| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. | +| 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. | +| 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. | +| Authorization data is **lost** on browser close/refresh | Use `enable_swagger(persist_authorization=True)` to persist authorization data, like OAuath 2.0 access tokens. | ```python hl_lines="12-13" title="enabling_swagger.py" --8<-- "examples/event_handler_rest/src/enabling_swagger.py" diff --git a/tests/functional/event_handler/test_openapi_swagger.py b/tests/functional/event_handler/test_openapi_swagger.py index 11ec0cf24d..a8d9326efc 100644 --- a/tests/functional/event_handler/test_openapi_swagger.py +++ b/tests/functional/event_handler/test_openapi_swagger.py @@ -118,6 +118,18 @@ def test_openapi_swagger_with_rest_api_stage(): assert "ui.specActions.updateUrl('/prod/swagger?format=json')" in result["body"] +def test_openapi_swagger_with_persist_authorization(): + app = APIGatewayRestResolver(enable_validation=True) + app.enable_swagger(persist_authorization=True) + + event = load_event("apiGatewayProxyEvent.json") + event["path"] = "/swagger" + + result = app(event, {}) + assert result["statusCode"] == 200 + assert "persistAuthorization: true" in result["body"] + + def test_openapi_swagger_oauth2_without_powertools_dev(): with pytest.raises(ValueError) as exc: OAuth2Config(app_name="OAuth2 app", client_id="client_id", client_secret="verysecret")