'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 |