Closed nlykkei closed 6 months ago
Hello @nlykkei! We currently do not support authentication and authorization in our OpenAPI utility. We already have an issue open (https://github.com/aws-powertools/powertools-lambda-python/issues/3662) for this same request and plan to work on it in the coming weeks. Do you mind if I close this issue and mention you in the one that's already open?
Thank you @leandrodamascena for your clarification.
Is it possible to implement myself using?:
swagger_base_url: str, optional
The base url for the swagger UI. If not provided, we will serve a recent version of the Swagger UI.
I don't know much about Swagger UI, but it seems it support OAuth 2.0 configuration. Could that be included into the external bundles?
swagger_js = f"{swagger_base_url}/swagger-ui-bundle.min.js"
swagger_css = f"{swagger_base_url}/swagger-ui.min.css"
https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
Thank you @leandrodamascena for your clarification.
Is it possible to implement myself using?:
swagger_base_url: str, optional The base url for the swagger UI. If not provided, we will serve a recent version of the Swagger UI.
Unfortunately, no. This
swagger_base
is specifically for when customers wants to host in a external server the JS/CSS files required to render the Swagger UI.I don't know much about Swagger UI, but it seems it support config for OAuth 2.0 configuration. Could that be included into the external bundles?
swagger_js = f"{swagger_base_url}/swagger-ui-bundle.min.js" swagger_css = f"{swagger_base_url}/swagger-ui.min.css"
I'm afraid you can't do that. Swagger UI is a project designed to enable developers to import OpenAPI/Swagger files and display them interactively in the browser. To incorporate support for OAuth2.0 and other authentication methods, we must change our OpenAPI utility to inject the configuration into the OpenAPI file.
Let me talk with the team to see our timeline for implementing this. I'll return here as soon as I have updates.
Thanks
Thank you.
But what's the purpose of the Swagger UI OAuth 2.0 configuration options then?
https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/
Would that be configuration for fetching the OpenAPI spec itself?
Open swagger-initializer.js in your text editor and replace "https://petstore.swagger.io/v2/swagger.json" with the URL for your OpenAPI 3.0 spec.
What I need is a Swagger UI for the OpenAPI spec, optionally protected by OIDC, and with an interface like the following, where users press "SSO Login", which fetches a token for calling all defined API endpoints:
My apologies for the misunderstanding. I realize now that what you're asking for is to protect the Swagger UI with OIDC/OAuth, rather than specific routes. Got it now.
However, I remain skeptical that this will work seamlessly without additional adjustments. We define the SwaggerUI at this line, and even if you bring your own JavaScript files and define initOAuth
there, I doubt that var ui = SwaggerUIBundle(swaggerUIOptions)
(here) will be able to read and embed specific OAuth configuration, at least without some hack.
The best approach here would be to introduce new parameters in the enable_swagger method, allowing customers to configure OAuth for SwaggerUI.
I'm adding this issue to our backlog to work on it in the next sprints.
Thank you.
My apologies for the misunderstanding. I realize now that what you're asking for is to protect the Swagger UI with OIDC/OAuth, rather than specific routes. Got it now.
Actually, protecting the Swagger UI is not a requirement, but just a nice feature.
However, I want the Swagger UI to be able to execute the Authorization Code Grant Flow (OAuth 2.0) to acquire an access token for calling the listed API endpoints.
I hope, I'm clear now :)
Making requests from the Swagger UI using OAuth 2.0 would be really good. Right now I'm not sure what's needed, so we need to investigate more, but it doesn't seem to be too hard. I can try to work on this next week if you want.
I'm starting to work on this now.
I can help you out, if you need. I made some manually edits of the generated OpenAPI spec, then ran Swagger UI from a Docker container as follows:
docker run -p 3000:8080 -e OAUTH_CLIENT_ID=<client-id> -e OAUTH_APP_NAME="My App" -e OAUTH_SCOPES="api://<resource-id>/user_impersonation" -e OAUTH_USE_PKCE="true" -e SWAGGER_JSON=./openapi.yaml -v $(pwd):/openapi swaggerapi/swagger-ui
Swagger UI provides several ways to provide these arguments: config file, hard-coded, etc.
With securitySchemes
defined, and security
either specified locally for the operation or globally, the user can easily authenticate without having to enter any values itself, except names of scopes
Awesome, thanks for this hints, I actually didn't had the full picture in my head how the Swagger UI would integrate with OAuth2, so your comment led me to learn all about securitySchemes :D I'll try to write something and will get back to you to get feedback.
Nice, if I can help with anything regarding the implementation, feel free to reach out. I would like to start contributing to the project myself :)
The tricky part is supplying the Swagger UI OAuth 2.0 configuration, which was provided as Docker environment variables above:
https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/
Oh I would love for you to contribute! 🎉 Here are my ideas:
securitySchemes
and security
on our OpenAPI generationRight now the models are already there, but they are not used anywhere.
The OpenAPI spec says we can add security to both the top API declaration and individual operations.
So here's an idea (napkin programming here :P):
securitySchemes
on the top API declaration (here and here)
security_schemes: Optional[List[SecurityScheme]]
? oauth2_flows = OAuthFlows(authorizationCode=OAuthFlowAuthorizationCode(authorizationUrl="https://example.com/oauth/authorize", tokenUrl="https://example.com/oauth/token", scopes={"read": "Grants read access"})
app.get_openapi_schema(title="...", security_schemes=[OAuth2(flows=oauth2_flows)])
security
on the same top API declaration. This would be interpreted by Swagger that it needs to apply to all operations.
security: Optional[List[Dict[str, List[str]]]]
(got the hint from here)key
of each security object exists in the securitySchemes
? This would avoid declaring security on a scheme that doesn't exist. Ideally we would do it at compile time (type checker) but not sure how far we can getapp.get_openapi_schema(..., security=[{"OAuth2": ["admin"]}])
And finally, we need to add the same security
support for each operation.
security
parameter. Make sure it's not the last parameter as the middleware functionality will stop working. middlewares
always needs to be the last.@app.get("/admin", security=[{"OAuth2": ["admin"]}])
Notice that this is just about generating the OpenAPI schema, not about enforcing any of those security schemas :D
Does any of this makes sense? Would you like to try it? :D If you're on Discord we can always have a chat if you ever get stuck.
I've went ahead and started the implementation. Still some tasks to do (check the PR description), let me know if you want to take some!
Thank you @rubenfonseca. I commented on your other PR. Great job updating the docs with a clear explanation on usage.
I will get back to you tomorrow or Friday. I have been extremely busy at LEGO for the past 3 days, so I haven't had much time helping you out here
This issue is now closed. Please be mindful that future comments are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.
This is now released under 2.37.0 version!
Use case
I want to protect and add authorization headers to requests sent using the Swagger UI, as endpoints are protected by an API Gateway REST Lambda authorizer:
https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/#enabling-swaggerui
Is this possible to achieve using the current Swagger UI implementation in powertools-lambda-python?
Solution/User Experience
I would like to provide configuration similar to how it's done for swagger-ui-py
Alternative solutions
No response
Acknowledgment