Simple integration between FastAPI and cloud authentication services (AWS Cognito, Auth0, Firebase Authentication).

Overview

FastAPI Cloud Auth

Tests codecov PyPI version

fastapi-cloudauth standardizes and simplifies the integration between FastAPI and cloud authentication services (AWS Cognito, Auth0, Firebase Authentication).

Features

  • Verify access/id token: standard JWT validation (signature, expiration), token audience claims and etc.
  • Verify permissions based on scope (or groups) within access token and Extract user info
  • Get the detail of login user info (name, email, etc.) within ID token
  • Dependency injection for verification/getting user, powered by FastAPI
  • Support for:

Requirements

Python 3.6+

Install

$ pip install fastapi-cloudauth

Example (AWS Cognito)

Pre-requirement

  • Check region, userPoolID and AppClientID of AWS Cognito that you manage to
  • Create a user assigned read:users permission in AWS Cognito
  • Get Access/ID token for the created user

NOTE: access token is valid for verification, scope-based authentication and getting user info (optional). ID token is valid for verification and getting full user info from claims.

Create it

Create a file main.py with:

import os
from pydantic import BaseModel
from fastapi import FastAPI, Depends
from fastapi_cloudauth.cognito import Cognito, CognitoCurrentUser, CognitoClaims

app = FastAPI()
auth = Cognito(
    region=os.environ["REGION"], 
    userPoolId=os.environ["USERPOOLID"],
    client_id=os.environ["APPCLIENTID"]
)

@app.get("/", dependencies=[Depends(auth.scope(["read:users"]))])
def secure():
    # access token is valid
    return "Hello"


class AccessUser(BaseModel):
    sub: str


@app.get("/access/")
def secure_access(current_user: AccessUser = Depends(auth.claim(AccessUser))):
    # access token is valid and getting user info from access token
    return f"Hello", {current_user.sub}


get_current_user = CognitoCurrentUser(
    region=os.environ["REGION"], 
    userPoolId=os.environ["USERPOOLID"],
    client_id=os.environ["APPCLIENTID"]
)


@app.get("/user/")
def secure_user(current_user: CognitoClaims = Depends(get_current_user)):
    # ID token is valid and getting user info from ID token
    return f"Hello, {current_user.username}"

Run the server with:

$ uvicorn main:app

INFO:     Started server process [15332]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Interactive API Doc

Go to http://127.0.0.1:8000/docs.

You will see the automatic interactive API documentation (provided by Swagger UI).

Authorize 🔓 button can be available at the endpoints injected dependency.

You can supply a token and try the endpoint interactively.

Swagger UI

Example (Auth0)

Pre-requirement

  • Check domain, customAPI (Audience) and ClientID of Auth0 that you manage to
  • Create a user assigned read:users permission in Auth0
  • Get Access/ID token for the created user

Create it

Create a file main.py with:

import os
from pydantic import BaseModel
from fastapi import FastAPI, Depends
from fastapi_cloudauth.auth0 import Auth0, Auth0CurrentUser, Auth0Claims

app = FastAPI()

auth = Auth0(domain=os.environ["DOMAIN"], customAPI=os.environ["CUSTOMAPI"])


@app.get("/", dependencies=[Depends(auth.scope(["read:users"]))])
def secure():
    # access token is valid
    return "Hello"


class AccessUser(BaseModel):
    sub: str


@app.get("/access/")
def secure_access(current_user: AccessUser = Depends(auth.claim(AccessUser))):
    # access token is valid and getting user info from access token
    return f"Hello", {current_user.sub}


get_current_user = Auth0CurrentUser(
    domain=os.environ["DOMAIN"],
    client_id=os.environ["CLIENTID"]
)


@app.get("/user/")
def secure_user(current_user: Auth0Claims = Depends(get_current_user)):
    # ID token is valid and getting user info from ID token
    return f"Hello, {current_user.username}"

Try to run the server and see interactive UI in the same way.

Example (Firebase Authentication)

Pre-requirement

  • Create a user in Firebase Authentication and get project ID
  • Get ID token for the created user

Create it

Create a file main.py with:

from fastapi import FastAPI, Depends
from fastapi_cloudauth.firebase import FirebaseCurrentUser, FirebaseClaims

