Java Code Examples for org.keycloak.common.util.Time#currentTime()

The following examples show how to use org.keycloak.common.util.Time#currentTime() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DemoServletsAdapterTest.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Test
public void testOIDCParamsForwarding() {
    // test login to customer-portal which does a bearer request to customer-db
    securePortal.navigateTo();
    assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
    testRealmLoginPage.form().login("[email protected]", "password");
    waitForPageToLoad();
    assertCurrentUrlStartsWith(securePortal);
    assertLogged();

    int currentTime = Time.currentTime();
    try {
        setAdapterAndServerTimeOffset(10, securePortal.toString());

        // Test I need to reauthenticate with prompt=login
        String appUri = tokenMinTTLPage.getUriBuilder().queryParam(OIDCLoginProtocol.PROMPT_PARAM, OIDCLoginProtocol.PROMPT_VALUE_LOGIN).build().toString();
        URLUtils.navigateToUri(appUri);
        assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
        testRealmLoginPage.form().login("[email protected]", "password");
        AccessToken token = tokenMinTTLPage.getAccessToken();
        int authTime = token.getAuthTime();
        assertThat(authTime, is(greaterThanOrEqualTo(currentTime + 10)));
    } finally {
        setAdapterAndServerTimeOffset(0, securePortal.toString());
    }
}
 
Example 2
Source File: TokenManager.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public AccessTokenResponse grantToken() {
    Form form = new Form().param(GRANT_TYPE, accessTokenGrantType);
    if (PASSWORD.equals(accessTokenGrantType)) {
        form.param("username", config.getUsername())
            .param("password", config.getPassword());
    }

    if (config.isPublicClient()) {
        form.param(CLIENT_ID, config.getClientId());
    }

    int requestTime = Time.currentTime();
    synchronized (this) {
        currentToken = tokenService.grantToken(config.getRealm(), form.asMap());
        expirationTime = requestTime + currentToken.getExpiresIn();
    }
    return currentToken;
}
 
Example 3
Source File: OIDCIdentityProvider.java    From keycloak with Apache License 2.0 6 votes vote down vote up
private String getIDTokenForLogout(KeycloakSession session, UserSessionModel userSession) {
    String tokenExpirationString = userSession.getNote(FEDERATED_TOKEN_EXPIRATION);
    long exp = tokenExpirationString == null ? 0 : Long.parseLong(tokenExpirationString);
    int currentTime = Time.currentTime();
    if (exp > 0 && currentTime > exp) {
        String response = refreshTokenForLogout(session, userSession);
        AccessTokenResponse tokenResponse = null;
        try {
            tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return tokenResponse.getIdToken();
    } else {
        return userSession.getNote(FEDERATED_ID_TOKEN);

    }
}
 
Example 4
Source File: RealmTest.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Test
public void pushNotBeforeWithSamlApp() {
    setupTestAppAndUser();
    setupTestSamlApp();

    int time = Time.currentTime() - 60;

    RealmRepresentation rep = realm.toRepresentation();
    rep.setNotBefore(time);
    realm.update(rep);
    assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);

    GlobalRequestResult globalRequestResult = realm.pushRevocation();
    assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult, ResourceType.REALM);

    assertThat(globalRequestResult.getSuccessRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin"));
    assertThat(globalRequestResult.getFailedRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/saml-app/saml"));

    PushNotBeforeAction adminPushNotBefore = testingClient.testApp().getAdminPushNotBefore();
    assertEquals(time, adminPushNotBefore.getNotBefore());
}
 
Example 5
Source File: InfinispanUserSessionProvider.java    From keycloak with Apache License 2.0 6 votes vote down vote up
void updateSessionEntity(UserSessionEntity entity, RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId) {
    entity.setRealmId(realm.getId());
    entity.setUser(user.getId());
    entity.setLoginUsername(loginUsername);
    entity.setIpAddress(ipAddress);
    entity.setAuthMethod(authMethod);
    entity.setRememberMe(rememberMe);
    entity.setBrokerSessionId(brokerSessionId);
    entity.setBrokerUserId(brokerUserId);

    int currentTime = Time.currentTime();

    entity.setStarted(currentTime);
    entity.setLastSessionRefresh(currentTime);


}
 
Example 6
Source File: RealmTest.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Test
public void pushNotBefore() {
    setupTestAppAndUser();

    int time = Time.currentTime() - 60;

    RealmRepresentation rep = realm.toRepresentation();
    rep.setNotBefore(time);
    realm.update(rep);
    assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);

    GlobalRequestResult globalRequestResult = realm.pushRevocation();
    assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult, ResourceType.REALM);

    assertThat(globalRequestResult.getSuccessRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin"));
    assertNull(globalRequestResult.getFailedRequests());

    PushNotBeforeAction adminPushNotBefore = testingClient.testApp().getAdminPushNotBefore();
    assertEquals(time, adminPushNotBefore.getNotBefore());
}
 
