'FastAPI: security with firebase token

I'm following this tutorial to create an api backend.

I use firebase authentication:

  • user input email and password at frontend
    • front sends the info to firebase
    • firebase auth user and return token
    • front stores the token
  • for any url that needs auth, front sends the token in Authorization header (Bearer xxx)
  • server side firebase checks the token

The tutorial shows how to do this with a password:

# creating a dependency
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = fake_decode_token(token)
    return user

But since I'm using firebase, there is no /token for getting token with password.

I can parse the token by creating a custom dependency, like:

async def parse_token(auth_token:str = Header(...)):
    token = auth_token.split(' ')[1]
    return token

async def get_current_user(token: str = Depends(parse_token)):
    # check the token with firebase auth
    user = auth.verify_id_token(token)
    return user

But now I have to check everything and return exceptions manually.

Is there a FastAPI way to do this?



Solution 1:[1]

Simply ignore it.

The /token endpoint is used to authenticate and generate the token (on successful attempt). It's just a login page/form. You simply skip that part and use a dependency that will perform the check.

Of course, you have to follow the same name and positioning of the OAuth2Password stuff.

Remember, HTTP is stateless, and tokens are used to remember that a user has already provided identification. If you have a valid token, you can also swap it on another machine and use it (unless there are some security cookies and machine-related information is stored within the cookie).

If you go on with the tutorial that you linked, you'll get to the final code with the authentication. Simply provide the firebase token in the "Authorization: Bearer {token}" of your requests from the frontend to the backend and it will work.

Below the link to the documentation.

https://fastapi.tiangolo.com/tutorial/security/simple-oauth2/

Solution 2:[2]

I had similar use case and on googling I got to this question. But it was not of much help to me. Upon further research I came across this post which was of much help. Just create a dependency as follows;

from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from fastapi import Depends, HTTPException, status, Response
from firebase_admin import auth, credentials
import firebase_admin

cred = credentials.Certificate('./account_key.json')
firebase_admin.initialize_app(cred)

def get_user(res: Response, cred: HTTPAuthorizationCredentials=Depends(HTTPBearer(auto_error=False))):
    if cred is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Bearer authentication required",
            headers={'WWW-Authenticate': 'Bearer realm="auth_required"'},
        )
    try:
        decoded_token = auth.verify_id_token(cred.credentials)
    except Exception as err:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=f"Invalid authentication credentials. {err}",
            headers={'WWW-Authenticate': 'Bearer error="invalid_token"'},
        )
    res.headers['WWW-Authenticate'] = 'Bearer realm="auth_required"'
    return decoded_token

Then add the dependency on the endpoints you would like to protect as follows

async def hello_user(user = Depends(get_user))

This integrates nicely with Swagger endpoint and you can then receive idToken on your requests and just use them as you you wish. Very much thanks to the poster

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 lsabi
Solution 2 Muteshi