├── Pipfile ├── README.md ├── main.py ├── models.py └── test.py /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | fastapi = "*" 8 | uvicorn = "*" 9 | firebase-admin = "*" 10 | pyrebase4 = "*" 11 | requests = "*" 12 | 13 | [dev-packages] 14 | 15 | [requires] 16 | python_version = "3.11" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FastAPI_firebase_auth 2 | A very simple REST API built to demonstrate how to use Firebase Authentication with FastAPI 3 | 4 | 5 | ## How to run 6 | - Install requirements with ```pipenv install ``` 7 | 8 | - Get Firebase Auth credentials and also Service account keys 9 | 10 | - Run API with ```python main.py``` -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import uvicorn 2 | import pyrebase 3 | from fastapi import FastAPI 4 | from models import LoginSchema,SignUpSchema 5 | from fastapi.responses import JSONResponse 6 | from fastapi.exceptions import HTTPException 7 | from fastapi.requests import Request 8 | 9 | app = FastAPI( 10 | description="This is a simple app to show Firebase Auth with FastAPI", 11 | title="Firebase Auth", 12 | docs_url="/" 13 | ) 14 | 15 | 16 | 17 | import firebase_admin 18 | from firebase_admin import credentials,auth 19 | 20 | 21 | if not firebase_admin._apps: 22 | cred = credentials.Certificate("serviceAccountKey.json") #get your service account keys from firebase 23 | firebase_admin.initialize_app(cred) 24 | 25 | 26 | firebaseConfig = { 27 | "message":"Get your config from firebase" 28 | } 29 | 30 | firebase = pyrebase.initialize_app(firebaseConfig) 31 | 32 | 33 | @app.post('/signup') 34 | async def create_an_account(user_data:SignUpSchema): 35 | email = user_data.email 36 | password = user_data.password 37 | 38 | try: 39 | user = auth.create_user( 40 | email = email, 41 | password = password 42 | ) 43 | 44 | return JSONResponse(content={"message" : f"User account created successfuly for user {user.uid}"}, 45 | status_code= 201 46 | ) 47 | except auth.EmailAlreadyExistsError: 48 | raise HTTPException( 49 | status_code=400, 50 | detail= f"Account already created for the email {email}" 51 | ) 52 | 53 | 54 | 55 | 56 | 57 | @app.post('/login') 58 | async def create_access_token(user_data:LoginSchema): 59 | email = user_data.email 60 | password = user_data.password 61 | 62 | try: 63 | user = firebase.auth().sign_in_with_email_and_password( 64 | email = email, 65 | password = password 66 | ) 67 | 68 | token = user['idToken'] 69 | 70 | return JSONResponse( 71 | content={ 72 | "token":token 73 | },status_code=200 74 | ) 75 | 76 | except: 77 | raise HTTPException( 78 | status_code=400,detail="Invalid Credentials" 79 | ) 80 | 81 | @app.post('/ping') 82 | async def validate_token(request:Request): 83 | headers = request.headers 84 | jwt = headers.get('authorization') 85 | 86 | user = auth.verify_id_token(jwt) 87 | 88 | return user["user_id"] 89 | 90 | if __name__ == "__main__": 91 | uvicorn.run("main:app",reload=True) -------------------------------------------------------------------------------- /models.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | 5 | class SignUpSchema(BaseModel): 6 | email:str 7 | password:str 8 | 9 | class Config: 10 | schema_extra ={ 11 | "example":{ 12 | "email":"sample@gmail.com", 13 | "password":"samplepass123" 14 | } 15 | } 16 | 17 | 18 | class LoginSchema(BaseModel): 19 | email:str 20 | password:str 21 | 22 | class Config: 23 | schema_extra ={ 24 | "example":{ 25 | "email":"sample@gmail.com", 26 | "password":"samplepass123" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhkMDNhZTdmNDczZjJjNmIyNTI3NmMwNjM2MGViOTk4ODdlMjNhYTkiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZmFzdGFwaWF1dGgtM2YyNmQiLCJhdWQiOiJmYXN0YXBpYXV0aC0zZjI2ZCIsImF1dGhfdGltZSI6MTY4NzU0MTYzNSwidXNlcl9pZCI6Im9DTUozVXZ0MGxWVGFYSlF3Nmt0MHhKbTNTdDIiLCJzdWIiOiJvQ01KM1V2dDBsVlRhWEpRdzZrdDB4Sm0zU3QyIiwiaWF0IjoxNjg3NTQxNjM1LCJleHAiOjE2ODc1NDUyMzUsImVtYWlsIjoic2FtcGxlQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwiZmlyZWJhc2UiOnsiaWRlbnRpdGllcyI6eyJlbWFpbCI6WyJzYW1wbGVAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoicGFzc3dvcmQifX0.ht9CELI9qRJJhQ1a4wMpVB_b_NzMolgIYVN3uEQDaVC3p-WEmtuh_eySPta7GkBaVErmzDUxyzun9xsm7y01s51E7S3vptYYKh3m_g87_hbaOmuflYUuCigDMaEDVBJX-nd4LoaTh0jLogScf05_3oxAQlz---eztUoo9r-qigIMyLHz7e7B_7mT3Te77OYHd5a9VbXFBk-2JmLU0WqjKsIpsY_MJwSGbHKmi6O6j7_WumHxneK4LYx56SzZZEppouU4VzY7gdXU3JQlHFu5Q852h8CP-TB9OkBFjsc4xlOMkTDpEh8ANvXYxvYp5mRMyXvPwPcJjKggnyaOMy8e-Q" 4 | 5 | 6 | def test_validate_endpoint(): 7 | headers = { 8 | 'authorization':token 9 | } 10 | 11 | response = requests.post( 12 | "http://127.0.0.1:8000/ping", 13 | headers=headers 14 | ) 15 | 16 | return response.text 17 | 18 | 19 | print(test_validate_endpoint()) 20 | 21 | 22 | --------------------------------------------------------------------------------