app = FastAPI()

get_current_user = FirebaseCurrentUser(
    project_id=os.environ["PROJECT_ID"]
)


@app.get("/user/")
def secure_user(current_user: FirebaseClaims = Depends(get_current_user)):
    # ID token is valid and getting user info from ID token
    return f"Hello, {current_user.user_id}"

Try to run the server and see interactive UI in the same way.

Additional User Information

We can get values for the current user from access/ID token by writing a few lines.

Custom Claims

For Auth0, the ID token contains extra values as follows (Ref at Auth0 official doc):

{
  "iss": "http://YOUR_DOMAIN/",
  "sub": "auth0|123456",
  "aud": "YOUR_CLIENT_ID",
  "exp": 1311281970,
  "iat": 1311280970,
  "name": "Jane Doe",
  "given_name": "Jane",
  "family_name": "Doe",
  "gender": "female",
  "birthdate": "0000-10-31",
  "email": "[email protected]",
  "picture": "http://example.com/janedoe/me.jpg"
}

By default, Auth0CurrentUser gives pydantic.BaseModel object, which has username (name) and email fields.

Here is sample code for extracting extra user information (adding user_id) from ID token:

from pydantic import Field
from fastapi_cloudauth.auth0 import Auth0Claims  # base current user info model (inheriting `pydantic`).

# extend current user info model by `pydantic`.
class CustomAuth0Claims(Auth0Claims):
    user_id: str = Field(alias="sub")

get_current_user = Auth0CurrentUser(domain=DOMAIN, client_id=CLIENTID)
get_current_user.user_info = CustomAuth0Claims  # override user info model with a custom one.

Or, we can also set new custom claims as follows:

get_user_detail = get_current_user.claim(CustomAuth0Claims)

@app.get("/new/")
async def detail(user: CustomAuth0Claims = Depends(get_user_detail)):
    return f"Hello, {user.user_id}"

Raw payload

If you doesn't require pydantic data serialization (validation), FastAPI-CloudAuth has a option to extract raw payload.

All you need is:

get_raw_info = get_current_user.claim(None)

@app.get("/new/")
async def raw_detail(user = Depends(get_raw_info)):
    # user has all items (ex. iss, sub, aud, exp, ... it depends on passed token) 
    return f"Hello, {user.get('sub')}"

Additional scopes

Advanced user-SCOPE verification to protect your API.

Supports:

  • all (default): required all scopes you set
  • any: At least one of the configured scopes is required

Use as (auth is this instanse and app is fastapi.FastAPI instanse):

from fastapi import Depends
from fastapi_cloudauth import Operator

@app.get("/", dependencies=[Depends(auth.scope(["allowned", "scopes"]))])
def api_all_scope():
    return "user has 'allowned' and 'scopes' scopes"

@app.get("/", dependencies=[Depends(auth.scope(["allowned", "scopes"], op=Operator._any))])
def api_any_scope():
    return "user has at least one of scopes (allowned, scopes)"

Development - Contributing

Please read the CONTRIBUTING how to setup development environment and testing.

