Using Firebase and Fast API, get the token on the client side, paste it in the header when hitting your own API, and verify on the server side to determine if you are logged in. Here, we will verify the token using the Google-made firebase_admin
.
Enable password login in Authentication on the Firebase console and create a suitable account like the one below. Here, log in using this.
EMAIL = '[email protected]'
PASSWORD = 'password'
Install what you need.
$ pip install requests
Get the following JSON from the firebase console and paste it into a nice shape. (Actually use only ʻapiKey`)
CONFIG = {
"apiKey": "YOUR API KEY",
"authDomain": "YOURPROJECTID.firebaseapp.com",
"databaseURL": "https://YOURPROJECTID.firebaseio.com",
"projectId": "YOUR PROJECT ID",
"storageBucket": "YOUR PROJECT ID.appspot.com",
"messagingSenderId": "YOUR MESSAGE SENDER ID",
"appId": "YOUR:APP:ID",
"measurementId": "YOUR MEASUREMENT ID"
}
Hit the REST API of Firebase Auth to get the token. The REST API documentation is here.
api_key = CONFIG["apiKey"]
uri = f"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key={api_key}"
data = {"email": EMAIL, "password": PASSWORD, "returnSecureToken": True}
result = requests.post(url=uri, data=data).json()
token = result['idToken']
Output this token at run time and use it later.
Install what you need.
$ pip install fastapi firebase_admin uvicorn
From the firebase console, go to Gear → Service Account → Generate New Private Key to download and load the private key.
from firebase_admin import auth, credentials
cred = credentials.Certificate("path/to/cert.json")
firebase_admin.initialize_app(cred)
Define a function that gets the token from the header, decodes it, and gets the user information.
Actually, I think you can get the user information from the DB here.
The FastAPI docs provided an example of using fastapi.security.OAuth2PasswordBearer
, but it didn't describe how to simply get a Bearer token, I had to look at the code.
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from fastapi import Depends, HTTPException, status
def get_current_user(cred: HTTPAuthorizationCredentials = Depends(HTTPBearer())):
try:
decoded_token = auth.verify_id_token(cred.credentials)
except:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail='Invalid authentication credentials',
headers={'WWW-Authenticate': 'Bearer'},
)
user = decoded_token['firebase']['identities']
return user
Defines an endpoint that can only be accessed with a valid Bearer token. FastAPI is really useful because you can inject what you want with Depends and type annotations.
from fastapi import FastAPI, Depends, HTTPException, status
app = FastAPI()
@app.get('/')
async def homepage(current_user=Depends(get_current_user)):
return {'msg': 'ok', 'user': current_user}
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host='localhost', port=5000)
The code so far is summarized in Gist. First, use the code below to get the token and copy it. https://gist.github.com/pteroid/241687ecb5219ae0ce633a884d8ab5bb
Then start the server with the following code. https://gist.github.com/pteroid/a698fd679fb545cb2cfe792f0114938c
Hit it with a suitable REST client (I use Insomnia). Then you will get the following result.
request
> GET / HTTP/1.1
> Host: localhost:5000
> User-Agent: insomnia/7.1.1
> Authorization: Bearer
YOURTOKENYOURTOKENYOURTOKENYOURTOKENYOURTOKENYOURTOKENYOURTOKENYOURTOKENYOURTOKENYOURTOKENYOURTOKEN
> Accept: */*
response
{
"msg": "ok",
"user": {
"identities": {
"email": [
"[email protected]"
]
},
"sign_in_provider": "password"
}
}
FastAPI I want you to be more popular.
Recommended Posts