问题
我正在开发一个 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/