Comments
  • TypeError: cannot pickle '_cffi_backend.FFI' object

    TypeError: cannot pickle '_cffi_backend.FFI' object

    Using a straight copy-paste of your example application, I get this pickle error.

    Traceback (most recent call last):
      File "/Users/scott/.local/bin/uvicorn", line 10, in <module>
        sys.exit(main())
      File "/Users/scott/.local/lib/python3.8/site-packages/click/core.py", line 829, in __call__
        return self.main(*args, **kwargs)
      File "/Users/scott/.local/lib/python3.8/site-packages/click/core.py", line 782, in main
        rv = self.invoke(ctx)
      File "/Users/scott/.local/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/Users/scott/.local/lib/python3.8/site-packages/click/core.py", line 610, in invoke
        return callback(*args, **kwargs)
      File "/Users/scott/.local/lib/python3.8/site-packages/uvicorn/main.py", line 355, in main
        run(**kwargs)
      File "/Users/scott/.local/lib/python3.8/site-packages/uvicorn/main.py", line 379, in run
        server.run()
      File "/Users/scott/.local/lib/python3.8/site-packages/uvicorn/main.py", line 407, in run
        loop.run_until_complete(self.serve(sockets=sockets))
      File "uvloop/loop.pyx", line 1456, in uvloop.loop.Loop.run_until_complete
      File "/Users/scott/.local/lib/python3.8/site-packages/uvicorn/main.py", line 414, in serve
        config.load()
      File "/Users/scott/.local/lib/python3.8/site-packages/uvicorn/config.py", line 300, in load
        self.loaded_app = import_from_string(self.app)
      File "/Users/scott/.local/lib/python3.8/site-packages/uvicorn/importer.py", line 20, in import_from_string
        module = importlib.import_module(module_str)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/importlib/__init__.py", line 127, in import_module
        return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
      File "<frozen importlib._bootstrap>", line 991, in _find_and_load
      File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
      File "<frozen importlib._bootstrap_external>", line 783, in exec_module
      File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
      File "./main.py", line 12, in <module>
        @app.get("/", dependencies=[Depends(auth.scope("read:users"))])
      File "/Users/scott/.local/lib/python3.8/site-packages/fastapi_cloudauth/base.py", line 83, in scope
        obj = deepcopy(self)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 172, in deepcopy
        y = _reconstruct(x, memo, *rv)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 270, in _reconstruct
        state = deepcopy(state, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 146, in deepcopy
        y = copier(x, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 230, in _deepcopy_dict
        y[deepcopy(key, memo)] = deepcopy(value, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 146, in deepcopy
        y = copier(x, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 230, in _deepcopy_dict
        y[deepcopy(key, memo)] = deepcopy(value, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 172, in deepcopy
        y = _reconstruct(x, memo, *rv)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 270, in _reconstruct
        state = deepcopy(state, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 146, in deepcopy
        y = copier(x, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 230, in _deepcopy_dict
        y[deepcopy(key, memo)] = deepcopy(value, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 172, in deepcopy
        y = _reconstruct(x, memo, *rv)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 270, in _reconstruct
        state = deepcopy(state, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 146, in deepcopy
        y = copier(x, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 230, in _deepcopy_dict
        y[deepcopy(key, memo)] = deepcopy(value, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 172, in deepcopy
        y = _reconstruct(x, memo, *rv)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 270, in _reconstruct
        state = deepcopy(state, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 146, in deepcopy
        y = copier(x, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 230, in _deepcopy_dict
        y[deepcopy(key, memo)] = deepcopy(value, memo)
      File "/Users/scott/.pyenv/versions/3.8.3/lib/python3.8/copy.py", line 161, in deepcopy
        rv = reductor(4)
    TypeError: cannot pickle '_cffi_backend.FFI' object
    
    opened by scott2b 8
  • How to inject auth globally and then use .scope?

    How to inject auth globally and then use .scope?

    i have this code

    async def init_auth(app: FastAPI) -> None:
        logger.info("Auth: Configuring connection to {0}", repr(AUTH0_DOMAIN))
        app.state.auth0_client = Auth0(domain=AUTH0_DOMAIN)
        logger.info("Auth: Connection configured")
    
    
    def _get_client(request: Request) -> Auth0:
        return request.app.state.auth0_client
    
    
    def get_auth() -> Callable:
        return _get_client
    

    init_auth is triggered on app.add_event_handler("startup", init_auth(application))

    then this code does work

    @router.get("/something",
                response_model=Any,
                dependencies=[
                    Depends(get_auth)
                ]
                )
    async def get_something(
            request: Request
    ):
    return []
    

    i would like to use auth.scope("read:something") with Depends but i can't seem to make it work

    def get_auth_scoped(
            *,
            scope_name: str,
            client: Auth0 = Depends(get_auth)
    ) -> Callable:
        return client.scope(scope_name=scope_name)
    

    and

    @router.get("/something",
                response_model=Any,
                dependencies=[
                    Depends(get_auth_scoped(scope_name="read:something"))
                ]
                )
    async def get_something(
            request: Request
    ):
    return []
    

    it results in a AttributeError: 'Depends' object has no attribute 'scope'

    what am i missing here? please help?

    opened by spawn-guy 7
  • JWKError

    JWKError

    Hi, I am trying to make it work with Firebase. I am using exaclty the same code you have in the examples

    import os
    from fastapi import FastAPI, Depends
    from fastapi_cloudauth.firebase import FirebaseCurrentUser, FirebaseClaims
    
    app = FastAPI()
    
    get_current_user = FirebaseCurrentUser(
        project_id="my-project-id"
    )
    
    
    @app.get("/user/")
    def secure_user(current_user: FirebaseClaims = Depends(get_current_user)):
        # ID token is valid and getting user info from ID token
        return f"Hello, {current_user.user_id}"
    
    

    but I have the following error:

     File "./src/main.py", line 7, in <module>
        get_current_user = FirebaseCurrentUser(
      File "/home/elvis/Documents/dev-tools/API/env/lib/python3.9/site-packages/fastapi_cloudauth/firebase.py", line 28, in __init__
        jwks = JWKS.firebase(url)
      File "/home/elvis/Documents/dev-tools/API/env/lib/python3.9/site-packages/fastapi_cloudauth/verification.py", line 70, in firebase
        keys = {
      File "/home/elvis/Documents/dev-tools/API/env/lib/python3.9/site-packages/fastapi_cloudauth/verification.py", line 71, in <dictcomp>
        kid: jwk.construct(publickey, algorithm="RS256")
      File "/home/elvis/Documents/dev-tools/API/env/lib/python3.9/site-packages/jose/jwk.py", line 79, in construct
        return key_class(key_data, algorithm)
      File "/home/elvis/Documents/dev-tools/API/env/lib/python3.9/site-packages/jose/backends/rsa_backend.py", line 171, in __init__
        raise JWKError(e)
    jose.exceptions.JWKError: No PEM start marker "b'-----BEGIN PRIVATE KEY-----'" found
    

    Any idea?

    Thank you

    answered 
    opened by AlviseSembenico 5
  • auto_error setting not passed to HTTPBearer dependencies

    auto_error setting not passed to HTTPBearer dependencies

    Hi guys, thanks for writing this implementation!

    I'm currently trying to fit this one into our set-up but I run into an issue with auto_error=False setting not being respected by the dependency injections inside fastapi_cloudauth. Fastapi-cloudauth builds on the fastapi HTTPBearer dependency injection, which raises an HTTPException when the credentials are not found in the headers. To prevent this exception, it supports the auto_error=False option. We need this to support other authentication methods.

    Our authentication set-up is based on this medium article to combine multiple types of authentication. To make this work, the "auto_error=False" is essential, to make sure none of the authentication methods block each other. (see example implementation below)

    Proposed fix: In base.py, there are these dependency injections for HTTPBearer(), which currently don't pass the auto_error parameter: https://github.com/tokusumi/fastapi-cloudauth/blob/36d947fd3e638683fa1cb96e194bdaa054d92ee9/fastapi_cloudauth/base.py#L153 and https://github.com/tokusumi/fastapi-cloudauth/blob/36d947fd3e638683fa1cb96e194bdaa054d92ee9/fastapi_cloudauth/base.py#L192

    These dependencies do support the auto_error parameter, like: HTTPBearer(auto_error=self.auto_error). Possibly you'd want to set this up as a partial function in the constructor.


    For reference: example implementation This fails on an HTTPException from HTTPBearer when the OAuth headers are not passed - which unfortunately is the case when another authentication method is used..

    api_key_query_dependency = APIKeyQuery(name=settings.api_key_name, auto_error=False)
    api_key_header_dependency = APIKeyHeader(name=settings.api_key_name, auto_error=False)
    api_key_cookie_dependency = APIKeyCookie(name=settings.api_key_name, auto_error=False)
    cognito_auth_dependency = Cognito(region=settings.aws_region,
                                      userPoolId=settings.aws_cognito_user_pool_id,
                                      auto_error=False
                                      ).scope("users")
    
    
    async def get_authorization(
            api_key_query: str = Security(api_key_query_dependency),
            api_key_header: str = Security(api_key_header_dependency),
            api_key_cookie: str = Security(api_key_cookie_dependency),
            cognito_auth: str = Depends(cognito_auth_dependency),
    ) -> Security:
        if not cognito_auth \
                or api_key_query == settings.api_key \
                or api_key_header == settings.api_key \
                or api_key_cookie == settings.api_key:
            raise HTTPException(
                status_code=HTTP_403_FORBIDDEN, detail="Could not validate credentials"
            )
    
    opened by mjvdvlugt 5
  • Using auth0 id_token possibly insecure

    Using auth0 id_token possibly insecure

    First of all I have to admit that I don't fully grasp all the oauth2 and OIDC concepts, which is probably why I stumbled accross this project to begin with, not knowing how to implement all the details myself.

    Anyway, I've been reading auth0 documentation and this source code and I see it's possible to retrieve user email using Auth0Claims. But these claims are valid only if FastAPI gets an id_token as Bearer, which is recommended against in this article: https://auth0.com/blog/why-should-use-accesstokens-to-secure-an-api/ that mentions id_token is only meant for the client (which I understand is the frontend, not FastAPI).

    I would love to find a reason why the official recommendation is not valid in this project.

    In my fastapi API I need to know the user email for every request authorization. That's because I support multi-tenancy, where each user has CRUD access only to their own resources. I think this should be a fairly common scenario.. so I'm puzzled why there wouldn't be a straightforward way to do it.

    opened by dorinclisu 4
  • [Auth0] user_id from current user

    [Auth0] user_id from current user

    Hello,

    Is there a way to extract user_id from current user (Auth0) Auth0CurrentUser()? For example, if I use:

    get_current_user = Auth0CurrentUser("dev-some-domain.eu.auth0.com")
    
    @router.get("/")
    async def get_current_user(current_user=Depends(get_current_user)):
        return current_user
    

    as a result, I get a JSON object containing only name and email. Example:

    {
      "name": "[email protected]",
      "email": "[email protected]"
    }
    
    opened by goranvrbaski 3
  • Cannot access `/users/` using the AWS Cognito configuration

    Cannot access `/users/` using the AWS Cognito configuration

    Using the authorization modal (in the docs) ...

    • if I insert an id_token and attempt to access the /users/ endpoint a JWTClaimsError is caught (i.e. "No access_token provided to compare against at_hash claim.")
    • if I insert an access_token and attempt to access the /users/ endpoint the token_use claim is flagged (because it is equal to "id").

    What am I missing?

    opened by IshakAhmed 2
  • Auth0: get_current_user always gives 401

    Auth0: get_current_user always gives 401

    Hi there,

    This is almost certainly user error & not a bug, as I'm new to Auth0.

    In Auth0, I have configured an application (which is a VueJS client) set up as well as an API (my FastAPI back-end).

    I've managed to get authentication working using the example def main_endpoint_test(current_user: AccessUser = Depends(auth.claim(AccessUser))) - when I do this, I can get the user_id/sub, but I don't get the user email.

    I tried using the other approach shown in the example: def secure_user(current_user: Auth0Claims = Depends(get_current_user)):. When I use this, I always get a 401 response. I have initialised the get_current_user passing in the domain and client_id as shown in the example - because the domain is working fine in the simpler auth method, maybe my mistake is entering the wrong value for the client_id?

    What is the client ID value should I be setting here, is it my Auth0 Application's client ID (i.e. the one for the VueJS client)? Is it the custom API's ID (as far as I can tell, there is no field explicitly labelled "client ID" in auth0's APIs)?

    opened by lesiki 2
  • Support multiple scope

    Support multiple scope

    Support a part of #35, multiple scopes with all and any combinator. As:

    from fastapi_cloudauth import Operator
    
    @app.get("/access-all/")
    def secure_access_and(scope=Depends(auth.scope(["role_admin", "super_admin"]))):
        return f"Hello {scope}"
    
    @app.get("/access-any/")
    def secure_access_or(scope=Depends(auth.scope(["role_admin", "super_admin"], op=Operator._any))):
        return f"Hello {scope}"
    
    opened by tokusumi 2
  • Firebase x509 issue

    Firebase x509 issue

    python-jose doesn't support x509 certificates without the extra install option (anymore? I not quite sure if it was a silent breaking change). This breaks the FirebaseCurrentUser's JWKS generation because google gives x509 files for the public key.

    the recommended setup on python-jose is using cryptography as the background, setup as following

    pip install python-jose[cryptography]
    

    but is sort of a debate I guess (acknowledging the fact that cryptography requires building and is not a small dependency)

    At least it needs some documentation about it, so I would like to know whats good for this library.

    documentation 
    opened by yu-ichiro 2
  • Auth0 token

    Auth0 token

    First of all, thanks for your work, easy and clear to use 😄

    The issue I'm facing isn't related to repo itself, but on how to generate the Auth0 token to have all the needed information to use the methods properly.

    For some endpoints that I'm implementing I'll just need to check if the token has the required scopes and for some others I'll need to use: current_user: Auth0Claims = Depends(auth.get_current_user). However I can't find a way to request to Auth0 a token with all of this information: username and scopes. I don't know if I'm misunderstanding some information/concepts or what is going wrong...

    Would appreciate some information with the steps to follow. Thanks in advance!

    opened by guillemfrancisco 2
  • Feature: Add scopes required to the openapi docs

    Feature: Add scopes required to the openapi docs

    Hey guys so I wanted to request this feature that I think might be an interesting addition to the library that consists of adding on the Authorization documentation of each request under "HTTP Authorization Scheme" a new row called "Scopes Accepted/Required" where it would be a list of the scopes the backend requires for the request to be accepted.

    If you guys could point me to where I could start exploring this feature I might be able to develop my self and contribute but right now Im not sure where does the library define documentation sections.

    Here is a image of the place I refer to. image

    opened by DEADSEC-SECURITY 0
  • Having trouble figuring out

    Having trouble figuring out "next steps"

    I'm a "noob" where Cognito is concerned and could be missing something about accessing the example API's. I've got an AWS User Pool defined with a user created. How do I log that user in, or get a JWT Token to use to authorize the example API to access the endpoints? Thanks for your help.

    opened by writeson 1
  • Take lot of time to start a fastapi project

    Take lot of time to start a fastapi project

    image

    Here I have attached the Image, I have used a firebase example and just try to run on ubuntu 20. x LTS But it take long time to run while using on local machine (windows) it quickly run with in no time. is there any reason or is there any config where I am making mistake . same code run on local (windows machine ) fine but take long time on cloud which uses ubuntu

    opened by marxyes 0
  • [Cognito] App client_id is not validated for Cognito JWT (access_token)

    [Cognito] App client_id is not validated for Cognito JWT (access_token)

    I faced with an issue when using congito auth, app client_id is not validating during token verification. So you can path any ID and it will work.

    
    # pass some fake client_id
    auth = Cognito(region=aws_region, userPoolId=aws_cognito_userpool_id, client_id='foo-bar')
    
    # access_token - obtained from Cognito
    http_auth = HTTPAuthorizationCredentials(scheme='Bearer', credentials=access_token)
    
    await auth.verifier.verify_token(http_auth)
    True
    

    The problem is that jwt.decode (jose lib) doesn't expect client_id in token and since aud is not defined it skips validation.

    opened by tivaliy 0
  • Simple Auth0 authentication when using the doc or redoc page

    Simple Auth0 authentication when using the doc or redoc page

    When I use your Python package, things work really well, so many thanks for it. 😀

    However, there is one thing, where I ask myself, whether I can do much better here. When I try to reach my doc page, it looks like this:

    fastapi_doc

    When I click on the locking the top right, it looks like this

    fastapi_auth

    And after I enter the right token_id, I can work with the doc page as intended.

    However, getting the token_id is quite cumbersome, as it usually involves curl requests etc.

    It would be much nicer, if I am automatically logged in from Auth0, if I authenticated somewhere else in my browser. If I did not authenticate somewhere, then this here pops up

    auth0-login

    and after authenticating, I can work as intended. Is that possible?

    opened by junoriosity 0
Releases(v0.4.3)
  • v0.4.3(Jan 6, 2022)

    What's Changed

    • Disable at_hash verification (not used but could raise error in auth flow generating access and ID token simultaneously) by @sindrig in https://github.com/tokusumi/fastapi-cloudauth/pull/58

    New Contributors

    • @sindrig made their first contribution in https://github.com/tokusumi/fastapi-cloudauth/pull/58

    Full Changelog: https://github.com/tokusumi/fastapi-cloudauth/compare/v0.4.2...v0.4.3

    Source code(tar.gz)
    Source code(zip)
  • v0.4.2(Jan 2, 2022)

    What's Changed

    • Fix dependency for Firebase: auto-install cryptography with python-jose by @tokusumi in https://github.com/tokusumi/fastapi-cloudauth/pull/63
    • Add support python3.9 by @tokusumi in https://github.com/tokusumi/fastapi-cloudauth/pull/64

    Full Changelog: https://github.com/tokusumi/fastapi-cloudauth/compare/v0.4.1...v0.4.2

    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Jan 2, 2022)

    What's Changed

    • ✏️ Fix broken link to CONTRIBUTING and grammar in README by @discdiver in https://github.com/tokusumi/fastapi-cloudauth/pull/57
    • Store Firebase JWKS expiry and refresh keys when they expire by @jleclanche in #60 & @tokusumi in https://github.com/tokusumi/fastapi-cloudauth/pull/61
    • codecov-action v1 to v2 by @tokusumi in https://github.com/tokusumi/fastapi-cloudauth/pull/62

    New Contributors

    • @discdiver made their first contribution in https://github.com/tokusumi/fastapi-cloudauth/pull/57

    Full Changelog: https://github.com/tokusumi/fastapi-cloudauth/compare/v0.4.0...v0.4.1

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jun 1, 2021)

    Security updates:

    • Add standard (and service specific) claims verification PR #45 by @tokusumi

    Features:

    • Support multiple scope validation PR #43 by @tokusumi

    Fixes:

    • Handle exceptions on malformed token PR #42 by @tokusumi & @jleclanche

    Internal:

    • Unification for test app instantiate PR #44 by @tokusumi
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Feb 25, 2021)

    Add features:

    • Add extraction for access token (#31). Get user info from access token easily. related issue are #14, #21, #27.

    Breaking changes:

    • Auth0 default scope key turned to be "permissions" ("scope" was scope key before v0.2.0). please make sure RBAC setting is valid.
    • For development, environment variables, AUTH0_MGMT_CLIENTID and AUTH0_MGMT_CLIENT_KEY, will be required to auth0 testing.

    Docs:

    • Add development - contribution guide (#19)

    Bug fixes:

    • Various grammatical cleanups and a fix to the Auth0 example. (#15) by @justinrmiller
    • Handle no-token exception in module to respect auto_error setting (#24, #26) by @mjvdvlugt

    Internal changes:

    • Unify testcases (#17, #18)
    • Refactoring Base module (in #31)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Dec 22, 2020)

    Add features

    • Firebase Authentication Support (Only ID token)

    Doc

    • Add Auth0 example
    • Add Firebase Authentication example
    • Add explanation how to define custom claims
    Source code(tar.gz)
    Source code(zip)
  • v0.1.3(Nov 1, 2020)

  • v0.1.2(Oct 7, 2020)

  • v0.1.1(Oct 7, 2020)

  • 0.1.0(Aug 2, 2020)

    • first release
    • Verify token (JWKS-based JSON Web Token)
    • Authenticate with scope (permissions)
    • Get user info in token
    • Dependency injection of the above
    • Use the above features in the interactive docs, else
    • Support for Auth0 and AWS Cognito
    Source code(tar.gz)
    Source code(zip)
Owner
tokusumi
tokusumi
Stock Market Insights is a Dashboard that gives the 360 degree view of the particular company stock

fedora-easyfix A collection of self-contained and well-documented issues for newcomers to start contributing with How to setup the local development e

Ganesh N 3 Sep 10, 2021
The raid botnet for Telegram

telegram-raid-botnet The raid botnet for Telegram Что нужно сделать перед запуском? Установить модули pip3 install -r requirements.txt Добавить аккаун

Maxim 68 Jan 03, 2023
CVE-2021-39685 Description and sample exploit for Linux USB Gadget overflow vulnerability

CVE-2021-39685 Description and sample exploit for Linux USB Gadget overflow vulnerability

8 May 25, 2022
Example code for interacting with solana anchor programs - candymachine

candypy example code for interacting with solana anchor programs - candymachine THIS IS PURELY SAMPLE CODE TO FORK, MODIFY, UNDERSTAND AND INTERACT WI

dubbelosix 3 Sep 18, 2022
HackerNews and Reddit in one placce

EDIT: this project is 3.5 years old. I found it sad it's just laying around, so I did some minimal fixes and deployed it. Hope you enjoy! (PR's welcom

Hugo Montenegro 1 Nov 13, 2021
Minecraft name sniper written in python.

⚠️ IMPORTANT ⚠️ DO NOT USE MCSNIPERPY -- READ BELOW This sniper does not support Microsoft accounts or prename / gc sniping and is MUCH harder to use

MCsniperPY 201 Dec 30, 2022
A Discord bot that may save your day by predicting it.

Sage A Discord bot that may save your day by predicting it.

1 Nov 17, 2022
A Discord bot for viewing any currency you want comfortably.

Dost Dost is a Discord bot for viewing currencies. Getting Started These instructions will get you a copy of the project up and running on your local

Baran Gökalp 2 Jan 18, 2022
This solution helps you deploy Data Lake Infrastructure on AWS using CDK Pipelines.

CDK Pipelines for Data Lake Infrastructure Deployment This solution helps you deploy data lake infrastructure on AWS using CDK Pipelines. This is base

AWS Samples 66 Nov 23, 2022
A powerful, cool and well-made userbot for your Telegram profile with promising extension capabilities.

Telecharm userbot A powerful, fast and simple Telegram userbot written in Python 3 and based on Pyrogram 1.X. Currently in active WIP state, so feel f

Daniil Kovalenko 16 Dec 01, 2022
Ubuntu env build; Nginx build; DB build;

Deploy 介绍 Deploy related scripts bitnami Dependencies Ubuntu openssl envsubst docker v18.06.3 docker-compose init base env upload https://gitlab-runn

Colin(liuji) 10 Dec 01, 2021
The official command-line client for spyse.com

Spyse CLI The official command-line client for spyse.com. NOTE: This tool is currently in the early stage beta and shouldn't be used in production. Yo

Spyse 43 Dec 08, 2022
Facebook fishing on telegram bot

Facebook-fishing Facebook fishing on telegram bot تثبيت الاداة pkg update -y pkg upgrade -y pkg install git -y pkg install python -y git clone https:/

sadamalsharabi 7 Oct 18, 2022
A multipurpose Telegram Bot written in Python for mirroring files on the Internet to Google Drive

Mirror Leech Bot Mirror Leech Bot is a multipurpose Telegram Bot written in Python for mirroring files on the Internet to our beloved Google Drive. Ba

1 Jan 01, 2022
Discord.py Bot Series With Python

Discord.py Bot Series YouTube Playlist: https://www.youtube.com/playlist?list=PL9nZZVP3OGOAx2S75YdBkrIbVpiSL5oc5 Installation pip install -r requireme

Step 1 Dec 17, 2021
🚀 An asynchronous python API wrapper meant to replace discord.py - Snappy discord api wrapper written with aiohttp & websockets

Pincer An asynchronous python API wrapper meant to replace discord.py ❗ The package is currently within the planning phase 📌 Links |Join the discord

Pincer 125 Dec 26, 2022
DIAL(Did I Alert Lambda?) is a centralised security misconfiguration detection framework which completely runs on AWS Managed services like AWS API Gateway, AWS Event Bridge & AWS Lambda

DIAL(Did I Alert Lambda?) is a centralised security misconfiguration detection framework which completely runs on AWS Managed services like AWS API Gateway, AWS Event Bridge & AWS Lambda

CRED 71 Dec 29, 2022
Termux Pkg

PKG Install Termux All Basic Pkg. Installation : pkg update && pkg upgrade && pkg install python && pkg install python2 && pkg install git && git clon

ɴᴏʙɪᴛᴀシ︎ 1 Oct 28, 2021
A discord bot to check if messages have the correct code formatting.

discord-code-formatter A discord bot to check if messages have the correct code formatting. This was a basic project to help me learn Python and learn

Nash Boisvert 1 Nov 23, 2021