Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,15 @@ public Response process(Context context) {
}

AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
if (clientSession == null) {
// The client session is gone (e.g. its idle timeout is shorter than the user session's),
// so the client has to restart the device flow.
String errorMessage = "Session not active";
event.detail(Details.REASON, errorMessage);
event.error(Errors.SESSION_EXPIRED);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, errorMessage,
Response.Status.BAD_REQUEST);
}
if (!client.getClientId().equals(clientSession.getClient().getClientId())) {
event.error(Errors.INVALID_CODE);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Auth error",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,52 @@ public void testDeviceCodeLifespanPerClient() throws Exception {
client.update(clientRepresentation);
}

@Test
public void testExpiredClientSession() throws Exception {
getTestingClient().testing().setTestingInfinispanTimeService();
ClientResource client = AdminApiUtil.findClientByClientId(adminClient.realm(REALM_NAME), DEVICE_APP_PUBLIC);
ClientRepresentation clientRepresentation = client.toRepresentation();

// Device Authorization Request from device
oauth.realm(REALM_NAME);
oauth.client(DEVICE_APP_PUBLIC);
DeviceAuthorizationResponse response = oauth.device().doDeviceAuthorizationRequest();

Assertions.assertEquals(200, response.getStatusCode());
assertNotNull(response.getDeviceCode());
assertNotNull(response.getUserCode());
assertNotNull(response.getVerificationUriComplete());

// Make the client session idle timeout shorter than the user session timeout
clientRepresentation.getAttributes().put(OIDCConfigAttributes.CLIENT_SESSION_IDLE_TIMEOUT, "5");
client.update(clientRepresentation);

openVerificationPage(response.getVerificationUriComplete());

// Do Login
oauth.fillLoginForm("device-login", "password");

// Consent
grantPage.accept();

try {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No failures of the kind described have been observed on this PR's CI: the red checks are the two infra flakes documented at PR level (comment) — Test OLM installation failed with a 504 gateway timeout during the install step (run 41929270839), and Admin UI E2E (chromium) hit a flaky step reported by Playwright as 1 flaky (run 41929270979) — neither is related to this test or its cleanup ordering.

// Wait until the client session is expired while the user session is still alive
timeOffSet.set(10);

// Token request from device
AccessTokenResponse tokenResponse = oauth.device().doDeviceTokenRequest(response.getDeviceCode());

Assertions.assertEquals(400, tokenResponse.getStatusCode());
Assertions.assertEquals("invalid_grant", tokenResponse.getError());
Assertions.assertEquals("Session not active", tokenResponse.getErrorDescription());
} finally {
timeOffSet.set(0);
clientRepresentation.getAttributes().remove(OIDCConfigAttributes.CLIENT_SESSION_IDLE_TIMEOUT);
client.update(clientRepresentation);
getTestingClient().testing().revertTestingInfinispanTimeService();
}
}

@Test
public void testDevicePollingIntervalPerClient() throws Exception {
getTestingClient().testing().setTestingInfinispanTimeService();
Expand Down
Loading