Adding a test case to check that the expiration time is set on logout tokens

Closes #25753

Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
Alexander Schwartz 2023-12-22 12:36:48 +01:00 committed by Alexander Schwartz
parent 5e623f42d4
commit 9e890264df
2 changed files with 24 additions and 1 deletions

View file

@ -329,6 +329,8 @@ public class DefaultTokenManager implements TokenManager {
LogoutToken token = new LogoutToken();
token.id(KeycloakModelUtils.generateId());
token.issuedNow();
// From the spec "OpenID Connect Back-Channel Logout 1.0 incorporating errata set 1" at https://openid.net/specs/openid-connect-backchannel-1_0.html
// "OPs are encouraged to use short expiration times in Logout Tokens, preferably at most two minutes in the future [...]"
token.exp(Time.currentTime() + Duration.ofMinutes(2).getSeconds());
token.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
token.putEvents(TokenUtil.TOKEN_BACKCHANNEL_LOGOUT_EVENT, JsonSerialization.createObjectNode());

View file

@ -33,6 +33,7 @@ import org.keycloak.jose.jws.JWSHeader;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.protocol.oidc.OIDCConfigAttributes;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.LogoutToken;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
@ -43,6 +44,8 @@ import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.pages.LoginPage;
import java.util.List;
import java.util.Map;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriBuilder;
@ -332,13 +335,31 @@ public class LogoutTest extends AbstractKeycloakTest {
MatcherAssert.assertThat(response.getFirstHeader(HttpHeaders.LOCATION).getValue(), is(oauth.APP_AUTH_ROOT));
}
assertNotNull(testingClient.testApp().getBackChannelLogoutToken());
validateLogoutToken(testingClient.testApp().getBackChannelLogoutToken());
} finally {
rep.getAttributes().put(OIDCConfigAttributes.BACKCHANNEL_LOGOUT_URL, "");
clientResource.update(rep);
}
}
/**
* Validate the token matches the spec at <a href="https://openid.net/specs/openid-connect-backchannel-1_0.html#LogoutToken">OpenID Connect Back-Channel Logout 1.0 incorporating errata set 1</a>
*/
private void validateLogoutToken(LogoutToken backChannelLogoutToken) {
assertNotNull("token must be present", backChannelLogoutToken);
assertNotNull("iss must be present", backChannelLogoutToken.getIssuer());
assertNotNull("aud must be present", backChannelLogoutToken.getAudience());
assertNotNull("iat must be present", backChannelLogoutToken.getIat());
assertNotNull("exp must be present", backChannelLogoutToken.getExp());
assertNotNull("jti must be present", backChannelLogoutToken.getId());
Map<String, Object> events = backChannelLogoutToken.getEvents();
assertNotNull("events must be present", events);
Object backchannelLogoutEvent = events.get("http://schemas.openid.net/event/backchannel-logout");
assertNotNull("back-channel logout event must be present", backchannelLogoutEvent);
assertTrue("back-channel logout event must have a member object", backchannelLogoutEvent instanceof Map);
MatcherAssert.assertThat("map of back-channel logout event member object should be an empty object", (Map<?, ?>) backchannelLogoutEvent, org.hamcrest.Matchers.anEmptyMap());
}
private OAuthClient.AccessTokenResponse loginAndForceNewLoginPage() {
oauth.doLogin("test-user@localhost", "password");