KEYCLOAK-19237 Avoid using stream that has been operated
This commit is contained in:
parent
10c3e149d3
commit
884471c729
2 changed files with 48 additions and 3 deletions
|
@ -273,15 +273,14 @@ public class DeviceGrantType {
|
|||
// Compute client scopes again from scope parameter. Check if user still has them granted
|
||||
// (but in device_code-to-token request, it could just theoretically happen that they are not available)
|
||||
String scopeParam = deviceCodeModel.getScope();
|
||||
Stream<ClientScopeModel> clientScopes = TokenManager.getRequestedClientScopes(scopeParam, client);
|
||||
if (!TokenManager.verifyConsentStillAvailable(session, user, client, clientScopes)) {
|
||||
if (!TokenManager.verifyConsentStillAvailable(session, user, client, TokenManager.getRequestedClientScopes(scopeParam, client))) {
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_SCOPE,
|
||||
"Client no longer has requested consent from user", Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndClientScopes(clientSession,
|
||||
clientScopes, session);
|
||||
TokenManager.getRequestedClientScopes(scopeParam, client), session);
|
||||
|
||||
// Set nonce as an attribute in the ClientSessionContext. Will be used for the token generation
|
||||
clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, deviceCodeModel.getNonce());
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.junit.Rule;
|
|||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.OAuth2DeviceConfig;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
||||
|
@ -59,6 +60,7 @@ public class OAuth2DeviceAuthorizationGrantTest extends AbstractKeycloakTest {
|
|||
public static final String REALM_NAME = "test";
|
||||
public static final String DEVICE_APP = "test-device";
|
||||
public static final String DEVICE_APP_PUBLIC = "test-device-public";
|
||||
public static final String DEVICE_APP_PUBLIC_CUSTOM_CONSENT = "test-device-public-custom-consent";
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
|
@ -93,6 +95,14 @@ public class OAuth2DeviceAuthorizationGrantTest extends AbstractKeycloakTest {
|
|||
.build();
|
||||
realm.client(appPublic);
|
||||
|
||||
ClientRepresentation appPublicCustomConsent = ClientBuilder.create().id(KeycloakModelUtils.generateId()).publicClient()
|
||||
.clientId(DEVICE_APP_PUBLIC_CUSTOM_CONSENT).attribute(OAuth2DeviceConfig.OAUTH2_DEVICE_AUTHORIZATION_GRANT_ENABLED, "true")
|
||||
.consentRequired(true)
|
||||
.attribute(ClientScopeModel.DISPLAY_ON_CONSENT_SCREEN, "true")
|
||||
.attribute(ClientScopeModel.CONSENT_SCREEN_TEXT, "This is the custom consent screen text.")
|
||||
.build();
|
||||
realm.client(appPublicCustomConsent);
|
||||
|
||||
userId = KeycloakModelUtils.generateId();
|
||||
UserRepresentation user = UserBuilder.create()
|
||||
.id(userId)
|
||||
|
@ -192,6 +202,42 @@ public class OAuth2DeviceAuthorizationGrantTest extends AbstractKeycloakTest {
|
|||
assertNotNull(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPublicClientCustomConsent() throws Exception {
|
||||
// Device Authorization Request from device
|
||||
oauth.realm(REALM_NAME);
|
||||
oauth.clientId(DEVICE_APP_PUBLIC_CUSTOM_CONSENT);
|
||||
OAuthClient.DeviceAuthorizationResponse response = oauth.doDeviceAuthorizationRequest(DEVICE_APP_PUBLIC_CUSTOM_CONSENT, null);
|
||||
|
||||
Assert.assertEquals(200, response.getStatusCode());
|
||||
assertNotNull(response.getDeviceCode());
|
||||
assertNotNull(response.getUserCode());
|
||||
assertNotNull(response.getVerificationUri());
|
||||
assertNotNull(response.getVerificationUriComplete());
|
||||
Assert.assertEquals(60, response.getExpiresIn());
|
||||
Assert.assertEquals(5, response.getInterval());
|
||||
|
||||
openVerificationPage(response.getVerificationUriComplete());
|
||||
|
||||
// Do Login
|
||||
oauth.fillLoginForm("device-login", "password");
|
||||
|
||||
// Consent
|
||||
Assert.assertTrue(grantPage.getDisplayedGrants().contains("This is the custom consent screen text."));
|
||||
grantPage.accept();
|
||||
|
||||
// Token request from device
|
||||
OAuthClient.AccessTokenResponse tokenResponse = oauth.doDeviceTokenRequest(DEVICE_APP_PUBLIC_CUSTOM_CONSENT, null, response.getDeviceCode());
|
||||
|
||||
Assert.assertEquals(200, tokenResponse.getStatusCode());
|
||||
|
||||
String tokenString = tokenResponse.getAccessToken();
|
||||
assertNotNull(tokenString);
|
||||
AccessToken token = oauth.verifyToken(tokenString);
|
||||
|
||||
assertNotNull(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoRefreshToken() throws Exception {
|
||||
ClientResource client = ApiUtil.findClientByClientId(adminClient.realm(REALM_NAME), DEVICE_APP);
|
||||
|
|
Loading…
Reference in a new issue