Python 3.x 是否有一个FastAPI库可用于将端点标记为受保护并验证仅HTTP Cookie中的Auth JWT令牌?
我试图学习和使用AWS Cognito用户池,并与Python FastAPI集成,并使用Python FastAPI实现API。到目前为止,我正在使用授权代码流和我的Cognito用户池重定向到FastAPI上的端点来解决代码挑战。源代码附加在此查询的末尾 API具有以下端点:Python 3.x 是否有一个FastAPI库可用于将端点标记为受保护并验证仅HTTP Cookie中的Auth JWT令牌?,python-3.x,amazon-cognito,openid-connect,openid,fastapi,Python 3.x,Amazon Cognito,Openid Connect,Openid,Fastapi,我试图学习和使用AWS Cognito用户池,并与Python FastAPI集成,并使用Python FastAPI实现API。到目前为止,我正在使用授权代码流和我的Cognito用户池重定向到FastAPI上的端点来解决代码挑战。源代码附加在此查询的末尾 API具有以下端点: 根端点[/]:将浏览器重定向到my AWS Cognito用户池的登录页面 重定向端点[/aws\u cognito\u Redirect]:成功登录到用户池后激活。从cognito用户池接收代码质询。在下面显示的代码
aws\u cognito\u redirect
端点通过向aws cognito用户池oauth2/token
端点发送代码质询、重定向uri、客户端id等来解决代码质询。我可以在控制台日志输出中看到,标识、访问和刷新令牌已成功检索/aws\u cognito\u redirect
端点在仅HTTP会话cookie中返回令牌。这样,每个后续的客户端请求都会自动包含cookie,而不会在浏览器本地存储中公开任何令牌。我知道我必须使用此选项处理XSRF/CSRF
或者,我可以使用Angular/React实现前端。据推测,建议的做法似乎是,我必须将授权流重新配置为PKCE的身份验证代码?在这种情况下,Angular/React web客户端将直接与AWS Cognito通信,以检索将转发到FastAPI端点的令牌。这些令牌将存储在浏览器的本地存储器中,然后在每个后续请求的授权标头中发送。我知道这种方法会受到XSS攻击
考虑到我的需求,我认为我倾向于使用jinja2模板在FastAPI上托管webapp,并在成功登录时返回一个仅限HTTP的会话cookie
如果我选择了这个实现路径,是否有一个FastAPI特性或Python库允许端点被修饰/标记为auth required
,以检查会话cookie的存在并执行令牌验证
FastAPI
导入base64
从functools导入lru\U缓存
进口httpx
从fastapi导入依赖、fastapi、请求
从fastapi.responses导入重定向响应
从…起导入配置
app=FastAPI()
@lru_缓存()
def get_设置():
“”“创建封装应用程序配置的配置设置实例。”“”
返回config.Settings()
def encode_auth_头(客户端id:str,客户端机密:str):
“”“将客户端id和密码编码为base64客户端id:client\u secret。”“”
secret=base64.b64编码(
字节(客户端id,“utf-8”)+b:“+字节(客户端机密,“utf-8”)
)
返回“Basic”+secret.decode()
@app.get(“/”)
def read_root(设置:config.settings=Depends(获取设置)):
登录\u url=(
“https://”
+设置.domain
+“.auth。”
+设置。区域
+“.amazoncignito.com/login?客户端id=”
+settings.client\u id
+“&response\u type=code&scope=email+openid&redirect\u uri=”
+settings.redirect\u uri
)
打印(“重定向到”+登录地址)
返回重定向响应(登录\ url)
@app.get(“/aws\u cognito\u redirect”)
异步def读取代码挑战(
请求:请求,设置:配置。设置=依赖(获取设置)
):
“”“从oauth2/令牌终结点检索令牌”“”
代码=请求。查询参数[“代码”]
打印(“/aws\u cognito\u重定向收到的代码:=”,代码)
auth\u secret=encode\u auth\u头(settings.client\u id,settings.client\u secret)
headers={“授权”:auth_secret}
打印(“授权:+str(标题[“授权”]))
有效载荷={
“客户端id”:settings.client\u id,
“代码”:代码,
“授权类型”:“授权代码”,
“redirect_uri”:settings.redirect_uri,
}
令牌\u url=(
“https://”
+设置.domain
+“.auth。”
+设置。区域
+“.amazoncignito.com/oauth2/token”
)
使用httpx.AsyncClient()作为客户端进行异步:
令牌=wait client.post(
令牌地址,
数据=有效载荷,
标题=标题,
)
打印(“Tokens\n”+str(Tokens.json()))
FastAPI高度依赖依赖依赖项注入,依赖项注入也可用于身份验证。您只需编写一个简单的依赖项来检查cookie:
async def verify_access(secret_token: Optional[str] = Cookie(None)):
if secret_token is None or secret_token not in valid_tokens:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
)
return secret_token
并将其作为依赖项在视图中使用:
@app.get("/")
def read_root(settings: config.Settings = Depends(get_settings), auth_token = Depends(verify_access)):
...
app = FastAPI()
auth_required_router = APIRouter()
app.include_router(
auth_required_router, dependencies=[Depends(verify_access)],
)
@auth_required_router.get("/")
def read_root(settings: config.Settings = Depends(get_settings)):
...
如果要保护一组端点,可以定义附加路由器,该路由器将始终包含verify\u access
作为依赖项:
@app.get("/")
def read_root(settings: config.Settings = Depends(get_settings), auth_token = Depends(verify_access)):
...
app = FastAPI()
auth_required_router = APIRouter()
app.include_router(
auth_required_router, dependencies=[Depends(verify_access)],
)
@auth_required_router.get("/")
def read_root(settings: config.Settings = Depends(get_settings)):
...
请注意,您的身份验证依赖项返回的值是任意的,因此您可以在那里返回在您的用例中有意义的任何内容(例如,经过身份验证的用户帐户)。如果要在由auth\u required\u路由器注册的视图中检索此值,只需在视图参数中定义此依赖项即可。FastAPI将只解析(并执行)此依赖项一次
您甚至可以执行更复杂的操作,例如创建两个嵌套依赖项,一个简单地检查身份验证,另一个从数据库检索用户帐户:
async def authenticate(...):
... # Verifies the auth data without fetching the user
async def get_auth_user(auth = Depends(authenticate):
... # Gets the user from the database, based on the auth data
现在,您的auth\u required\u路由器
只能具有authenticate
依赖项,但每个视图也需要访问