Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Implement OAuth2 authorization_code integration#797

Merged
tiangolo merged 15 commits into
fastapi:masterfrom
kuwv:master
Jan 8, 2020
Merged

Implement OAuth2 authorization_code integration#797
tiangolo merged 15 commits into
fastapi:masterfrom
kuwv:master

Conversation

@kuwv

@kuwv kuwv commented Dec 18, 2019

Copy link
Copy Markdown
Contributor

FastAPI currently implements the password flow grant. While this is sufficient for building applications that self-host identity, it is not the recommended OAuth2 implementation. It is also not preferred when attempting to use external identity providers. This PR would allow three-legged OAuth to be utilized by FastAPI with the OpenAPI integration.

This is a working implementation: https://github.com/kuwv/python-microservices
https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section-3.4
(edit: grammar, references)

kuwv added 2 commits December 17, 2019 22:08
Add authorization_code OpenAPI integration to FastAPI.
@codecov

codecov Bot commented Dec 18, 2019

Copy link
Copy Markdown

Codecov Report

Merging #797 into master will increase coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #797      +/-   ##
==========================================
+ Coverage    99.9%   99.92%   +0.01%     
==========================================
  Files         287      287              
  Lines        7509     7506       -3     
==========================================
- Hits         7502     7500       -2     
+ Misses          7        6       -1
Impacted Files Coverage Δ
fastapi/applications.py 100% <ø> (ø) ⬆️
...torial/test_body_nested_models/test_tutorial009.py 100% <ø> (ø) ⬆️
...est_tutorial/test_extra_models/test_tutorial005.py 100% <ø> (ø) ⬆️
tests/test_application.py 100% <ø> (ø) ⬆️
docs/src/body_fields/tutorial001.py 100% <ø> (ø) ⬆️
..._tutorial/test_handling_errors/test_tutorial002.py 100% <ø> (ø) ⬆️
tests/test_starlette_exception.py 100% <ø> (ø) ⬆️
tests/test_extra_routes.py 100% <ø> (ø) ⬆️
fastapi/logger.py 100% <100%> (ø) ⬆️
..._sql_databases_peewee/test_sql_databases_peewee.py 100% <100%> (ø) ⬆️
... and 26 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8b0b4db...fc28bf3. Read the comment docs.

Comment thread fastapi/security/oauth2.py Outdated
@dmontagu

dmontagu commented Dec 18, 2019

Copy link
Copy Markdown
Contributor

I'm in favor of this; defer to @tiangolo though.

It will need tests and documentation, but if you wanted to wait for @tiangolo to confirm interest before building those out, that would make sense to me.

@kuwv

kuwv commented Dec 18, 2019

Copy link
Copy Markdown
Contributor Author

I knew coverage was going to be the issue. I commented on a previous issue. The trick is that a mock IdP would need to be setup. I planned to do a write-up discussing the example I put together to help.

@dmontagu

Copy link
Copy Markdown
Contributor

I don't think you need to mock out an identity provider (and would in fact prefer you didn't! unless you add more to this PR) -- the dependency you've written just returns the authorization scheme param, so testing that it returns the right value should be enough.

I think it's enough to just explain how it should be used in the documentation; I don't think you need to actually implement a mocked out identity provider. (Well, that's my opinion anyway!)

@kuwv

kuwv commented Dec 18, 2019

Copy link
Copy Markdown
Contributor Author

Sure, I see that in the other tests. I'll give it a try next.

@kuwv

kuwv commented Dec 26, 2019

Copy link
Copy Markdown
Contributor Author

@tiangolo could I get your input on this? I'd like to see this implemented. If you give the go ahead I can start documenting an example implementation.

Comment thread Pipfile Outdated
@dmontagu

Copy link
Copy Markdown
Contributor

This looks good to me. Any chance you could add a brief discussion somewhere in the docs?

@kuwv

kuwv commented Dec 31, 2019

Copy link
Copy Markdown
Contributor Author

This looks good to me. Any chance you could add a brief discussion somewhere in the docs?

Yeah, I was going to wait for additional feedback but I can begin it sometime later this week.

@dmontagu

dmontagu commented Dec 31, 2019

Copy link
Copy Markdown
Contributor

I would vote for a section in the security docs somewhere under this one: https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/ describing 1) (briefly) how password flow differs from authorization code flow, and 2) a basic example of how the models you've added are intended to be used.

For what it's worth, I think this would be a substantial and meaningful addition to the docs! I haven't found a great description (brief or otherwise) of the relationship between the OAuth flows, not to mention anything practical.