Example 7
Source File: CustomLockService.java    From keycloak with Apache License 2.0 6 votes vote down vote up
private void waitForLock(LockDatabaseChangeLogStatement lockStmt) {
    boolean locked = false;
    long startTime = Time.toMillis(Time.currentTime());
    long timeToGiveUp = startTime + (getChangeLogLockWaitTime());
    boolean nextAttempt = true;

    while (nextAttempt) {
        locked = acquireLock(lockStmt);
        if (!locked) {
            int remainingTime = ((int)(timeToGiveUp / 1000)) - Time.currentTime();
            if (remainingTime > 0) {
                log.debugf("Will try to acquire log another time. Remaining time: %d seconds", remainingTime);
            } else {
                nextAttempt = false;
            }
        } else {
            nextAttempt = false;
        }
    }

    if (!locked) {
        int timeout = ((int)(getChangeLogLockWaitTime() / 1000));
        throw new IllegalStateException("Could not acquire change log lock within specified timeout " + timeout + " seconds.  Currently locked by other transaction");
    }
}
 
Example 8
Source File: ClientSessionCode.java    From keycloak with Apache License 2.0 6 votes vote down vote up
public boolean isActionActive(ActionType actionType) {
    CodeGenerateUtil.ClientSessionParser<CLIENT_SESSION> clientSessionParser = (CodeGenerateUtil.ClientSessionParser<CLIENT_SESSION>) CodeGenerateUtil.getParser(commonLoginSession.getClass());
    int timestamp = clientSessionParser.getTimestamp(commonLoginSession);

    int lifespan;
    switch (actionType) {
        case CLIENT:
            lifespan = realm.getAccessCodeLifespan();
            break;
        case LOGIN:
            lifespan = realm.getAccessCodeLifespanLogin() > 0 ? realm.getAccessCodeLifespanLogin() : realm.getAccessCodeLifespanUserAction();
            break;
        case USER:
            lifespan = realm.getAccessCodeLifespanUserAction();
            break;
        default:
            throw new IllegalArgumentException();
    }

    return lifespan > Time.currentTime() - timestamp;
}
 
Example 9
Source File: NodesRegistrationManagement.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private boolean needRefreshRegistration(String registrationUri, KeycloakDeployment resolvedDeployment) {
    NodeRegistrationContext currentRegistration = nodeRegistrations.get(registrationUri);
    /// We don't yet have any registration for this node
    if (currentRegistration == null) {
        return true;
    }

    return currentRegistration.lastRegistrationTime + resolvedDeployment.getRegisterNodePeriod() < Time.currentTime();
}
 
