使用 FastAPI 和 Swagger 刷新令牌

hir*_*lau 13 python jwt swagger swagger-ui fastapi

我正在尝试使用 FastAPI 为我们的组织创建 API。它有一个用于所有身份验证的 KeyCloak 服务器,以及被认为是最佳实践的 OpenID Connect 和 JWT。

在最简单的情况下,其他人负责获取有效的 JWT 令牌,以便 FastAPI 可以简单地解码和读取用户和权限。

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

async def get_current_user(token: str = Depends(oauth2_scheme)):

    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )

    try:
        jwt_token = jwt.decode(token, key=env.keycloak_server_public_key, audience='myorg')
        return jwt_token['preferred_username']
    except jwt.exceptions.ExpiredSignatureError:
        raise credentials_exception
Run Code Online (Sandbox Code Playgroud)

生活是简单的!

但是,我确实想尝试让用户使用 Swagger 页面探索 API。我创建了这个函数,让用户使用 UI 登录:

@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    login_request = requests.post(
        "https://mygreatorg.com/auth/realms/master/protocol/openid-connect/token",
        data={
            "grant_type": "password",
            "username": form_data.username,
            "password": form_data.password,
            "client_id": "fastapi-application",
        },
    )
    raw_response = json.loads(login_request.content.decode('utf-8'))
    raw_response['acquire_time'] = time.time()

    TOKEN_CACHE[form_data.username] = raw_response

    return {"access_token": raw_response['access_token'], "token_type": "bearer"}
Run Code Online (Sandbox Code Playgroud)

这工作正常。Swagger 中的 auth 标头现在是令牌,它会验证大约一分钟。令牌的过期时间设置为非常短的时间。然后期望使用raw_response有效负载中提供的 refresh_token 刷新它们。

给定refresh_token,我可以很容易地发出另一个请求以获取新的有效访问令牌。但是我无法让 Swagger 在 UI 中更改请求的令牌。我找到的唯一方法是退出并重新登录,但是如果他们只允许一分钟而不被踢出,用户会非常生气。

一种解决方法是简单地缓存令牌并忽略到期时间并让用户登录一段时间,但这违背了整个安全设置的目的,感觉是个坏主意。

关于如何让 FastAPI 的 UI 在需要刷新时更新不记名令牌而不让用户再次登录的任何想法?

Lif*_*lex 5


这远不是答案,我可能会稍后删除它。它只是一个占位符,用于概述我对此问题的研究


使用案例: Swagger UI 需要使用更新的 JWT 令牌自动刷新,而不关闭 UI。

系统/应用:

  • 钥匙斗篷
  • 快速API
  • 昂首阔步
  • OpenID Connect 和 JWT

当我研究这个问题时,我注意到这个问题中的问题是在 FastApi 和 Swagger 的问题中提出的。

昂首阔步


在查看 Swagger 的代码库时,我注意到一个名为persistAuthorization的授权参数。根据文档,此参数将维护授权数据,并且该数据不会在浏览器关闭/刷新时丢失。

在 Swagger 代码库中我看到了这个项目:

  # source: /src/plugins/topbar/topbar.jsx
  #
  flushAuthData() {
    const { persistAuthorization } = this.props.getConfigs()
    if (persistAuthorization)
    {
      return
    }
    this.props.authActions.restoreAuthorization({
      authorized: {}
    })
  }
Run Code Online (Sandbox Code Playgroud)

上面的代码调用/src/core/plugins/auth/actions.js

在 Swagger 拉取请求中,有一个名为configs.preserveAuthorization的待处理功能。此功能的范围:

如果我们将 configs.preserveAuthorization 设置为 true,则刷新或关闭/重新打开页面将保留授权。

根据评论,尚不清楚保留授权持久授权功能有何不同。

快速API


当我查看 FastApi 代码库时,我注意到一个名为refreshUrl的OAuthFlowsMo​​del。我翻阅了FastApi文档,没有看到提到这一点。

# source: /fastapi/security/oauth2.py
#
class OAuth2AuthorizationCodeBearer(OAuth2):
    def __init__(
        self,
        authorizationUrl: str,
        tokenUrl: str,
        refreshUrl: Optional[str] = None,
        scheme_name: Optional[str] = None,
        scopes: Optional[Dict[str, str]] = None,
        auto_error: bool = True,
    ):
        if not scopes:
            scopes = {}
        flows = OAuthFlowsModel(
            authorizationCode={
                "authorizationUrl": authorizationUrl,
                "tokenUrl": tokenUrl,
                "refreshUrl": refreshUrl,
                "scopes": scopes,
            }
        )
        super().__init__(flows=flows, scheme_name=scheme_name, auto_error=auto_error)

    async def __call__(self, request: Request) -> Optional[str]:
        authorization: str = request.headers.get("Authorization")
        scheme, param = get_authorization_scheme_param(authorization)
        if not authorization or scheme.lower() != "bearer":
            if self.auto_error:
                raise HTTPException(
                    status_code=HTTP_401_UNAUTHORIZED,
                    detail="Not authenticated",
                    headers={"WWW-Authenticate": "Bearer"},
                )
            else:
                return None  # pragma: nocover
        return param
Run Code Online (Sandbox Code Playgroud)

浏览 FastApi 的问题时,我注意到其中一个问题要求添加OAuth2RerefreshRequestForm 。此问题的范围是令牌刷新。

我还注意到Keycloak 和 Fastapi 的另一个刷新令牌问题


对于无法提供可靠的答案,我深表歉意。

  • 请留下这个答案,不要删除...有帮助 (4认同)