Once you've added this, I'd also like to integrate the authorization code flow into my (work-in-progress) fastapi-auth package (https://github.com/dmontagu/fastapi-auth.).

@kuwv

kuwv commented Jan 4, 2020

Copy link
Copy Markdown
Contributor Author

I would vote for a section in the security docs somewhere under this one: https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/ describing 1) (briefly) how password flow differs from authorization code flow, and 2) a basic example of how the models you've added are intended to be used.

For what it's worth, I think this would be a substantial and meaningful addition to the docs! I haven't found a great description (brief or otherwise) of the relationship between the OAuth flows, not to mention anything practical.

Once you've added this, I'd also like to integrate the authorization code flow into my (work-in-progress) fastapi-auth package (https://github.com/dmontagu/fastapi-auth.).

Sure, that would be great. I plan to do a complete working example, but I'm not sure how it will fit yet.

@tiangolo tiangolo merged commit 91fe90e into fastapi:master Jan 8, 2020
@tiangolo

tiangolo commented Jan 8, 2020

Copy link
Copy Markdown
Member

Thank you @kuwv ! This looks great. 🚀 🎉

Thanks @dmontagu for the review! 💪 🙇‍♂️

I've been delaying adding these classes until I can write the full tutorial for that, but that has taken too long 😅 So I'll merge this right away as having the functionality there can probably help a bunch of people already, and I expect its tutorial to be potentially long/complex...

We can handle the tutorial for it in a second PR. If you wanna start it, that's great, if not, that's fine, I'll do it later (and probably get opinionated about it 😂 ).

@ghost

ghost commented Apr 13, 2020

Copy link
Copy Markdown

Hey @tiangolo, I was wondering if there is any docs for this just yet?

@moldhouse

Copy link
Copy Markdown

Hey, does there exist a working example where FastAPI is used as an identity provider for external services to register with?

@kuwv

kuwv commented Sep 25, 2020

Copy link
Copy Markdown
Contributor Author

@moldhouse fyi #335

@nikokaoja

Copy link
Copy Markdown

@kuwv is there any draft of a tutorial for implementing authorization flow in FastAPI?

@kuwv

kuwv commented Mar 17, 2021

Copy link
Copy Markdown
Contributor Author

@niva83 I have my draft stored somewhere. I was working it but @tiangolo said that he would prefer to do the write up himself. I was going to restart it a while ago, but alot of newer auth examples have been created since, so I thought that it would be also.

FastAPI uses OpenAPI so this should help: https://swagger.io/docs/specification/authentication/oauth2/

I'll consider doing the writeup if you believe this is insufficient.

@nikokaoja

Copy link
Copy Markdown

@kuwv if you are interested maybe I can contribute?
I've just implemented authorization flow for a web app that I am developing.
In my example, I use keycloak as an auth server.

I noticed that many of the online examples are either setting the bar too high (requires one to be already expert in auth) or they are too simple (lack a number of things which are required in production, such as refreshing your tokens, storing session info, etc.)

@rdpravin1895

Copy link
Copy Markdown

FastAPI currently implements the password flow grant. While this is sufficient for building applications that self-host identity, it is not the recommended OAuth2 implementation. It is also not preferred when attempting to use external identity providers. This PR would allow three-legged OAuth to be utilized by FastAPI with the OpenAPI integration.

This is a working implementation: https://github.com/kuwv/python-microservices
https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section-3.4
(edit: grammar, references)

@kuwv That is the implementation I was looking for more than 2 weeks. Is that available some where in the FastAPI docs? I could see only the jwt example.

@nikokaoja

Copy link
Copy Markdown

@rdpravin1895 it is not

@rdpravin1895

Copy link
Copy Markdown

@niva83 Are you planning to do a writeup? This will be really useful for integrating third party SSO with fastapi, for which currently I am facing difficulties in getting it to work properly

@nikokaoja

nikokaoja commented Apr 12, 2021

Copy link
Copy Markdown

@rdpravin1895 I am planning to do it, hopefully soon. My implementation makes use of keycloak as OIDC/Auth2 server. Would that be useful for you ?

@rdpravin1895

Copy link
Copy Markdown

@niva83 That should be great. I'm trying for Microsoft Azure AD, but SSO sequence is the same for all Identity providers, so that shouldn't matter I believe. Thanks a lot in advance.

@nikokaoja

nikokaoja commented Apr 12, 2021

Copy link
Copy Markdown

@rdpravin1895 I requested clearance from my employer to do this, so it might take some time.

@raphaelauv

raphaelauv commented Apr 12, 2021

Copy link
Copy Markdown
Contributor

Hey @niva83 , why did you mentioned me here ?

@nikokaoja

Copy link
Copy Markdown

@raphaelauv sorry meant to @rdpravin1895 but was too fast on keyboard!

@major-mayer

Copy link
Copy Markdown

Hi @niva83
We would also like to use the OAuth2 Authorization Code flow in combination with a keycloak OIDC server, so i would be very interested in your tutorial.
You can give me a sneak preview if you like to, maybe i can spot some typos, etc. ;)

