Login for access token 422 Validation Error FastApi

125 views Asked by At

I want make autorization on my site using this code (It is not important for me to use this particular authorization option. If you have other options for implementing authorization on the site, I will be glad to consider them)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


SECRET_KEY = "somekeyfasfascsacs"
ALGORITHM = "HS256"

bcrypt_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

oauth2_bearer = OAuth2PasswordBearer(tokenUrl="auth/token")


db_dependency = Annotated[Session, Depends(get_db)]


def authenticate_user(username: str, password: str, db: db_dependency):
    user = db.query(Users).filter(Users.username == username).first()
    if not user:
        return False
    if not bcrypt_context.verify(password, user.hashed_password):
        return False
    print(type(user))
    return user


def create_access_token(username: str, user_id: int,
                        expires_delta: Optional[datetime.timedelta] = None):

    encode = {"sub": username, "id": user_id}
    if expires_delta:
        expire = datetime.datetime.utcnow() + expires_delta
    else:
        expire = datetime.datetime.utcnow() + datetime.timedelta(minutes=15)
    encode.update({"exp": expire})
    return jwt.encode(encode, SECRET_KEY, algorithm=ALGORITHM)


async def get_current_user(token: Annotated[str, Depends(oauth2_bearer)]):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        user_id: int = payload.get("id")
        user_role: str = payload.get("role")
        if username is None or user_id is None:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate user")
        return {"username": username, "id": user_id, "user_role": user_role}
    except JWTError:
        # When authorizing using a button and trying to use other functions,
        # it gives this error
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate user")


@router.post("/token")
async def login_for_access_token(response: Response, form_data: OAuth2PasswordRequestForm = Depends(),
                                 db: Session = Depends(get_db)):

    user = authenticate_user(form_data.username, form_data.password, db)
    if not user:
        return False
    token_expires = datetime.timedelta(minutes=60)
    token = create_access_token(user.username,
                                user.id,
                                expires_delta=token_expires)

    response.set_cookie(key="access_token", value=token, httponly=True)

    return True

But I get this error:

enter image description here

If you log in through the Autorize button, it doesn’t give you an error, but when you try to use other functions, the site gives you a 401 Unautorize error.

enter image description here

1

There are 1 answers

0
Yurii Motov On BEST ANSWER

You should return token in async def login_for_access_token instead of returning True.

If you use OAuth2PasswordBearer auth schema, then Swager (documentation system) expects to receive token in the response body, not in cookies.

return {"access_token": user.username, "token_type": "bearer"}