Package: fastapi-cloudauth
FastAPI Cloud Authfastapi-cloudauth standardizes and simplifies the integration between FastAPI and cloud authentication services (AWS Cognito, Auth0, Firebase Authentication).FeaturesVerify access/id token: standard JWT validation (signature, expiration), token audience claims, etc.Verify permissions based on scope (or groups) within access token and extract user infoGet the detail of login user info (name, email, etc.) within ID tokenDependency injection for verification/getting user, powered byFastAPISupport for:AWS CognitoAuth0Firebase Auth(Only ID token)RequirementsPython 3.6+Install$pipinstallfastapi-cloudauthExample (AWS Cognito)Pre-requirementsCheckregion,userPoolIDandAppClientIDof AWS Cognito that you manage toCreate a user's assignedread:userspermission in AWS CognitoGet Access/ID token for the created userNOTE: access token is valid for verification, scope-based authentication, and getting user info (optional). ID token is valid for verification and getting full user info from claims.Create itCreate amain.pyfile with the following content:importosfrompydanticimportBaseModelfromfastapiimportFastAPI,Dependsfromfastapi_cloudauth.cognitoimportCognito,CognitoCurrentUser,CognitoClaimsapp=FastAPI()auth=Cognito(region=os.environ["REGION"],userPoolId=os.environ["USERPOOLID"],client_id=os.environ["APPCLIENTID"])@app.get("/",dependencies=[Depends(auth.scope(["read:users"]))])defsecure():# access token is validreturn"Hello"classAccessUser(BaseModel):sub:str@app.get("/access/")defsecure_access(current_user:AccessUser=Depends(auth.claim(AccessUser))):# access token is valid and getting user info from access tokenreturnf"Hello",{current_user.sub}get_current_user=CognitoCurrentUser(region=os.environ["REGION"],userPoolId=os.environ["USERPOOLID"],client_id=os.environ["APPCLIENTID"])@app.get("/user/")defsecure_user(current_user:CognitoClaims=Depends(get_current_user)):# ID token is valid and getting user info from ID tokenreturnf"Hello,{current_user.username}"Run the server with:$uvicornmain:appINFO:     Started server process [15332]INFO:     Waiting for application startup.INFO:     Application startup complete.INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)Interactive API DocGo tohttp://127.0.0.1:8000/docs.You will see the automatic interactive API documentation (provided by Swagger UI).Authorize:unlock: button can be available at the endpoint's injected dependency.You can supply a token and try the endpoint interactively.Example (Auth0)Pre-requirementCheckdomain,customAPI(Audience) andClientIDof Auth0 that you manage toCreate a user assignedread:userspermission in Auth0Get Access/ID token for the created userCreate itCreate a file main.py with:importosfrompydanticimportBaseModelfromfastapiimportFastAPI,Dependsfromfastapi_cloudauth.auth0importAuth0,Auth0CurrentUser,Auth0Claimsapp=FastAPI()auth=Auth0(domain=os.environ["DOMAIN"],customAPI=os.environ["CUSTOMAPI"])@app.get("/",dependencies=[Depends(auth.scope(["read:users"]))])defsecure():# access token is validreturn"Hello"classAccessUser(BaseModel):sub:str@app.get("/access/")defsecure_access(current_user:AccessUser=Depends(auth.claim(AccessUser))):# access token is valid and getting user info from access tokenreturnf"Hello",{current_user.sub}get_current_user=Auth0CurrentUser(domain=os.environ["DOMAIN"],client_id=os.environ["CLIENTID"])@app.get("/user/")defsecure_user(current_user:Auth0Claims=Depends(get_current_user)):# ID token is valid and getting user info from ID tokenreturnf"Hello,{current_user.username}"Try to run the server and see interactive UI in the same way.Example (Firebase Authentication)Pre-requirementCreate a user in Firebase Authentication and getproject IDGet ID token for the created userCreate itCreate a file main.py with:fromfastapiimportFastAPI,Dependsfromfastapi_cloudauth.firebaseimportFirebaseCurrentUser,FirebaseClaimsapp=FastAPI()get_current_user=FirebaseCurrentUser(project_id=os.environ["PROJECT_ID"])@app.get("/user/")defsecure_user(current_user:FirebaseClaims=Depends(get_current_user)):# ID token is valid and getting user info from ID tokenreturnf"Hello,{current_user.user_id}"Try to run the server and see the interactive UI in the same way.Additional User InformationWe can get values for the current user from access/ID token by writing a few lines.Custom ClaimsFor Auth0, the ID token contains the following extra values (Ref atAuth0 official doc):{"iss":"http://YOUR_DOMAIN/","sub":"auth0|123456","aud":"YOUR_CLIENT_ID","exp":1311281970,"iat":1311280970,"name":"Jane Doe","given_name":"Jane","family_name":"Doe","gender":"female","birthdate":"0000-10-31","email":"janedoe@example.com","picture":"http://example.com/janedoe/me.jpg"}By default,Auth0CurrentUsergivespydantic.BaseModelobject, which hasusername(name) andemailfields.Here is sample code for extracting extra user information (addinguser_id) from ID token:frompydanticimportFieldfromfastapi_cloudauth.auth0importAuth0Claims# base current user info model (inheriting `pydantic`).# extend current user info model by `pydantic`.classCustomAuth0Claims(Auth0Claims):user_id:str=Field(alias="sub")get_current_user=Auth0CurrentUser(domain=DOMAIN,client_id=CLIENTID)get_current_user.user_info=CustomAuth0Claims# override user info model with a custom one.Or, we can set new custom claims as follows:get_user_detail=get_current_user.claim(CustomAuth0Claims)@app.get("/new/")asyncdefdetail(user:CustomAuth0Claims=Depends(get_user_detail)):returnf"Hello,{user.user_id}"Raw payloadIf you don't requirepydanticdata serialization (validation),FastAPI-CloudAuthhas an option to extract the raw payload.All you need is:get_raw_info=get_current_user.claim(None)@app.get("/new/")asyncdefraw_detail(user=Depends(get_raw_info)):# user has all items (ex. iss, sub, aud, exp, ... it depends on passed token)returnf"Hello,{user.get('sub')}"Additional scopesAdvanced user-SCOPE verification to protect your API.Supports:all (default): required all scopes you setany: At least one of the configured scopes is requiredUse as (authis this instanse andappis fastapi.FastAPI instanse):fromfastapiimportDependsfromfastapi_cloudauthimportOperator@app.get("/",dependencies=[Depends(auth.scope(["allowned","scopes"]))])defapi_all_scope():return"user has 'allowned' and 'scopes' scopes"@app.get("/",dependencies=[Depends(auth.scope(["allowned","scopes"],op=Operator._any))])defapi_any_scope():return"user has at least one of scopes (allowned, scopes)"Development - ContributingPlease readCONTRIBUTINGfor how to set up the development environment and testing.