@nikokaoja

Copy link
Copy Markdown

@major-mayer I've just submitted proposal to get this work de-classified at my work and allowed to be turned into an open-source project on GitHub.

@major-mayer

Copy link
Copy Markdown

Great thing, thank you :)

@kuwv

kuwv commented May 4, 2021

Copy link
Copy Markdown
Contributor Author

@niva83 My apologies. I didn't get any earlier notifications. I can review your work once you submit it if you like?

@stratosgear

Copy link
Copy Markdown
Contributor

@niva83 I guess the proposal for turning your work as an open source project failed? Or is it published somewhere...? This would still be useful! Thanks.

@nikokaoja

Copy link
Copy Markdown

Guys sorry I did not manage to reply as I was changing job/country. Indeed, unfortunately my previous employer forbid making the project open source due to fear/incompetence of the legal department who thought that 'we could get sued if your package cause security risks to company xx'

@major-mayer

Copy link
Copy Markdown

Oh damn, that's a pity.
Especially since in almost every open source license file, literally the first line says: "THIS SOFTWARE COMES WITHOUT ANY WARRANTY".
Really sad 😿

@stratosgear

Copy link
Copy Markdown
Contributor

A pitty indeed.

But maybe it does not even have to be a full blown open source project hosted on github. Even if you share some standalone snippets or two of the setup files, they might point us along the right way. I know, it's still a hassle, but it's a shame of you have already done the work in the past.

In any case, thanks for getting back anyways... :)

@nikokaoja

Copy link
Copy Markdown

Let me what I can do. Ideally I would like to post the entire solution, since my previous company decided to use different flow instead of authorization code.

@jb747

jb747 commented Jan 15, 2023

Copy link
Copy Markdown

Perhaps of interest to passers-by: fastapi oauth2 authorization code/implicit flow examples. Just a heads-up.

@maveius

maveius commented Dec 18, 2025

Copy link
Copy Markdown

@kuwv Please explain what and why scopes in OAuth2AuthorizationCodeBearer are dictionary ?
but in swagger_ui_init_oauth are single string ?

What should be as a Key? What should be as value in this dictionary? the documentation says:

The OAuth2 scopes that would be required by the path operations that use this dependency.

no more details with what should be key and what should be a value

@kuwv

kuwv commented Dec 28, 2025

Copy link
Copy Markdown
Contributor Author

@maveius

@kuwv Please explain what and why scopes in OAuth2AuthorizationCodeBearer are dictionary ? but in swagger_ui_init_oauth are single string ?

What should be as a Key? What should be as value in this dictionary? the documentation says:

The OAuth2 scopes that would be required by the path operations that use this dependency.

no more details with what should be key and what should be a value

I'm not sure why I submitted as a dict. It should be either a space delimited string, or a list. Maybe a goof or I mistook set for a dict when reviewing the OpenAPI spec.

edit:
Actually, I'm not seeing anything listed for bearer scopes but the spec essentially extends the OAuth2 spec. That one specifically states that it should be a map instead of a list: https://swagger.io/docs/specification/v3_0/authentication/oauth2/

I did make sure to follow the spec when I submitted this (5-6 years ago). So, I'm not sure what's correct here now. Many systems use scopes as such {"scope": "group:read user:write"} which would align to the spec, and would still jive with JWT.

Probably should be dict | list instead. The spec is intended to work with JWT and Opaque tokens. With an Opaque token it would usually require a back channel introspect call to populate scopes. Could be why it is a map in the spec instead.

@maveius

maveius commented Dec 29, 2025

Copy link
Copy Markdown

Thanks for the explanation. I see that as an example of openAPI using values as a description, it would be good to document that the structure can be mapping like "scope": "description" but in my case only a simple list will be enough and will be parsed into space separated. Always important are keys from dict and keys should be casting to list we don't send descriptions because oauth don't specify it as needed to be sent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.