KEYCLOAK-13682 NPE when refreshing token after enabling consent
This commit is contained in:
parent
a878bec60f
commit
aa309b96a8
2 changed files with 52 additions and 1 deletions
|
@ -570,7 +570,7 @@ public class TokenManager {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!grantedConsent.getGrantedClientScopes().contains(requestedScope)) {
|
if (grantedConsent == null || !grantedConsent.getGrantedClientScopes().contains(requestedScope)) {
|
||||||
logger.debugf("Client '%s' no longer has requested consent from user '%s' for client scope '%s'",
|
logger.debugf("Client '%s' no longer has requested consent from user '%s' for client scope '%s'",
|
||||||
client.getClientId(), user.getUsername(), requestedScope.getName());
|
client.getClientId(), user.getUsername(), requestedScope.getName());
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -20,18 +20,26 @@ package org.keycloak.testsuite.admin;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.keycloak.OAuth2Constants;
|
||||||
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.admin.client.resource.UserResource;
|
import org.keycloak.admin.client.resource.UserResource;
|
||||||
import org.keycloak.admin.client.resource.UsersResource;
|
import org.keycloak.admin.client.resource.UsersResource;
|
||||||
|
import org.keycloak.events.Details;
|
||||||
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
|
import org.keycloak.representations.idm.EventRepresentation;
|
||||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.representations.idm.UserSessionRepresentation;
|
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||||
import org.keycloak.testsuite.Assert;
|
import org.keycloak.testsuite.Assert;
|
||||||
|
import org.keycloak.testsuite.AssertEvents;
|
||||||
|
import org.keycloak.testsuite.pages.AppPage;
|
||||||
import org.keycloak.testsuite.pages.ConsentPage;
|
import org.keycloak.testsuite.pages.ConsentPage;
|
||||||
import org.keycloak.testsuite.pages.ErrorPage;
|
import org.keycloak.testsuite.pages.ErrorPage;
|
||||||
import org.keycloak.testsuite.pages.LoginPage;
|
import org.keycloak.testsuite.pages.LoginPage;
|
||||||
|
@ -41,11 +49,15 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.keycloak.testsuite.AbstractTestRealmKeycloakTest.TEST_REALM_NAME;
|
||||||
|
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
|
||||||
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
|
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
|
||||||
import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
|
import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
|
||||||
import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword;
|
import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword;
|
||||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
||||||
|
import org.keycloak.testsuite.util.OAuthClient.AccessTokenResponse;
|
||||||
|
import org.keycloak.testsuite.util.OAuthClient.AuthorizationEndpointResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||||
|
@ -149,6 +161,8 @@ public class ConsentsTest extends AbstractKeycloakTest {
|
||||||
return IDP_OIDC_ALIAS;
|
return IDP_OIDC_ALIAS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public AssertEvents events = new AssertEvents(this);
|
||||||
|
|
||||||
@Page
|
@Page
|
||||||
protected LoginPage accountLoginPage;
|
protected LoginPage accountLoginPage;
|
||||||
|
@ -156,6 +170,9 @@ public class ConsentsTest extends AbstractKeycloakTest {
|
||||||
@Page
|
@Page
|
||||||
protected ConsentPage consentPage;
|
protected ConsentPage consentPage;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
protected AppPage appPage;
|
||||||
|
|
||||||
@Page
|
@Page
|
||||||
protected ErrorPage errorPage;
|
protected ErrorPage errorPage;
|
||||||
|
|
||||||
|
@ -163,9 +180,11 @@ public class ConsentsTest extends AbstractKeycloakTest {
|
||||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||||
RealmRepresentation providerRealm = createProviderRealm();
|
RealmRepresentation providerRealm = createProviderRealm();
|
||||||
RealmRepresentation consumerRealm = createConsumerRealm();
|
RealmRepresentation consumerRealm = createConsumerRealm();
|
||||||
|
RealmRepresentation realmRepresentation = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
|
||||||
|
|
||||||
testRealms.add(providerRealm);
|
testRealms.add(providerRealm);
|
||||||
testRealms.add(consumerRealm);
|
testRealms.add(consumerRealm);
|
||||||
|
testRealms.add(realmRepresentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -347,6 +366,38 @@ public class ConsentsTest extends AbstractKeycloakTest {
|
||||||
accountPage.assertCurrent();
|
accountPage.assertCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clientConsentRequiredAfterLogin() {
|
||||||
|
oauth.realm(TEST_REALM_NAME).clientId("test-app");
|
||||||
|
AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
|
||||||
|
AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(response.getCode(), "password");
|
||||||
|
|
||||||
|
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||||
|
Assert.assertNotNull(oauth.getCurrentQuery().get(OAuth2Constants.CODE));
|
||||||
|
|
||||||
|
EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
|
||||||
|
String sessionId = loginEvent.getSessionId();
|
||||||
|
|
||||||
|
ClientRepresentation clientRepresentation = adminClient.realm(TEST_REALM_NAME).clients().findByClientId("test-app").get(0);
|
||||||
|
try {
|
||||||
|
clientRepresentation.setConsentRequired(true);
|
||||||
|
adminClient.realm(TEST_REALM_NAME).clients().get(clientRepresentation.getId()).update(clientRepresentation);
|
||||||
|
|
||||||
|
events.clear();
|
||||||
|
|
||||||
|
// try to refresh the token
|
||||||
|
// this fails as client no longer has requested consent from user
|
||||||
|
AccessTokenResponse refreshTokenResponse = oauth.doRefreshTokenRequest(accessTokenResponse.getRefreshToken(), "password");
|
||||||
|
Assert.assertEquals(OAuthErrorException.INVALID_SCOPE, refreshTokenResponse.getError());
|
||||||
|
Assert.assertEquals("Client no longer has requested consent from user", refreshTokenResponse.getErrorDescription());
|
||||||
|
|
||||||
|
events.expectRefresh(accessTokenResponse.getRefreshToken(), sessionId).clearDetails().error(Errors.INVALID_TOKEN).assertEvent();
|
||||||
|
} finally {
|
||||||
|
clientRepresentation.setConsentRequired(false);
|
||||||
|
adminClient.realm(TEST_REALM_NAME).clients().get(clientRepresentation.getId()).update(clientRepresentation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String getAccountUrl(String realmName) {
|
private String getAccountUrl(String realmName) {
|
||||||
return getAuthRoot() + "/auth/realms/" + realmName + "/account";
|
return getAuthRoot() + "/auth/realms/" + realmName + "/account";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue