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
Halcyon is a Matrix bot library created with the intention of being easy to install and use. Inspired by discord.py

Halcyon is a Matrix bot library with the goal of being easy to install and use. The library takes inspiration from discord.py and the Slack li

Wes Ring 19 Jan 06, 2023
BingBot - A bot that will automate searches on bing

bingBot A bot that will automate searches on bing. To install this just download

Lukas 2 Jul 28, 2022
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 pyrogram simple bot for Educational purpose.

A pyrogram simple bot for Educational purpose. To Learn More check at @PyrogramBot or on Documentation Mandatory variables API_ID - Get It From my.tel

SpamShield 10 Dec 06, 2022
The Python version of the official Discord bot for the Astura Studios Discord community server.

About Astura (Python version) is the official Discord bot for the Astura Studios Discord community server developed and maintained by Ascendus and the

Ascendus 1 Apr 21, 2022
A multi purpose discord bot for python

Sypher The best multi purpose discord bot. Add Sypher right now Invite Me | Join

Johan Naizu 1 Dec 15, 2022
Many discord bots serving different purposes

Discord_Botlari Farklı amaçlara hizmet eden bir çok discord botu En kapsamlı Bot Game Bottur. bir oyun botudur discord sunucularında kullanılır. (tüm

1 Dec 21, 2021
MusicBot is the original Discord music bot written for Python 3.5+, using the discord.py library

The original MusicBot for Discord (formerly SexualRhinoceros/MusicBot)

Just Some Bots 2.9k Jan 02, 2023
An Async Bot/API wrapper for Twitch made in Python.

TwitchIO is an asynchronous Python wrapper around the Twitch API and IRC, with a powerful command extension for creating Twitch Chat Bots. TwitchIO co

TwitchIO 590 Jan 03, 2023
Telegram Group Manager Bot + Userbot Written In Python Using Pyrogram.

Telegram Group Manager Bot + Userbot Written In Python Using PyrogramTelegram Group Manager Bot + Userbot Written In Python Using Pyrogram

1 Nov 11, 2021
A telegram mirror bot with an integrated RSS feed reader.

About What is this repo? This is a slightly modified fork which includes some extra features & memes added to my liking. How's this different from the

11 May 15, 2022
WhatsApp Web API client with multi-device support

Tauros WhatsApp Web client for multi-device in python Free software: MIT Documentation: https://tauros.readthedocs.io Features TODO Credits This packa

Manjit Pardeshi 0 Jan 20, 2022
This is a repository for the Duke University Cloud Computing course project on Serveless Data Engineering Pipeline. For this project, I recreated the below pipeline.

AWS Data Engineering Pipeline This is a repository for the Duke University Cloud Computing course project on Serverless Data Engineering Pipeline. For

15 Jul 28, 2021
Deep reinforcement learning library built on top of Neural Network Libraries

Deep Reinforcement Learning Library built on top of Neural Network Libraries NNablaRL is a deep reinforcement learning library built on top of Neural

Sony 100 Dec 14, 2022
A Python library for PagerDuty.

Pygerduty Python Library for PagerDuty's REST API and Events API. This library was originally written to support v1 and is currently being updated to

Dropbox 164 Dec 20, 2022
This is a bot which you can use in telegram to spam without flooding and enjoy being in the leaderboard

Telegram-Count-spamming-Bot This is a bot which you can use in telegram to spam without flooding and enjoy being in the leaderboard You can avoid the

Lalan Kumar 1 Oct 23, 2021
Nflmetrics - Johns Hopkins Spring 2022 Sports Analytics research project about NFL Draft Metrics

nflmetrics GitHub repo for Johns Hopkins Spring 2022 Sports Analytics research p

Anish Kulkarni 4 Feb 24, 2022
Extrait les informations contenues dans le code QR de la preuve de vaccination générée par le gouvernement du Québec

DecodeurPreuveVaccinationQC Extrait les informations contenues dans le code QR de la preuve de vaccination générée par le gouvernement du Québec Utili

Guillaume Morissette 8 Jul 26, 2022
Smilecreator4 - This site is for people who want to hack or want to learn it!

smilecreator4 This site is for people who want to hack or want to learn it! Furthermore, this program does not work without turning off Antivirus or W

1 Jan 04, 2022
Change the name and pfp of ur accounts, uses tokens.txt for ur tokens.

Change the name and pfp of ur accounts, uses tokens.txt for ur tokens. Also scrapes the pfps+names from a server chosen by you. For hq tokens go to discord.gg/tokenshop or t.me/praisetelegram

cChimney 36 Dec 09, 2022