aws-powertools / powertools-lambda-python

A developer toolkit to implement Serverless best practices and increase developer velocity.
https://docs.powertools.aws.dev/lambda/python/latest/
MIT No Attribution
2.88k stars 396 forks source link

Feature request: Add support for OAuth 2.0 authorization for Swagger UI #4036

Closed nlykkei closed 6 months ago

nlykkei commented 7 months ago

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

leandrodamascena commented 7 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?

nlykkei commented 7 months ago

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/

leandrodamascena commented 7 months ago

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

nlykkei commented 7 months ago

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:

image
leandrodamascena commented 7 months ago

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.

leandrodamascena commented 7 months ago

I'm adding this issue to our backlog to work on it in the next sprints.

nlykkei commented 7 months ago

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 :)

rubenfonseca commented 7 months ago

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.

rubenfonseca commented 7 months ago

I'm starting to work on this now.

nlykkei commented 7 months ago

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

rubenfonseca commented 7 months ago

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.

nlykkei commented 7 months ago

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/

rubenfonseca commented 7 months ago

Oh I would love for you to contribute! 🎉 Here are my ideas:

Right 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):

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)])
app.get_openapi_schema(..., security=[{"OAuth2": ["admin"]}])

And finally, we need to add the same security support for each operation.

@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.

rubenfonseca commented 7 months ago

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!

nlykkei commented 7 months ago

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

github-actions[bot] commented 6 months ago

⚠️COMMENT VISIBILITY WARNING⚠️

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.

github-actions[bot] commented 6 months ago

This is now released under 2.37.0 version!