FastAPI is convenient. I personally use it as a framework that makes it easy to build an API server. This time, we will add an authentication function to the Fast API.
** Caution **: Setup such as FastAPI and Firebase installation is not mentioned here as a prerequisite.
I think there is a lot of demand to identify and authenticate the user who requested the server and control the appropriate permission for the requested resource. Here, we will implement Bearer authentication, which can be easily implemented by simply adding it to the HTTP header.
[Qiita] "About Bearer Authentication"
Can be specified as a scheme in the HTTP Authorization header and is specified as
Authorization: Bearer <token>. The token format is specified in the token68 format.
Since it is difficult to implement the issuance and verification of token by yourself, we will use Firebase this time.
Illustrates the whole picture of Bearer authentication using Firebase

tokentokentoken to validate it.
If the verification is successful, the user identification / authentication is completed.Implement authentication function using Firebase Admin SDK
Get a Firebase account in advance. First, open the project console (https://console.firebase.google.com/u/0/)
Open the settings from the gear icon in the upper right

Get the private key as a JSON file from the button at the bottom of the Service Accounts tab. Here, save it as account_key.json.

$ pip install firebase_admin
First, prepare a simple endpoint and build a minimum API server.
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/api/")
async def hello():
    return {"msg":"Hello, this is API server"}
Let's set up a test server with uvicorn
$ uvicorn main:app --port 8001 --reload
Let's hit the API server as a trial (Web browser is also OK)
PS > curl http://localhost:8001/api
StatusCode        : 200
StatusDescription : OK
Content           : {"msg":"Hello, this is API server"}
RawContent        : HTTP/1.1 200 OK
                    Content-Length: 35
                    Content-Type: application/json
                    Date: Wed, 18 Nov 2020 11:11:20 GMT
                    Server: uvicorn
                    {"msg":"Hello, this is API server"}
user.py
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
First, you need to extract token from the Authorization header. FastAPI is convenient because you can also validate the authentication header of the request.
[FastAPI] Query Parameters and String Validations
[Qiita] Firebase Authentication token acquisition with Python and token verification with Fast API
Next, verify token. The above code defines what to do if the token does not exist and is invalid. The content of the response to the error conforms to RFC 6750, which defines Bearer authentication. Just throw HTTPExeption and the Fast API will pick it up and generate a response, so it's easy.
Official Firebase documentation
Firebase Admin Python SDK
[[Qiita] To implement an RFC 6750 compliant Bearer scheme](https://qiita.com/uasi/items/cfb60588daa18c2ec6f5#rfc-6750-%E3%81%AB%E6%BA%96%E6 % 8B% A0% E3% 81% 97% E3% 81% 9F-bearer-% E3% 82% B9% E3% 82% AD% E3% 83% BC% E3% 83% A0% E3% 82% 92% E5% AE% 9F% E8% A3% 85% E3% 81% 99% E3% 82% 8B% E3% 81% AB% E3% 81% AF)
** Caution **: When HTTPBearer (auto_error = True) (default) is set, for requests without token
PS > curl http://localhost:8001/api/me                            
curl : {"detail":"Not authenticated"}
PS > $error[0].exception
Remote server returned an error: (403)Unavailable
And FastAPI will generate exception handling + response without permission.
Add an API endpoint that requires user authentication.
main.py
from fastapi import FastAPI, Depends
from user import get_user
app = FastAPI()
@app.get("/api/")
async def hello():
    return {"msg":"Hello, this is API server"} 
@app.get("/api/me")
async def hello_user(user = Depends(get_user)):
    return {"msg":"Hello, user","uid":user['uid']} 
uid is the identifier of the user who logged in to Firebase, and can identify not only e-mail & password but also users authenticated by various services such as Twitter and Google.
Let's actually hit the API from the client and see the response.
tokenSelect a project from Firebase Console and copy from Settings> General.

Assuming that the user (e-mail & password) is already registered in the project
POSThttps://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${API_KEY}
--Body: Information required for login written in JSON{
  "email":"[email protected]",
  "password":"your password",
  "returnSecureToken":true
}
[Firebase] Auth REST API-Official Documentation
PS >  curl -Method Post -Body $Body -Headers @{"content-type"="application/json"} $URL
StatusCode        : 200
StatusDescription : OK
Content           : {
                      "kind": "identitytoolkit#VerifyPasswordResponse",
                      "localId": "OZzdeAtK4VM4OlHHbUXTY6YNr8C3",
                      "email": "[email protected]",
                      "displayName": "",
                      "idToken": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjNlNTQ...
RawContent        : HTTP/1.1 200 OK
                    Pragma: no-cache
                    Vary: X-Origin,Referer,Origin,Accept-Encoding
                    X-XSS-Protection: 0
                    X-Frame-Options: SAMEORIGIN
                    X-Content-Type-Options: nosniff
                    Alt-Svc: h3-Q050=":443"; ma=2592000...
The response is also JSON and uses the value of idToken for Bearer authentication.
PS > curl -Headers @{"Authorization"="Bearer ${token}"} http://localhost:8001/api/me
StatusCode        : 200                                                         
StatusDescription : OK                                                          
Content           : {"msg":"Hello, user","uid":"OZzdeAtK4VM4OlHHbUXTY6YNr8C3"}  
RawContent        : HTTP/1.1 200 OK                                                                 
                    Content-Length: 58                                                              
                    Content-Type: application/json                                                  
                    Date: Fri, 20 Nov 2020 15:28:18 GMT                                             
                    Server: uvicorn                                                                 
                    WWW-Authenticate: Bearer realm="auth_required"       
                                                                                                           
                    {"msg":"Hello, user","uid":... 
token exampleTry to play with the value of token and pass it
PS > curl -Headers @{"Authorization"="Bearer ${token}"} http://localhost:8001/api/me
curl : {"detail":"Invalid authentication credentials. Could not verify token signature."}
token defectPS > curl http://localhost:8001/api/me                                              
curl : {"detail":"Bearer authentication required"}
        Recommended Posts