|
32 | 32 | import org.keycloak.events.Details; |
33 | 33 | import org.keycloak.events.Errors; |
34 | 34 | import org.keycloak.representations.idm.ClientRepresentation; |
| 35 | +import org.keycloak.representations.idm.ClientScopeRepresentation; |
35 | 36 | import org.keycloak.representations.idm.EventRepresentation; |
36 | 37 | import org.keycloak.representations.idm.IdentityProviderRepresentation; |
37 | 38 | import org.keycloak.representations.idm.RealmRepresentation; |
|
51 | 52 | import java.util.Map; |
52 | 53 |
|
53 | 54 | import static org.junit.Assert.assertEquals; |
| 55 | +import static org.junit.Assert.assertFalse; |
| 56 | +import static org.junit.Assert.assertNotNull; |
| 57 | +import static org.junit.Assert.assertTrue; |
54 | 58 | import static org.keycloak.testsuite.AbstractTestRealmKeycloakTest.TEST_REALM_NAME; |
55 | 59 | import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; |
56 | 60 | import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient; |
57 | 61 | import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId; |
58 | 62 | import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword; |
59 | 63 | import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude; |
60 | 64 | import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer; |
| 65 | +import org.keycloak.testsuite.util.OAuthClient; |
61 | 66 | import org.keycloak.testsuite.util.OAuthClient.AccessTokenResponse; |
62 | 67 | import org.keycloak.testsuite.util.OAuthClient.AuthorizationEndpointResponse; |
63 | 68 |
|
@@ -336,6 +341,66 @@ public void testConsents() { |
336 | 341 | Assert.assertEquals("There should be no client in user session", 0, sessions.get(0).getClients().size()); |
337 | 342 | } |
338 | 343 |
|
| 344 | + /** |
| 345 | + * KEYCLOAK-18954 |
| 346 | + */ |
| 347 | + @Test |
| 348 | + @AuthServerContainerExclude(AuthServer.REMOTE) |
| 349 | + public void testRetrieveConsentsForUserWithClientsWithGrantedOfflineAccess() throws Exception { |
| 350 | + |
| 351 | + RealmResource providerRealm = adminClient.realm(providerRealmName()); |
| 352 | + |
| 353 | + RealmRepresentation providerRealmRep = providerRealm.toRepresentation(); |
| 354 | + providerRealmRep.setAccountTheme("keycloak"); |
| 355 | + providerRealm.update(providerRealmRep); |
| 356 | + |
| 357 | + ClientRepresentation providerAccountRep = providerRealm.clients().findByClientId("account").get(0); |
| 358 | + |
| 359 | + // add offline_scope to default account-console client scope |
| 360 | + ClientScopeRepresentation offlineAccessScope = providerRealm.getDefaultOptionalClientScopes().stream() |
| 361 | + .filter(csr -> csr.getName().equals(OAuth2Constants.OFFLINE_ACCESS)).findFirst().get(); |
| 362 | + providerRealm.clients().get(providerAccountRep.getId()).removeOptionalClientScope(offlineAccessScope.getId()); |
| 363 | + providerRealm.clients().get(providerAccountRep.getId()).addDefaultClientScope(offlineAccessScope.getId()); |
| 364 | + |
| 365 | + // enable consent required to explicitly grant offline access |
| 366 | + providerAccountRep.setConsentRequired(true); |
| 367 | + providerAccountRep.setDirectAccessGrantsEnabled(true); // for offline token retrieval |
| 368 | + providerRealm.clients().get(providerAccountRep.getId()).update(providerAccountRep); |
| 369 | + |
| 370 | + List<UserRepresentation> searchResult = providerRealm.users().search(getUserLogin()); |
| 371 | + UserRepresentation user = searchResult.get(0); |
| 372 | + |
| 373 | + driver.navigate().to(getAccountUrl(providerRealmName())); |
| 374 | + |
| 375 | + waitForPage("Sign in to provider"); |
| 376 | + log.debug("Logging in"); |
| 377 | + accountLoginPage.login(getUserLogin(), getUserPassword()); |
| 378 | + |
| 379 | + waitForPage("grant access"); |
| 380 | + log.debug("Grant consent for offline_access"); |
| 381 | + Assert.assertTrue(consentPage.isCurrent()); |
| 382 | + consentPage.confirm(); |
| 383 | + |
| 384 | + waitForPage("keycloak account console"); |
| 385 | + |
| 386 | + // disable consent required again to enable direct grant token retrieval. |
| 387 | + providerAccountRep.setConsentRequired(false); |
| 388 | + providerRealm.clients().get(providerAccountRep.getId()).update(providerAccountRep); |
| 389 | + |
| 390 | + log.debug("Obtain offline_token"); |
| 391 | + OAuthClient.AccessTokenResponse response = oauth.realm(providerRealmRep.getRealm()) |
| 392 | + .clientId(providerAccountRep.getClientId()) |
| 393 | + .scope(OAuth2Constants.SCOPE_OPENID +" " + OAuth2Constants.SCOPE_PROFILE + " " + OAuth2Constants.OFFLINE_ACCESS) |
| 394 | + .doGrantAccessTokenRequest(null, getUserLogin(), getUserPassword()); |
| 395 | + assertNotNull(response.getRefreshToken()); |
| 396 | + |
| 397 | + log.debug("Check for Offline Token in consents"); |
| 398 | + List<Map<String, Object>> consents = providerRealm.users().get(user.getId()).getConsents(); |
| 399 | + assertFalse("Consents should not be empty", consents.isEmpty()); |
| 400 | + |
| 401 | + assertTrue(consents.toString().contains("Offline Token")); |
| 402 | + } |
| 403 | + |
339 | 404 | @Test |
340 | 405 | public void testConsentCancel() { |
341 | 406 | // setup account client to require consent |
|
0 commit comments