Replies: 52 comments
-
|
To clarify, the app structure should look a bit like this (super simplified) Cheers |
Beta Was this translation helpful? Give feedback.
-
|
Hey @matthdsm , This particular set of docs and examples should get you pretty far: https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/ You also get an interactive way to test all this out too. The only piece missing (I assume, based on your chart) would be an async def get_current_user(token: str = Security(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
token_data = TokenPayload(**payload)
except PyJWTError:
raise HTTPException(
status_code=HTTP_403_FORBIDDEN, detail="Could not validate credentials"
)
#use something like requests.get and pass your payload here probably
user = get_user(fake_users_db, username=token_data.username)
return userSide note: if you're coming from Django or Flask, most people reuse or enforce auth using the decorator pattern (i.e. @requires_auth). @tiangolo 's examples above show a much easier and traceable way using Hope that helps, but I'll stick around if you run into probs or have more specific questions. |
Beta Was this translation helpful? Give feedback.
-
That's awesome to hear @matthdsm ! Also, thanks for taking the time to create the diagram and explain the use case so clearly. @rcox771 Awesome response! Thanks for sticking around and helping here 😄 🌮
Loved that, I'm citing it 😂 😁 Some more info: Pretty much what @rcox771 explained. Let's say the function One little detail: as Requests doesn't use More technical details (this is about to get pretty technical with specs stuff): Specifically for your use case that is a bit more "elaborate", FastAPI has some other utilities that you can use for advanced OAuth2 flows, that are not in the tutorials but are there available for these cases. The tutorials use the OAuth2 Password Flow. Which is the one appropriate when the same FastAPI application is the "Authorization Server" and the "Resource Server" (using OAuth 2.0 spec terms). That's the simplest case that works for the simplest/more common scenarios. In your case, your FastAPI application would be the "Resource Server", but Hydra would be the "Authorization Server". In this case, you would probably use the "Authorization Code" or the "Impicit" OAuth 2.0 flows. As Hydra is OpenId Connect compatible, you might want to use And instead of using
FastAPI, although not documented, includes Pydantic models for the whole OpenAPI 3.0 spec, this might help you if you want to use completion, etc during development. And it includes, of course, all the models for OAuth 2.0 flows, etc. You can use them from here: https://github.com/tiangolo/fastapi/blob/master/fastapi/openapi/models.py#L291 There are models for all the OAuth 2.0 flows, also made to match the OpenAPI 3.0 spec (and the way it's sub-divided in sections):
All this OAuth 2.0 stuff gets hairy, abstract and not very easy to understand quickly. If you are an expert in OAuth 2.0 with all it covers already (wow, congrats), I'm probably talking (writing) too much already and you know what to do. But I personally don't know anyone that knows and understands deeply all OAuth 2.0 with all its abstractions, flows, etc. 😂 My suggestion is, build something quick that you can throw away using the basic OAuth 2.0 tutorial. Just to get your hands dirty and check that you have the basics working (debug any unrelated errors). This should take you 15 minutes (less?) if you do the OAuth 2.0 tutorial in FastAPI's docs. Then, after that, use the If needed, then implement the |
Beta Was this translation helpful? Give feedback.
-
|
I guess what I'm wondering, without going too far down the OAuth rabbits hole, is how to enable both a password bearer scheme for local authentication as well as an OpenID Connect scheme for federated authentication. So for example to let someone login either via Google or local username/password bearer, would I define one |
Beta Was this translation helpful? Give feedback.
-
|
@kkinder In your case, you could create a custom For it, you would create the To parse the token in the case it was a password token, you can copy code fragments from the Also, have in mind that:
|
Beta Was this translation helpful? Give feedback.
-
|
Thanks, @tiangolo , that's a really helpful summary. |
Beta Was this translation helpful? Give feedback.
-
|
Nice discussion! I have about the same requirement and I am working on a solution to support this. I am trying the following:
Now I want to create logic to test either the jwt.decode based on the tutorial scripts or jwt.decode based on the Auth0 token. I have come up with two approaches:
What do you think is a good approach? |
Beta Was this translation helpful? Give feedback.
-
|
Guys, there's a new version that should facilitate all this a bit more: Allowing you to use the classes directly in many cases, instead of having to subclass them. The PR is here: #134 In summary, you can now pass a parameter oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token", auto_error=False)Then, in your dependency, it's the same: async def get_current_user(token: str = Security(oauth2_scheme)):
if token is None:
# Not authenticated with oauth2_scheme, maybe with other scheme?
# Raise here, or check for other options, or allow a simpler version for the anonymous users
raise HTTPException(status_code=403, detail="Not authenticated")
...But now, when the used didn't authenticate using this With this, you should be able to define multiple |
Beta Was this translation helpful? Give feedback.
-
|
@tiangolo Thanks for the update and your work! I will try to test and implement this and report the results back. |
Beta Was this translation helpful? Give feedback.
-
|
Great! Thanks. |
Beta Was this translation helpful? Give feedback.
-
|
There's a few more things I'm struggling with, but I'm really wondering if maybe a more thorough example might help out the broader community. Specifically, I'm looking at the And per its layout, there can only be one of each flow. One implicit, one password, etc. So if you want multiple flows available for different providers, that breaks the above model. That is to say, you can't really do this: You can define multiple schemes, it seems, but that also gets messy, especially in terms of injecting them into dependencies. Does anyone know of a project currently implementing FastAPI's OAuth2 support for a variety of providers and flows? Especially, perhaps, one that implements Google, Github, and local auth? |
Beta Was this translation helpful? Give feedback.
-
|
@kkinder So, right to the point: Let's say I want to have Facebook, Google, GitHub, and any other of these systems as valid login providers. And I'm actually not interested in interacting with those providers directly, at least for this example. So, I don't want to create GitHub repos or write Facebook posts in the name of my users. I just want them to be able to login to my app. What I would do, and I plan on writing about it and including it in the project generators, is create a normal username (email)/password security scheme. Then I would have a frontend with a login page having the buttons for the social logins I want, let's say Facebook, and also the normal email/password login option. It would perform the social login in the frontend directly. Underneath, my frontend JS would be using the implicit flow of Facebook, but that's not declared in my app, only in Facebook's. When the user clicks the Facebook login button, it would do all the OAuth2 dance with Facebook, automatically handled by the frontend facebook SDK. In the final step of that, my JS would receive a Facebook Here's the key part: Then my frontend would send that Facebook And then, my frontend would perform all the interactions with my app/API using the token generated from my app itself. Even with its own expiration date. That could be independent of the original expiration date of the Facebook For this to work I wouldn't even need to declare in my app an additional OAuth2 flow, the password one would be enough. But if we want to be strict with the OpenAPI/OAuth2 standard and have all that flow "properly" documented, I would create an OAuth2 implicit flow, with the Now, technical details about your previous questions, having only one type of flow per security scheme is part of OpenAPI, is not a limitation at the FastAPI level. Nevertheless, you can have multiple security schemes with different flows. And all of them can be added to a single path operation, making any of them be a valid security scheme to access your API. Now, all this OAuth2 stuff and declarations in OpenAPI is actually targeted at the OAuth2 provider, not the clients. So, social login could be used independent of OpenAPI, FastAPI, how you handle authentication in your app, and even if your app has any OAuth2 related feature or not. All these OAuth2 features that get integrated into your OpenAPI (generated automatically by FastAPI) are targeted mainly at the OAuth2 authentication provider. That means that, with FastAPI, you can build your own OAuth2 provider equivalent to Facebook, Google, GitHub, etc. You could have third-party applications that do social login using Facebook, Google, GitHub, AND your app. Or you could use your FastAPI app as a central single-sign-on place for other applications (that can be built with FastAPI or anything else). It also means that if you use the scopes, you would have a fully documented API, including permissions, using the standards with all the features. In fact, probably a bit more compliant than some of these providers 😉 Or you could even create more exotic features, for example, having a way to allow your users to generate access tokens that are not even necessarily associated with them, but that have some permissions (scopes) that the users' themselves decide, allowing a third party (let's say, a robot) to access some resources that the user has some control of, while still having an expiration time. Imagine allowing the Amazon robot to deliver the package for you in your garage, not allowing him to enter anywhere else in the house, and only for a limited time frame, all remotely. I know that example might probably seem too weird and maybe complex. But by being able to create a fully compliant OAuth2 application, with FastAPI doing the heavy lifting for you, it would be fairly easy to achieve. |
Beta Was this translation helpful? Give feedback.
-
|
@tiangolo Thanks for the elaborate comment! I do have a question about this and that is how you know when to check which authentication provider:
For example is this something like: /facebook-login and /google-login ? Later on, I see this:
So if I understand correctly, I don't need a specific path operation and can use one endpoint like: But how do you know which provider should be checked when the endpoint gets a request? Is this provided by a header from the frontend? |
Beta Was this translation helpful? Give feedback.
-
Sadly GitHub doesn't allow for Implicit flow so Authorization Code is required. I'd like to make an app fully based on GitHub authentication, I couldn't get it to work with Swagger UI. I would expect the following:
However, I cannot inject the clientId in 1. (edit: it looks like it is possible) and 3. is linked to an endpoint that just let Swagger do the job. GitHub is returning 404 on OPTIONS on the access_token endpoint due to CORS. Is there a working Social connect example out there that I would've missed? Thanks |
Beta Was this translation helpful? Give feedback.
-
|
Hi Diaoul! It does not include integration with the Swagger UI login button, but it can be a start! |
Beta Was this translation helpful? Give feedback.
-
|
I agree, you need to have an In my project, using Azure AD, I have found I can define the application client ID, scope, and PKCE flow through the FastAPI instance. These settings then flow through to Swagger. The Here is the Swagger docs that list what keys you can define in that dictionary. Based upon that doc, here's the configuration that works well for me: app = FastAPI(
title=settings.PROJECT_NAME,
openapi_url=f"{settings.API_V1_STR}/openapi.json",
swagger_ui_init_oauth={
"usePkceWithAuthorizationCodeGrant": True,
"clientId": settings.CLIENT_ID,
"scopes": settings.OAUTH_SCOPES,
},
)I also do the dependency injection of the app.include_router(
api_router, prefix=settings.API_V1_STR, dependencies=[Depends(oauth2_scheme)]
)I can't speak to whether this configuration works for B2C, but I don't see why it wouldn't. My use-case is a tenant-specific application, so all our users are members of our tenant's active directory. I am also doing the token validation in AWS at the API Gateway v2 ("HTTP API") layer, so in FastAPI-land I only need to make sure:
The actual token verification is done before my FastAPI is invoked by AWS & MS on my behalf. It's only tangentially related, but happy to share that configuration if anyone is interested. If you weren't doing that, you should just have to add the token verification as per the FastAPI docs. All the PKCE/OAuth stuff is just to get the token on the app-side for a single-page app. |
Beta Was this translation helpful? Give feedback.
-
|
Hi @nadirsidi . Unfortunately, seems like I can't get this to work with my application. When I click on the Authorize button on the swagger UI, I get redirected to my Auth provider login page. From what I see in the browser console, this seems to be a CORS related issue but I don't understand how I can get rid of it. Any idea ? |
Beta Was this translation helpful? Give feedback.
-
Hi @jmereaux, I was also recently up against a CORS issue. Learned a lot, so maybe I can help. The Mozilla Foundation has some great information on CORS, I recommended checking that out. Here's the first page that is the entry point to the rabbit hole that is CORS. It's good news that the preflight is working. I believe that means your host is authorized to call some resources at the cross-origin domain. Take a look at the response from the EDIT: It may seem silly, but if you're on localhost, make sure you've temporarily enabled your backend CORS config to allow http://localhost:80-- Note that the protocol, domain, and port constitute the unique origin. Then I would look into the raw request for that "fetch CORS error" thing. Hopefully you'll see that your Swagger app is trying to make a request that your backend hasn't configured for CORS. Then the thing to do would be to update your backend CORS configuration. What is your backend in this case? Good luck, here be dragons in my experience. Lost a lot of time figuring this stuff out. |
Beta Was this translation helpful? Give feedback.
-
|
Hi @nadirsidi and thanks for taking the time to answer. In my case, the backend is my FastAPI application and the authentication provider is IBM Cloud AppId. Below is the CORS configuration I put in the FastAPI app : On the IBM Cloud AppID side, I've declared the FastAPI app in the redirect urls section (http://localhost:8000/*): Here is more details regarding the OPTIONS preflight request : |
Beta Was this translation helpful? Give feedback.
-
|
A couple things. For the I also specify The other thing I'll warn you is that I believe the FastAPI / Starlette CORS middleware has some bugs. I tried to use it at one point, but I found it didn't work as expected on my router. Then I dug into the GitHub Issues and it looks like there are some open issues in both projects regarding CORS. There seem to be plenty of workarounds, and I am sure people are using it successfully, just a heads up. I can only vouch for CORS as I have it working on AWS API Gateway, which is an abstraction layer above my FastAPI. Where will you ultimately deploy your FastAPI? You may find it simplifies your Python code to handle CORS in your infrastructure configuration. Nadir |
Beta Was this translation helpful? Give feedback.
-
|
@nadirsidi I'm a bit confused. As far as I understand from the error message below, this is the Auth Provider (IBM Cloud AppId in my case) that raises the CORS error : |
Beta Was this translation helpful? Give feedback.
-
|
@jmereaux, I compared what I can see from your preflight response to my preflight response ahead of the Based upon that message, it sounds like you need to configure CORS in your Auth Provider. In MS Azure, simply adding the redirect URI seems to handle this for me. Perhaps with IBM there is an additional step to get this to work? I would look around. I suspect that error is not specific to your FastAPI implementation. Sorry I can't be more helpful! |
Beta Was this translation helpful? Give feedback.
-
|
@nadirsidi , how does your EDIT: I see, it just stays there, but it's no longer a required field. |
Beta Was this translation helpful? Give feedback.
-
|
Yes, @JonasKs, I unfortunately see the same. I wish I could suppress both the client id and secret fields, but as you said it works if you leave the secret blank. There might be some Swagger setting somewhere to change the UI, but I have never bothered to look since our docs are typically only used internally. |
Beta Was this translation helpful? Give feedback.
-
|
No worries, I'll put some docs or overwrite css. Thank you for responding. 😊 |
Beta Was this translation helpful? Give feedback.
-
|
I've created an Azure AD authentication (FastAPI-Azure-Auth) package for FastAPI, if someone need inspiration/a package to deal with Azure AD. The current |
Beta Was this translation helpful? Give feedback.
-
|
I would like to use firebase auth as the oAuth provider, and preferably, allow the swagger UI to understand endpoints that require authentication and allow me to auth through the UI. The firebase auth all occurs client-side, and my API would just accept a token that it would decode and ensure was valid, preferably without any outgoing calls to firebase from the fastapi server. Is |
Beta Was this translation helpful? Give feedback.
-
|
Here is my workaround:
|
Beta Was this translation helpful? Give feedback.
-
Just got a notification on this thread so thought I’d update this comment. |
Beta Was this translation helpful? Give feedback.
-
|
Hi guys, I'm new to coding, but met the similar problem. I wonder if there's a way like specifying the BTW, auth0 seems great, but I just thought the above may be more simple. I tested, but it doesn't work. Any guidance how to proceed? Thank you. |
Beta Was this translation helpful? Give feedback.





Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
First of all, thank you for all the amazing work you've done with FastAPI. I'm just scratching the surface and I'm already amazed by what you're able to do right out of the box.
As for my question, At my institute we use a centralized authentication service for all webapps base on ORY Hydra. Is there an easy way built in to integrate an external server to authenticate again and use the token query the API?
Thanks
M
Beta Was this translation helpful? Give feedback.
All reactions