Skip to content

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

Closed
@InterStella0

Description

@InterStella0

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

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions