Skip to content

A silenced error for JWT Stateless Authentication during token validation #832

Open
@InterStella0

Description

Context

I'm using Keycloak to implement SSO with Django, and I found this library. I used JWTStatelessUserAuthentication for my default authentication class as stated in the docs. However, i was having trouble with the validation process when the frontend passed in the JWT token to django on a protected endpoint. It keeps giving me 401 Unauthorized with the message "Token is invalid or expired". The message was quite vague as i couldn't debug the code as there is no logging output other than the Unauthorized response.

Issue

With Keycloak, you would get the JWK via https://xxx/realms/xxx/protocol/openid-connect/certs endpoint. What I found was that it was raising a Forbidden error from PyJWKClient when it does PyJWKClient.fetch_data(), I couldn't see this error due to the generic error raised by this try-except.

For more detail, Keycloak rejects (gives Forbidden) on GET requests that does not have a user-agent header, which PyJWKClient does not by default.

Current solution

To solve my issue i had to override Token and patch the token_backend

Code

from rest_framework_simplejwt.tokens import AccessToken
class KeycloakAccessToken(AccessToken):
    token_type = "Bearer"  # token_type is not stated within payload, but `typ` exist
    def get_token_backend(self) -> "TokenBackend":
        backend = super().get_token_backend()
        backend.jwks_client.headers = {"User-Agent": "Keycloak-python-urllib"}
        return backend

settings.py

SIMPLE_JWT = {
    "ALGORITHM": "RS256",
    "ISSUER": KEYCLOAK_ISSUER,
    "JWK_URL": JWKS_URL,
    "SIGNING_KEY": None,
    "VERIFYING_KEY": None,
    "USER_ID_CLAIM": "sub",
    "TOKEN_TYPE_CLAIM": "typ",
    "LEEWAY": 5,
    "AUTH_HEADER_TYPES": ("Bearer",),
    "AUTH_TOKEN_CLASSES": ("search.token.KeycloakAccessToken",),
}

Discussion

It would be helpful if there is a way to debug these, have verbose output with logging DEBUG level. It would also be good to be able to override PyJWKClient args for TokenBackend init.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions