タイトルの通り、FastAPIで開発したAPIにServerless Frameworkの authorizer
で設定したCognito認証の情報をPython内で使う方法です。
ほぼ最小構成で書いてます。
FastAPI+Mangum(Python)
利用しているパッケージです。
pyproject.toml
#省略
[tool.poetry.dependencies]
python = "^3.8"
fastapi = "^0.87.0"
mangum = "^0.16.0"
#省略
/auth
というCognito認証情報だけ返すAPIです。
http.py
from fastapi import FastAPI
from mangum import Mangum
from starlette.requests import Request
app = FastAPI()
@app.get("/auth")
def get_auth(request: Request):
# Cognitoの認証情報がrequest変数の中に入っています
auth_info = request.scope["aws.event"]["requestContext"]["authorizer"]
return {"auth": auth_info}
handler = Mangum(app, lifespan="off")
Serverless Framework
以下の通りデプロイします。※ CognitoのUserPoolのARNだけダミーです。
serverless.yml
service: echo-auth
frameworkVersion: "3"
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
usePoetry: true
provider:
name: aws
runtime: python3.8
stage: dev
region: ap-northeast-1
package:
patterns:
- "./**"
- "./http.py"
functions:
api:
handler: http.handler
memorySize: 128
events:
- http:
path: /auth
method: GET
authorizer:
name: cognito
arn: arn:aws:cognito-idp:ap-northeast-1:123456789012:userpool/ap-northeast-1_Txxxxxxx
試してみる
CognitoからID Tokenを取得してAPIを実行してみます。
ID_TOKEN=eyJ....
curl -s https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/auth -H "Authorization: ${ID_TOKEN}" | jq
以下のような情報が取得可能です。
{
"auth": {
"claims": {
"at_hash": "xxxxxxxxxxxxxxxxxxxx",
"sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"email_verified": "true",
"iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_Txxxxxx",
"cognito:username": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"origin_jti": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"aud": "xxxxxxxxxxxxxxxxxxxx",
"token_use": "id",
"auth_time": "1669009768",
"exp": "Tue Nov 22 05:49:28 UTC 2022",
"iat": "Mon Nov 21 05:49:28 UTC 2022",
"jti": "56a45e94-cd73-4675-93fc-d396260c3880",
"email": "yusuke.otomo@mail.com"
}
}
}
Dependsを使った方法
Dependsを使った方法もあります。こっちの方がスッキリ処理できる要件もあります。
http.py
from fastapi import FastAPI, Depends, Request
from fastapi.exceptions import HTTPException
from mangum import Mangum
def auth_verify(request: Request):
try:
auth_info = request.scope["aws.event"]["requestContext"]["authorizer"]
print(f"auth_verify -> {auth_info}")
except:
raise HTTPException(status_code=403)
app = FastAPI()
@app.get("/auth",dependencies=[Depends(auth_verify)])
def get_auth():
return {"auth": "ok"}
handler = Mangum(app, lifespan="off")
参考