Fastapi Either Or Dependencies

61 Views Asked by At

I'm using FastAPI and FastAPI-users for protected routes which can be accessed by either:

user login (with fastapi-users way), api key (from using fastapi's Security)

I need a way to do the "either or" on the dependency injection

@router.get('/protected')
def wrapper_layout(
    layoutRun: LayoutRun,

    user: User = Depends(current_active_user),
    user: User = Security(get_user_from_api_key)
 ): 

I want either user from either [current_active_user] or [get_api_key]

I would like something like

@router.get('/protected')
def wrapper_layout(layoutRun: LayoutRun): 

    try:
        user = Security(get_api_key)
        return user
    except:
        user = Depends(current_active_user)            
        return user

I could try to get this to work, but i have to assume fastapi's dependency injection system thought about sites with many different auth schemes and only one has to pass.

1

There are 1 best solutions below

0
On

The idea is to make both of these security schemes 'optional' (so they don't throw an exception if user isn't authorized) and then check that at least one of them returns valid user.

Pass auto_error=False to constructor of FastAPI security scheme.

Pass optional=True when you are getting the function for user validation in FastAPI Users.

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/users/token", auto_error=False)
current_active_user = fastapi_users.current_user(optional=True, active=True)

Then create dependency function which includes both security dependemcies and checks whether one of them is valid.

def get_user(
    user1: User = Depends(current_active_user),
    user2: User = Security(oauth2_scheme)
):
    if user1 is not None:
        return user1
    elif user2 is not None:
        return user2
    else:
        raise HTTPException(401)

And then use this dependency to protect you routes:

@app.get("/")
def index(user: User = Security(get_user)):
   pass