Skip to content

'Depends' object has no attribute '...' [HELP NEEDED] #3707

@ricardo-reis-1970

Description

@ricardo-reis-1970

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google "How to X in FastAPI" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

credentials_exception = HTTPException(
    status_code=status.HTTP_401_UNAUTHORIZED,
    detail="Could not validate credentials",
    headers={"WWW-Authenticate": "Bearer"},
)

def get_user(username: str):
    user = User.get_by_username(username) # CHANGE
    if user:
        return user

async def get_current_user(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError:
        raise credentials_exception
    user = get_user(username=token_data.username) # CHANGE
    if user is None:
        raise credentials_exception
    return user

async def check_role(role: str):
    current_user = await get_current_user()
    print(f"[check_role] current_user: {current_user}")
    roles = [role.name for role in current_user.roles]
    return role in roles

async def check_admin():
    if await check_role('admin'):
        return True
    else:
        raise credentials_exception

Description

I'm trying to use security dependencies throughout my API, in order to make sure that endpoints are only available to the appropriate roles or privileges. Please note that in the above example, I'm defining a wrapper called check_admin because Depends won't allow me to pass the parameter 'admin' directly to check_role (what a shame!).

I'm using the example from https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/ with very small adjustments, such as getting the user from a SQLAlchemy call: User.get_by_username(username). I also pulled the credentials_exception out to the global scope, in order to use it from different places.

I've been moving away from Depends, because it's working in a rather unexpected way: instead of calling whatever dependency and returning its result, it's returning a Depends object, which I don't know what to do with.

For instance, I started with:

async def check_role(role: str, current_user: UserSchema = Depends(get_current_user)):
    roles = [role.name for role in current_user.roles]
    return role in roles

but I got:

AttributeError: 'Depends' object has no attribute 'roles'

Every time I convert what used to be a dependency into an explicit call, such as:

async def check_role(role: str):
    current_user = await get_current_user()
    roles = [role.name for role in current_user.roles]
    return role in roles

all I achieve is to propagate the Depends exception to the next function, in this case:

AttributeError: 'Depends' object has no attribute 'rsplit'

because get_current_user got the token Depends(OAuth2PasswordBearer) (instead of an actual token) and then, in the line:

payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])

it raises the above exception.

From the docs — Dependencies - First Steps > Simple and Powerful —, I was under the impression that I could use any level of dependencies, and that these were precisely designed to simplify the code, instead of mixing everything in the 'man finction', working a bit like decorators:

Questions

  • am I messing up things with async?
  • should I only use Depends on endpoint functions?
  • should I update any version (FastAPI, Python itself)?

This is blocking my entire API so far. Googling this leads always to the very documentation whose examples I'm unsuccessfully replicating. My only option has been to leave it totally insecure. I work in a highly regulated market. I need help.

Operating System

Windows

Operating System Details

No response

FastAPI Version

0.66.0

Python Version

3.9.0

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions