python-keycloak包与FastApi的兼容问题

0 投票
1 回答
41 浏览
提问于 2025-04-14 17:17

我有一个小应用程序,想用Keycloak来进行身份验证。如果我使用/public这个接口来获取测试用户的令牌,然后用这个令牌在Postman里发送请求到/protected资源,这样是可以正常工作的。

我的问题是,如果我通过Postman用以下方式从Keycloak获取令牌,我就无法用这个access_token去调用/protected。我总是收到“无法验证凭证”的错误,当我通过get_current_user方法检查这个令牌时。

http://localhost:8180/auth/realms/FastApi/protocol/openid-connect/token
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2AuthorizationCodeBearer
from typing import List
from keycloak import KeycloakOpenID

app = FastAPI()

# Keycloak settings
keycloak_openid = KeycloakOpenID(
    server_url="http://localhost:8180/auth/",
    realm_name="FastApi",
    client_id="fast_api",
    client_secret_key="secret",
)

# OAuth2 scheme using Keycloak
oauth2_scheme = OAuth2AuthorizationCodeBearer(
    authorizationUrl="http://localhost:8180/auth/realms/FastApi/protocol/openid-connect/auth",
    tokenUrl="http://localhost:8180/auth/realms/FastApi/protocol/openid-connect/token")


# Dependency to validate token and get user roles
async def get_current_user(token: str = Depends(oauth2_scheme)):
    try:
        d = keycloak_openid.userinfo(token)
        userinfo = keycloak_openid.userinfo(token)
        user_roles = userinfo.get("roles", [])
        if 'admin' not in user_roles:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="User not authorized to access this resource",
            )
        return user_roles
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not validate credentials",
        )


@app.get("/public", tags=["public"])
async def public_endpoint():
    token = keycloak_openid.token("test", "test")
    return {"token": token}


# Protected endpoint
@app.get("/protected", tags=["protected"])
async def protected_endpoint(current_user_roles: List[str] = Depends(get_current_user)):
    return {"message": "This is a protected endpoint", "user_roles": current_user_roles}

1 个回答

0

我找到了问题所在。原来我在用Postman请求获取令牌时,漏掉了“scope”这个属性:

http://localhost:8180/auth/realms/FastApi/protocol/openid-connect/token

在这里输入图片描述

撰写回答