React + Flask + Flask OIDC + Keycloak + Bearer Only

557 views Asked by At

I'm struggling with securing a flask API backend with flask-oidc and keycloak. My project consist of a React front end and a flask application as REST API protected by a Keycloak server v13.0.1. So I created a public client for the front end and a bearer only client for the backen but I keep getting 401 with a "Token required but invalid message". Flask is not writing any log about the cause of the error. I can't figure out what I'm doing wrong so i hope you are able to help me out.

This is the client_secrets.json for flask-oidc

{
  "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"
  }
}

These are the flask-oidc config parameters (it's taking always the default values)

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"

This is the token protected method:

@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

And finally this is my keycloak configuration for the client:

Client Settings Client credentials

0

There are 0 answers