Example 10
Source File: AbstractLastSessionRefreshStore.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private synchronized Map<String, SessionData> prepareSendingMessage() {
    // Safer to retrieve currentTime to avoid race conditions during testsuite
    int currentTime = Time.currentTime();
    if (lastSessionRefreshes.size() >= maxCount || lastRun + maxIntervalBetweenMessagesSeconds <= currentTime) {
        // Create new map instance, so that new writers will use that one
        Map<String, SessionData> copiedRefreshesToSend = lastSessionRefreshes;
        lastSessionRefreshes = new ConcurrentHashMap<>();
        lastRun = currentTime;

        return copiedRefreshesToSend;
    } else {
        return null;
    }
}
 
Example 11
Source File: InfinispanAuthenticationSessionProvider.java    From keycloak with Apache License 2.0 5 votes vote down vote up
@Override
public void removeExpired(RealmModel realm) {
    log.debugf("Removing expired sessions");

    int expired = Time.currentTime() - RealmInfoUtil.getDettachedClientSessionLifespan(realm);

    final AdvancedCache<String, RootAuthenticationSessionEntity> localCache = CacheDecorators.localCache(cache);
    int localCacheSizePre = localCache.size();
    // Each cluster node cleanups just local sessions, which are those owned by himself (+ few more taking l1 cache into account)
    localCache.entrySet()
            .removeIf(RootAuthenticationSessionPredicate.create(realm.getId()).expired(expired));

    log.debugf("Removed %d expired authentication sessions for realm '%s'", localCache.size() - localCacheSizePre, realm.getName());
}
 
Example 12
Source File: AttackDetectionResource.java    From keycloak with Apache License 2.0 5 votes vote down vote up
/**
 * Get status of a username in brute force detection
 *
 * @param userId
 * @return
 */
@GET
@Path("brute-force/users/{userId}")
@NoCache
@Produces(MediaType.APPLICATION_JSON)
public Map<String, Object> bruteForceUserStatus(@PathParam("userId") String userId) {
    UserModel user = session.users().getUserById(userId, realm);
    if (user == null) {
        auth.users().requireView();
    } else {
        auth.users().requireView(user);
    }

    Map<String, Object> data = new HashMap<>();
    data.put("disabled", false);
    data.put("numFailures", 0);
    data.put("lastFailure", 0);
    data.put("lastIPFailure", "n/a");
    if (!realm.isBruteForceProtected()) return data;


    UserLoginFailureModel model = session.sessions().getUserLoginFailure(realm, userId);
    if (model == null) return data;

    boolean disabled;
    if (user == null) {
        disabled = Time.currentTime() < model.getFailedLoginNotBefore();
    } else {
        disabled = session.getProvider(BruteForceProtector.class).isTemporarilyDisabled(session, realm, user);
    }
    if (disabled) {
        data.put("disabled", true);
    }

    data.put("numFailures", model.getNumFailures());
    data.put("lastFailure", model.getLastFailure());
    data.put("lastIPFailure", model.getLastIPFailure());
    return data;
}
 
Example 13
Source File: TokenManager.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private int getOfflineExpiration() {
    int sessionExpires = userSession.getStarted() + realm.getOfflineSessionMaxLifespan();

    int clientOfflineSessionMaxLifespan;
    String clientOfflineSessionMaxLifespanPerClient = client
        .getAttribute(OIDCConfigAttributes.CLIENT_OFFLINE_SESSION_MAX_LIFESPAN);
    if (clientOfflineSessionMaxLifespanPerClient != null
        && !clientOfflineSessionMaxLifespanPerClient.trim().isEmpty()) {
        clientOfflineSessionMaxLifespan = Integer.parseInt(clientOfflineSessionMaxLifespanPerClient);
    } else {
        clientOfflineSessionMaxLifespan = realm.getClientOfflineSessionMaxLifespan();
    }

    if (clientOfflineSessionMaxLifespan > 0) {
        int clientOfflineSessionMaxExpiration = userSession.getStarted() + clientOfflineSessionMaxLifespan;
        sessionExpires = sessionExpires < clientOfflineSessionMaxExpiration ? sessionExpires
            : clientOfflineSessionMaxExpiration;
    }

    int expiration = Time.currentTime() + realm.getOfflineSessionIdleTimeout();

    int clientOfflineSessionIdleTimeout;
    String clientOfflineSessionIdleTimeoutPerClient = client
        .getAttribute(OIDCConfigAttributes.CLIENT_OFFLINE_SESSION_IDLE_TIMEOUT);
    if (clientOfflineSessionIdleTimeoutPerClient != null
        && !clientOfflineSessionIdleTimeoutPerClient.trim().isEmpty()) {
        clientOfflineSessionIdleTimeout = Integer.parseInt(clientOfflineSessionIdleTimeoutPerClient);
    } else {
        clientOfflineSessionIdleTimeout = realm.getClientOfflineSessionIdleTimeout();
    }

    if (clientOfflineSessionIdleTimeout > 0) {
        int clientOfflineSessionIdleExpiration = Time.currentTime() + clientOfflineSessionIdleTimeout;
        expiration = expiration < clientOfflineSessionIdleExpiration ? expiration : clientOfflineSessionIdleExpiration;
    }

    return expiration <= sessionExpires ? expiration : sessionExpires;
}
 
Example 14
Source File: JpaRealmProvider.java    From keycloak with Apache License 2.0 5 votes vote down vote up
@Override
public void removeExpiredClientInitialAccess() {
    int currentTime = Time.currentTime();

    em.createNamedQuery("removeExpiredClientInitialAccess")
            .setParameter("currentTime", currentTime)
            .executeUpdate();
}
 
Example 15
Source File: ClientManager.java    From keycloak with Apache License 2.0 5 votes vote down vote up
public Set<String> validateRegisteredNodes(ClientModel client) {
    Map<String, Integer> registeredNodes = client.getRegisteredNodes();
    if (registeredNodes == null || registeredNodes.isEmpty()) {
        return Collections.emptySet();
    }

    int currentTime = Time.currentTime();

    Set<String> validatedNodes = new TreeSet<String>();
    if (client.getNodeReRegistrationTimeout() > 0) {
        List<String> toRemove = new LinkedList<String>();
        for (Map.Entry<String, Integer> entry : registeredNodes.entrySet()) {
            Integer lastReRegistration = entry.getValue();
            if (lastReRegistration + client.getNodeReRegistrationTimeout() < currentTime) {
                toRemove.add(entry.getKey());
            } else {
                validatedNodes.add(entry.getKey());
            }
        }

        // Remove time-outed nodes
        for (String node : toRemove) {
            client.unregisterNode(node);
        }
    } else {
        // Periodic node reRegistration is disabled, so allow all nodes
        validatedNodes.addAll(registeredNodes.keySet());
    }

    return validatedNodes;
}
 
Example 16
Source File: UserInfoTest.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Test
public void testNotBeforeTokens() {
    Client client = ClientBuilder.newClient();

    try {
        AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);

        int time = Time.currentTime() + 60;

        RealmResource realm = adminClient.realm("test");
        RealmRepresentation rep = realm.toRepresentation();
        rep.setNotBefore(time);
        realm.update(rep);

        Response response = UserInfoClientUtil.executeUserInfoRequest_getMethod(client, accessTokenResponse.getToken());

        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());

        response.close();

        events.expect(EventType.USER_INFO_REQUEST_ERROR)
                .error(Errors.INVALID_TOKEN)
                .user(Matchers.nullValue(String.class))
                .session(Matchers.nullValue(String.class))
                .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
                .client((String) null)
                .assertEvent();

        events.clear();
        rep.setNotBefore(0);
        realm.update(rep);

        // do the same with client's notBefore
        ClientResource clientResource = realm.clients().get(realm.clients().findByClientId("test-app").get(0).getId());
        ClientRepresentation clientRep = clientResource.toRepresentation();
        clientRep.setNotBefore(time);
        clientResource.update(clientRep);

        response = UserInfoClientUtil.executeUserInfoRequest_getMethod(client, accessTokenResponse.getToken());

        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());

        response.close();

        events.expect(EventType.USER_INFO_REQUEST_ERROR)
                .error(Errors.INVALID_TOKEN)
                .user(Matchers.nullValue(String.class))
                .session(Matchers.nullValue(String.class))
                .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
                .client((String) null)
                .assertEvent();

        clientRep.setNotBefore(0);
        clientResource.update(clientRep);
    } finally {
        client.close();
    }
}
 
Example 17
Source File: AuthenticationManager.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
                                                   ClientSessionContext clientSessionCtx,
                                                   HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection,
                                                   EventBuilder event, AuthenticationSessionModel authSession, LoginProtocol protocol) {
    Cookie sessionCookie = getCookie(request.getHttpHeaders().getCookies(), AuthenticationManager.KEYCLOAK_SESSION_COOKIE);
    if (sessionCookie != null) {

        String[] split = sessionCookie.getValue().split("/");
        if (split.length >= 3) {
            String oldSessionId = split[2];
            if (!oldSessionId.equals(userSession.getId())) {
                UserSessionModel oldSession = session.sessions().getUserSession(realm, oldSessionId);
                if (oldSession != null) {
                    logger.debugv("Removing old user session: session: {0}", oldSessionId);
                    session.sessions().removeUserSession(realm, oldSession);
                }
            }
        }
    }

    // Updates users locale if required
    session.getContext().resolveLocale(userSession.getUser());

    // refresh the cookies!
    createLoginCookie(session, realm, userSession.getUser(), userSession, uriInfo, clientConnection);
    if (userSession.getState() != UserSessionModel.State.LOGGED_IN) userSession.setState(UserSessionModel.State.LOGGED_IN);
    if (userSession.isRememberMe()) {
        createRememberMeCookie(realm, userSession.getLoginUsername(), uriInfo, clientConnection);
    } else {
        expireRememberMeCookie(realm, uriInfo, clientConnection);
    }

    AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();

    // Update userSession note with authTime. But just if flag SSO_AUTH is not set
    boolean isSSOAuthentication = "true".equals(session.getAttribute(SSO_AUTH));
    if (isSSOAuthentication) {
        clientSession.setNote(SSO_AUTH, "true");
    } else {
        int authTime = Time.currentTime();
        userSession.setNote(AUTH_TIME, String.valueOf(authTime));
        clientSession.removeNote(SSO_AUTH);
    }

    // The user has successfully logged in and we can clear his/her previous login failure attempts.
    logSuccess(session, authSession);

    return protocol.authenticated(authSession, userSession, clientSessionCtx);

}
 
Example 18
Source File: InitialAccessTokenResourceTest.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Test
@AuthServerContainerExclude(AuthServer.REMOTE) // Time difference is possible on remote server
public void testInitialAccessTokens() {
    ClientInitialAccessCreatePresentation rep = new ClientInitialAccessCreatePresentation();
    rep.setCount(2);
    rep.setExpiration(100);

    int time = Time.currentTime();

    ClientInitialAccessPresentation response = resource.create(rep);
    assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientInitialAccessPath(response.getId()), rep, ResourceType.CLIENT_INITIAL_ACCESS_MODEL);

    assertNotNull(response.getId());
    assertEquals(new Integer(2), response.getCount());
    assertEquals(new Integer(2), response.getRemainingCount());
    assertEquals(new Integer(100), response.getExpiration());
    assertThat(response.getTimestamp(), allOf(greaterThanOrEqualTo(time), lessThanOrEqualTo(Time.currentTime())));
    assertNotNull(response.getToken());

    rep.setCount(3);
    response = resource.create(rep);
    assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientInitialAccessPath(response.getId()), rep, ResourceType.CLIENT_INITIAL_ACCESS_MODEL);

    rep.setCount(4);
    response = resource.create(rep);
    String lastId = response.getId();
    assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientInitialAccessPath(lastId), rep, ResourceType.CLIENT_INITIAL_ACCESS_MODEL);

    List<ClientInitialAccessPresentation> list = resource.list();
    assertEquals(3, list.size());

    assertEquals(9, list.get(0).getCount() + list.get(1).getCount() + list.get(2).getCount());
    assertNull(list.get(0).getToken());

    // Delete last and assert it was deleted
    resource.delete(lastId);
    assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.clientInitialAccessPath(lastId), ResourceType.CLIENT_INITIAL_ACCESS_MODEL);

    list = resource.list();
    assertEquals(2, list.size());
    assertEquals(5, list.get(0).getCount() + list.get(1).getCount());
}
 
Example 19
Source File: KeycloakTokenManager.java    From nexus3-keycloak-plugin with Apache License 2.0 4 votes vote down vote up
private synchronized boolean tokenExpired() {
    return (Time.currentTime() + this.minTokenValidity) >= this.expirationTime;
}
 
Example 20
Source File: OIDCIdentityProvider.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
protected Response exchangeSessionToken(UriInfo uriInfo, EventBuilder event, ClientModel authorizedClient, UserSessionModel tokenUserSession, UserModel tokenSubject) {
    String refreshToken = tokenUserSession.getNote(FEDERATED_REFRESH_TOKEN);
    String accessToken = tokenUserSession.getNote(FEDERATED_ACCESS_TOKEN);
    String idToken = tokenUserSession.getNote(FEDERATED_ID_TOKEN);

    if (accessToken == null) {
        event.detail(Details.REASON, "requested_issuer is not linked");
        event.error(Errors.INVALID_TOKEN);
        return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
    }
    try (VaultStringSecret vaultStringSecret = session.vault().getStringSecret(getConfig().getClientSecret())) {
        long expiration = Long.parseLong(tokenUserSession.getNote(FEDERATED_TOKEN_EXPIRATION));
        if (expiration == 0 || expiration > Time.currentTime()) {
            AccessTokenResponse tokenResponse = new AccessTokenResponse();
            tokenResponse.setExpiresIn(expiration);
            tokenResponse.setToken(accessToken);
            tokenResponse.setIdToken(null);
            tokenResponse.setRefreshToken(null);
            tokenResponse.setRefreshExpiresIn(0);
            tokenResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
            tokenResponse.getOtherClaims().put(ACCOUNT_LINK_URL, getLinkingUrl(uriInfo, authorizedClient, tokenUserSession));
            event.success();
            return Response.ok(tokenResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
        }
        String response = getRefreshTokenRequest(session, refreshToken, getConfig().getClientId(), vaultStringSecret.get().orElse(getConfig().getClientSecret())).asString();
        if (response.contains("error")) {
            logger.debugv("Error refreshing token, refresh token expiration?: {0}", response);
            event.detail(Details.REASON, "requested_issuer token expired");
            event.error(Errors.INVALID_TOKEN);
            return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
        }
        AccessTokenResponse newResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
        long accessTokenExpiration = newResponse.getExpiresIn() > 0 ? Time.currentTime() + newResponse.getExpiresIn() : 0;
        tokenUserSession.setNote(FEDERATED_TOKEN_EXPIRATION, Long.toString(accessTokenExpiration));
        tokenUserSession.setNote(FEDERATED_REFRESH_TOKEN, newResponse.getRefreshToken());
        tokenUserSession.setNote(FEDERATED_ACCESS_TOKEN, newResponse.getToken());
        tokenUserSession.setNote(FEDERATED_ID_TOKEN, newResponse.getIdToken());
        newResponse.setIdToken(null);
        newResponse.setRefreshToken(null);
        newResponse.setRefreshExpiresIn(0);
        newResponse.getOtherClaims().clear();
        newResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
        newResponse.getOtherClaims().put(ACCOUNT_LINK_URL, getLinkingUrl(uriInfo, authorizedClient, tokenUserSession));
        event.success();
        return Response.ok(newResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}