8000 After migrating to newer Keycloak, token refreshes using inherited offline sessions return access tokens with invalid exp value · Issue #39021 · keycloak/keycloak · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

After migrating to newer Keycloak, token refreshes using inherited offline sessions return access tokens with invalid exp value #39021

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks done
mposolda opened this issue Apr 16, 2025 · 2 comments · Fixed by #39449
Assignees
Labels
area/oidc Indicates an issue on OIDC area kind/bug Categorizes a PR related to a bug priority/important Must be worked on very soon release/26.0.12 release/26.2.4 release/26.3.0 team/core-clients team/rh-iam

Comments

@mposolda
Copy link
Contributor
mposolda commented Apr 16, 2025

Before reporting an issue

  • I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.

Area

oidc

Describe the bug

This is for migration from RH-SSO 7.6 to Keycloak 24.0.

After they migrated their production environment to Keycloak 24.0.z, they attempted to refresh a token for an offline session migrated from RH-SSO, and the following was returned as the token response.

 {
  "access_token": "...",
  "expires_in": -1586880441,
  "refresh_expires_in": -1586880441,
  "refresh_token": "...",
  "token_type": "Bearer",
  "not-before-policy": 0,
  "session_state": "...",
  "scope": "... offline_access"
}

As you can see, the expires_in value is negative, which is invalid.
The value is derived from the exp claim of the access token, and the issued access token has an exp value of 157680000 (1974-12-31 00:00:00 UTC), which is also invalid.

{
  "exp": 157680000,
  "iat": 1744560441,
  "auth_time": 1709734954,
  "typ": "Bearer",
  ...

The exp value of the access token is, roughly speaking, calculated as (session start time) + offlineSessionMaxLifespan.
In this realm, offlineSessionMaxLifespan is set to 157680000 seconds (5 years), so it appears the result is from 0 + offlineSessionMaxLifespan.
In other words, for some reason, the session start time is being treated as 0.

The following is the code that likely considers the session start time to be 0:

default int getStarted() {
String started = getNote(STARTED_AT_NOTE);
// Fallback to 0 if "started" note is not available. This can happen for the offline sessions migrated from old version where "startedAt" note was not yet available
return started == null ? 0 : Integer.parseInt(started);
}

For recently created sessions, it seems that a note called startedAt is added to the offline session. However, in the customer's case, the session was created with an older version, so it appears that the startedAt note is not included [1].

Therefore, clientSession.getStarted() in the following code becomes 0, leading SessionExpirationUtils.calculateClientSessionMaxLifespanTimestamp() to return 0 + offlineSessionMaxLifespan, which caused the access token's exp to be 157680000.

long sessionExpires = SessionExpirationUtils.calculateClientSessionMaxLifespanTimestamp(
userSession.isOffline() || offlineTokenRequested, userSession.isRememberMe(),
TimeUnit.SECONDS.toMillis(clientSession.getStarted()), TimeUnit.SECONDS.toMillis(userSession.getStarted()),
realm, client);

Version

24.0.z

Regression

  • The issue is a regression

Anything else?

Consideration

Is it possible that if clientSession.getStarted() is 0, then we use the iat of the offlineToken, which was sent to the endpoint? We should make sure to set startedAt, so that it is correctly set in the DB for the next time.

Alternative is to update all client sessions at startup and set started_at in case that it is not set. But not sure if still possible and it can take long time as bulk updates could be long and people can have millions of sessions in the DB...

Testing note

There is AbstractMigrationTest.testOfflineTokenLogin() for testing migration of offline-token from the older version. Currently it is tested from Keycloak 19 or earlier, which I am not 100% sure if can be used to simulate the issue (as the issue is for migration from RH-SSO 7.6, which is Keycloak 18), but maybe yes. Hopefully we can maybe add calling the "introspection endpoint" to that testOfflineTokenLogin() to doublecheck if access-token has correct exp times (as introspection for such access-token would probably fail).

@mposolda mposolda added kind/bug Categorizes a PR related to a bug status/triage labels Apr 16, 2025
@keycloak-github-bot keycloak-github-bot bot added area/oidc Indicates an issue on OIDC area team/core-clients labels Apr 16, 2025
@keycloak-github-bot keycloak-github-bot bot added the priority/important Must be worked on very soon label Apr 16, 2025
@keycloak-github-bot keycloak-github-bot bot added the priority/important Must be worked on very soon label Apr 16, 2025
@mposolda mposolda added status/triage kind/bug Categorizes a PR related to a bug and removed action/priority-important status/triage labels Apr 16, 2025
@mposolda
Copy link
Contributor Author

Update from @ynojima: Testing with Keycloak 26.0 returns the following error instead of a token response with an invalid exp value:

{"error":"invalid_grant","error_description":"Client session not active"} 

It still can't handle valid offline sessions created by RH-SSO 7.4, but I'm leaving this note here to avoid confusion when reproducing the issue.

@rmartinc rmartinc self-assigned this May 5, 2025
rmartinc added a commit to rmartinc/keycloak that referenced this issue May 5, 2025
@rmartinc
Copy link
Contributor
rmartinc commented May 5, 2025

The initial problem was introduced very long ago in keycloak 14 (this commit) so I think that the issue cannot be tested in the migration. I suppose the user was using a previous version before using RH-SSO 7.6 and the offline sessions were moved from version to version several times. Nevertheless I was able to create an ad-hoc test removing the notes in the server.

rmartinc added a commit to rmartinc/keycloak that referenced this issue May 6, 2025
Closes keycloak#39021

Signed-off-by: rmartinc <rmartinc@redhat.com>
(cherry picked from commit 11b032f)
InJoDave pushed a commit to InJoDave/keycloak that referenced this issue May 6, 2025
rmartinc added a commit to rmartinc/keycloak that referenced this issue May 6, 2025
Closes keycloak#39021

Signed-off-by: rmartinc <rmartinc@redhat.com>
(cherry picked from commit 11b032f)
rmartinc added a commit to rmartinc/keycloak that referenced this issue May 6, 2025
Closes keycloak#39021

Signed-off-by: rmartinc <rmartinc@redhat.com>
(cherry picked from commit 11b032f)
mposolda pushed a commit that referenced this issue May 7, 2025
Closes #39021

Signed-off-by: rmartinc <rmartinc@redhat.com>
(cherry picked from commit 11b032f)
mposolda pushed a commit that referenced this issue May 7, 2025
Closes #39021

Signed-off-by: rmartinc <rmartinc@redhat.com>
(cherry picked from commit 11b032f)
shawkins pushed a commit to shawkins/keycloak that referenced this issue May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/oidc Indicates an issue on OIDC area kind/bug Categorizes a PR related to a bug priority/important Must be worked on very soon release/26.0.12 release/26.2.4 release/26.3.0 team/core-clients team/rh-iam
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants
0