Skip to content

non-JWT refresh token causes keycloak-js parseError #149

@benzitohhh

Description

@benzitohhh

Describe the bug

Keycloak-js assumes that "refresh token" payload is JWT.

While the Keycloak Server does issue refresh tokens with JWT payload, many other OIDC servers do not, and the OIDC spec does not require this.

For example, our company uses keycloak-js with the Keycloak Server, but additionally with Ory Hydra OIDC Server. In the Hydra case, the refresh tokens look like this:

LaRIEB5jv-cnTmgEYEdAL8Uig2NoTCC2y_OJwWafMMY.-yn4F5AIdrDziEt4qp--0c-sfsTgnIQhQ6N0Mp8dZ54

Notice the payload is not JWT.

But keycloak.js tries to parse the payload as jwt:
https://github.com/keycloak/keycloak-js/blob/main/lib/keycloak.js#L1538

        if (refreshToken) {
            this.refreshToken = refreshToken;
            this.refreshTokenParsed = decodeToken(refreshToken);
        }

This throws a parse error, and causes login to fail :(

An easy solution would be to add an option flag here:

    if (refreshToken) {
        this.refreshToken = refreshToken;
        if (this.refreshTokenIsJWT === true) {
          this.refreshTokenParsed = decodeToken(refreshToken);
        }
    }

Version

26.2.0

Expected behavior

Keycloak should support cases where the "refresh token" payload is not JWT.

.... i.e. Ory Hdra OIDC server issues refresh tokens that look like this:

LaRIEB5jv-cnTmgEYEdAL8Uig2NoTCC2y_OJwWafMMY.-yn4F5AIdrDziEt4qp--0c-sfsTgnIQhQ6N0Mp8dZ54

There should be an option so that keycloak.js does not try to parse the payload as JWT

Actual behavior

Currently keycloak.js assumes "refresh token" payload is always JWT, and it tries to parse this.

For example, an Ory Hydra refresh token looks like this:

LaRIEB5jv-cnTmgEYEdAL8Uig2NoTCC2y_OJwWafMMY.-yn4F5AIdrDziEt4qp--0c-sfsTgnIQhQ6N0Mp8dZ54

But keycloak.js tries to parse the payload as jwt:

https://github.com/keycloak/keycloak-js/blob/main/lib/keycloak.js#L1538

        if (refreshToken) {
            this.refreshToken = refreshToken;
            this.refreshTokenParsed = decodeToken(refreshToken);
        }

This throws a parse error, and causes login to fail :(

How to Reproduce?

Pass a refresh token with non-JWT payload into Keycloak:

// Non-JWT payload
const REFRESH_TOKEN = "LaRIEB5jv-cnTmgEYEdAL8Uig2NoTCC2y_OJwWafMMY.-yn4F5AIdrDziEt4qp--0c-sfsTgnIQhQ6N0Mp8dZ54"

// JWT payload
const ACCESS_TOKEN  = "eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzpjZTMyMzE5Ny0zZjE1LTQ5OTctOWJiNS01ZWNhYzkxYmUzNzciLCJ0eXAiOiJKV1QifQ.eyJhdWQiOltdLCJjbGllbnRfaWQiOiI5ZTAxMTBiOC0xYzFmLTQzZmItYTU4YS1lNzM2ZWY1Mjg3NjYiLCJleHAiOjE3Mjc4ODc2MjMsImV4dCI6e30sImlhdCI6MTcyNzg4NDAyMiwiaXNzIjoiaHR0cHM6Ly9jZGMxYy1sb2dpbi5sZXhpc25leGlzLmNvbS8iLCJqdGkiOiJiZDY4NTg5Yi1mMjY0LTRiNjAtOWFjNi0xODc2OGZhZDUyNjYiLCJuYmYiOjE3Mjc4ODQwMjIsInNjcCI6WyJvcGVuaWQiLCJvZmZsaW5lIiwiZW1haWwiLCJ0ZXN0Um9sZSJdLCJzdWIiOiJ1cm46dXNlcjpDQTIwMDMzODQ1NSJ9.fnLO1eDpQ2llUUbFx70yRA_sYEIQMVZAKUgIvgjl5l_PBajqEX9kV6GGtzihrnu4VOE2b-e5C6AyBbPNwOMz-sdoY7hGUebJ7AJVkrCIPlFzbZ8_WQILL1F2ff2Sghw95XrqosTeaU-6TxOJJqXQEd1LpQRI9e86TBJ6m6LjC-GYGPP3nGhjrlizLrNSsB8ZOZNnSldQ2alkO-_YK66L5hyicY_kZ3FsENS4jdTS24FOwQALry_Gj8CLBftoQKaWTLPoAyrlnDqK53z_2EadZUueexIFiapo3F1_P-_frdFEWqNbDZ8gHF5wy0Y40CIKpgoQNaSp7osbGFIYfTVswG-OWXV82DpvC_pm9BHQfh7DYQpj2jTr78ypPy6LzViffbIWAdnuJ8QCEW6aP1vOghHVF4P9wuT8Hs-d2nB0DdDDA-kJdjjvKULnuHjlO00iJRcliZOSyw71p52rnmiLmCfEgxezr4kPnyhlNBk75fx3OJjamFmB0tM0EolIogn6EC66kvygNoSSMl_E2u0MP01Ya8iuKqPirGIkO5YHJ2SZ4V3TgM8Uf9cADtQo5X0JqrfLMwUJXBtQTArsMQrHQQthsi5puDUUcLjo5-jCcqUVuF_tUzeNBMRWuUxGBWUth4qhe_MI8Ei5k2h7CMSsAEjKq94PMfz-guRxolxLns8"

keycloak = new Keycloak({
 clientId: ...
 realm:    ....
 url:         ....
})

keycloak.init({
  token:             ACCESS_TOKEN,
  refreshToken: REFRESH_TOKEN,
  idToken:          ID_TOKEN,
})

This should trigger:

setToken(token, refreshToken)

which should then trigger:

this.refreshTokenParsed = decodeToken(refreshToken);

which will throw a ParseError

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions