我正在努力使用烧瓶 oidc 和 keycloak 保护烧瓶 API 后端。我的项目包括一个 React 前端和一个烧瓶应用程序,作为受 Keycloak 服务器 v13.0.1 保护的 REST API。因此,我为前端创建了一个公共客户端,为后端创建了一个仅承载客户端,但我不断收到带有“需要令牌但无效消息”的 401。Flask 没有写任何关于错误原因的日志。我无法弄清楚我做错了什么,所以我希望你能帮助我。
这是 flask-oidc 的 client_secrets.json
{
"web": {
"issuer": "http://127.0.0.1:8080/auth/realms/reamar",
"auth_uri": "http://127.0.0.1:8080/auth/realms/reamar/protocol/openid-connect/auth",
"client_id": "reamar-api",
"client_secret": "5d241a3c-d0a2-4811-b54c-d910a8e6aa7e",
"redirect_uris": ["http://127.0.0.1:5000/*"],
"userinfo_uri": "http://127.0.0.1:8080/auth/realms/reamar/protocol/openid-connect/userinfo",
"token_uri": "http://127.0.0.1:8080/auth/realms/reamar/protocol/openid-connect/token",
"token_introspection_uri": "http://127.0.0.1:8080/auth/realms/reamar/protocol/openid-connect/token/instrospect",
"bearer_only": "true"
}
}
这些是 flask-oidc 配置参数(它总是采用默认值)
OIDC_CLIENT_SECRETS = os.getenv("ODIC_CLIENT_SECRETS", "data/client_secrets.json")
OIDC_COOKIE_SECURE = os.getenv("OIDC_COOKIE_SECURE", False)
OIDC_ID_TOKEN_COOKIE_SECURE = os.getenv("OIDC_ID_TOKEN_COOKIE_NAME", False)
OIDC_SCOPES = os.getenv("OIDC_SCOPES", ["openid", "email", "profile"])
OIDC_USER_INFO_ENABLED = os.getenv("OIDC_USER_INFO_ENABLED", True)
OIDC_OPENID_REALM = os.getenv("OIDC_OPENID_REALM", "reamar")
OIDC_INTROSPECTION_AUTH_METHOD = os.getenv("OIDC_INTROSPECTION_AUTH_METHOD", "client_secret_post")
OIDC_RESOURCE_SERVER_ONLY = os.getenv("OIDC_RESOURCE_SERVER_ONLY", True)
OIDC_RESOURCE_CHECK_AUD = os.getenv("OIDC_RESOURCE_CHECK_AUD", False)
OIDC_REQUIRE_VERIFIED_EMAIL = os.getenv("OIDC_REQUIRE_VERIFIED_EMAIL", False)
OIDC_TOKEN_TYPE_HINT = "access_token"
这是令牌保护方法:
@TramiteEndpoint.route("/<string:numero>/", methods=["PUT"])
@content_type("application/json")
@accepts("application/json")
@OIDC.accept_token(require_token=True)
def actualizar(numero: str):
tramite = TTramite(unknown=INCLUDE, context={"tramite": numero}).load(
request.get_json()
)
if tramite.estado not in [
EEstadoTramite.INICIADO,
EEstadoTramite.PENDIENTE,
EEstadoTramite.FINALIZADO,
]:
raise Conflict(
"No se puede modificar un trámite en estado {}".format(tramite.estado)
)
tipo = tramite.tipo
if tipo == ETipoTramite.DJG:
tramite = TDeclaracionJuradaGeneral(context={"tramite": numero}).load(
request.get_json()
)
elif tipo == ETipoTramite.DJE:
tramite = TDeclaracionJuradaEmpadronamiento(context={"tramite": numero}).load(
request.get_json()
)
elif tipo == ETipoTramite.DJA:
tramite = TDeclaracionJuradaActividad(context={"tramite": numero}).load(
request.get_json()
)
elif tipo == ETipoTramite.DJEELL:
tramite = TDeclaracionJuradaEfluentesLiquidos(context={"tramite": numero}).load(
request.get_json()
)
elif tipo == ETipoTramite.DJRR:
tramite = TDeclaracionJuradaResiduos(context={"tramite": numero}).load(
request.get_json()
)
elif tipo == ETipoTramite.DJEEGG:
tramite = TDeclaracionJuradaEmisionesGaseosas(context={"tramite": numero}).load(
request.get_json()
)
tramite = TramiteRepository(current_app.entityManager).load(tramite)
TramiteRepository(current_app.entityManager).guardar(tramite)
return "", HTTPStatus.NO_CONTENT
最后这是我为客户端配置的密钥斗篷: