oauth-2.0 - 如何验证在 FastAPI 中作为 HttpOnly cookie 发送的 JWT?

标签 oauth-2.0 jwt fetch fastapi cookie-httponly

问题

我正在开发一个 FastAPI 应用程序,该应用程序需要对用户访问的某些端点进行身份验证。我正在使用 FastAPI 中的 Oauth2 和 Jose 为我的身份验证过程创建 JWT。经过一些研究后,确保 token 在前端受到保护的最佳方法似乎是将它们存储在 HttpOnly Cookie 中。我正在努力了解如何通过 HttpOnly Cookie 正确传递 JWT,以便我的 FastAPI 服务器能够验证 header 中的 JWT。目前,当我尝试将 JWT token 作为 HttpOnly Cookie 传递时,我收到 401 Unauthorized Error

我尝试过的

当我将 token 作为模板字符串编码到 header 中时,我已经能够使用 JWT token 成功地对用户进行身份验证。但是,当我通过 header 将 JWT 作为 Cookie 传递到 FastAPI 服务器时,我的 FastAPI 服务器无法对用户进行身份验证并返回 401 未经授权的错误。我尝试查看网络选项卡,看看我的请求中向 FastApi 服务器发送了哪些 header ,以便更好地了解这两种情况之间的不同之处。

成功示例及代码

当我将 JWT 作为模板字符串传递并获得 200 响应时,这是在 header 中:

Authentication: Bearer token

  async function getPosts() {
    const url = "http://localhost:8000/posts";
    const fetchConfig = {
      headers: {
        Authorization: `Bearer ${tokenValue}`,
      },
    };
    const response = await fetch(url, fetchConfig);
    const posts = await response.json();
  }

不成功的示例代码

当我将 JWT 作为 HttpOnly Cookie 传递并获得 401 响应时,这位于 header 中:

Cookie: access_token="Bearer token"

我还尝试更改在服务器上设置 cookie 的方式,以便 header 如下所示:

Cookie: Authentication="Bearer token"

  async function getPosts() {
    const url = "http://localhost:8000/posts";
    const fetchConfig = {
      credentials: "include",
    };
    const response = await fetch(url, fetchConfig);
    const posts = await response.json();
    console.log(posts);
  }

FastAPI代码

以下是用于保护我的 API 端点的 Oauth2 token 验证的代码。这是基于 FastAPI 文档中的示例: FastApi Oauth2

oauth2_scheme = OAuth2PasswordBearer(tokenUrl='login')

SECRET_KEY = settings.SECRET_KEY
ALGORITHM = settings.ALGORITHM
ACCESS_TOKEN_EXPIRE_MINUTES = settings.ACCESS_TOKEN_EXPIRE_MINUTES


def verify_access_token(token: str, credentials_exception):
  try:
    payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
    id: str = payload.get("user_id")
    if id is None:
      raise credentials_exception
    token_data = schemas.TokenData(id=id)
  
  except JWTError:
    raise credentials_exception

  return token_data

def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(database.get_db)):
  credentials_exception = HTTPException(
    status_code=status.HTTP_401_UNAUTHORIZED,
    detail=f"Could not validate credentials",
    headers={"WWW-Authenticate": "Bearer"}
  )

  token = verify_access_token(token, credentials_exception)
  user = db.query(models.User).filter(models.User.id == token.id).first()

  return user

以下是 protected 端点的示例,该端点依赖于上面列出的 oauth2 文件中的 get_current_user 函数。

@router.get("/", response_model=List[schemas.PostOut])
def get_posts(db: Session = Depends(get_db), current_user: int = Depends(oauth2.get_current_user):
  return {"Message": "Protected Endpoint Reached"}

看来我遇到了这个问题,因为 Oauth2 中的 get_current_user 函数只能在以下格式时从 header 中获取 JWT:

Authentication: Bearer token

当 token 采用以下任一格式时,它似乎无法从 header 中验证 token :

Cookie: access_token="Bearer token"

Cookie: Authentication="Bearer token"

当我通过 HttpOnly Cookie 发送 header 时,我是否需要以某种方式改变发送 header 的方式,或者我是否需要更改有关 get_current_user 函数的某些内容,以使其能够正确读取 cookie header 。

非常感谢任何建议,感谢您花时间阅读本文!

最佳答案

要从 cookie 而不是 OAuth2PasswordBearer 默认的 Authorization header 获取 token ,tell FastAPI that you want the token to originate from a cookie instead .

def get_current_user(access_token: str = Cookie(...), db: Session = Depends(database.get_db)):

这假设 token 已命名为access_token(而不仅仅是 token )。根据需要调整名称。

关于oauth-2.0 - 如何验证在 FastAPI 中作为 HttpOnly cookie 发送的 JWT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74634957/

相关文章:

oauth-2.0 - Perl 中的 google API 服务帐户流程

javascript - 无法使用 JWT 读取 Express 上未定义的属性 'username'

c# - System.IdentityModel.Tokens 和 Microsoft.IdentityModel.Tokens 之间的冲突

javascript - 对 spring @ResourceMapping 方法进行 react ,未使用相同的请求参数调用

git - 运行 git svn fetch --all 时,--all 选项有什么作用?

java - 在同一上下文中使用 Spring Boot 2 OAuth 客户端和资源服务器

Spring Boot OAuth2 - 无法从 token 获取用户详细信息

meteor - "415 Error"查询 Spotify token 时

spring - Spring Security Filter Chain 如何工作

unit-testing - Nock拦截请求但返回空对象