8000 (26.6) Check consento for JWT Authorization Grant by graziang · Pull Request #52115 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
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 @@ -125,6 +125,13 @@ public Response process(Context context) {

String scopeParam = getRequestedScopes();

if (!TokenManager.verifyConsentStillAvailable(session, user, client, TokenManager.getRequestedClientScopes(session, scopeParam, client, user))) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this one differs from the original cherry pick, please can you elaborate on it? thanks

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.

verifyConsentStillAvailable has been refactored in 26.7 as part of parameterized scopes feature, I'm passing the scope parameter as a stream like before

8000 Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thanks for the explanation

String errorMessage = "Missing consents for the client " + client.getClientId();
event.detail(Details.REASON, errorMessage);
event.error(Errors.CONSENT_DENIED);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_SCOPE, errorMessage, Response.Status.BAD_REQUEST);
}

try {
session.clientPolicy().triggerOnEvent(new JWTAuthorizationGrantContext(context.getSession(), authorizationGrantContext, identityProviderModel.getAlias()));
} catch (ClientPolicyException cpe) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,49 @@
import java.util.List;

import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
import org.keycloak.common.util.PemUtils;
import org.keycloak.common.util.Time;
import org.keycloak.crypto.Algorithm;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventType;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserModel;
import org.keycloak.protocol.oidc.OIDCConfigAttributes;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.UserConsentManager;
import org.keycloak.testframework.events.EventAssertion;
import org.keycloak.testframework.oauth.OAuthIdentityProvider;
import org.keycloak.testframework.realm.ManagedClient;
import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.tests.utils.admin.AdminApiUtil;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
import org.keycloak.util.JsonSerialization;

import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public abstract class AbstractJWTAuthorizationGrantTest extends BaseAbstractJWTAuthorizationGrantTest {

@InjectRunOnServer
RunOnServerClient runOnServer;

@Test
public void testPublicClient() {
String jwt = getIdentityProvider().encodeToken(createDefaultAuthorizationGrantToken());
Expand Down Expand Up @@ -438,4 +454,56 @@ public void testHS256AlgorithmConfusionWithHardcodedJWKS() throws IOException {
AccessTokenResponse response = oAuthClient.jwtAuthorizationGrantRequest(encodedToken).send();
assertFailure("Invalid signature algorithm", response, events.poll());
}

@Test
public void testConsentRequiredIsRejected() {
ClientResource clientResource = AdminApiUtil.findClientByClientId(realm.admin(), "test-app");
ClientRepresentation rep = clientResource.toRepresentation();
rep.setConsentRequired(true);
clientResource.update(rep);
try {
String jwt = getIdentityProvider().encodeToken(createDefaultAuthorizationGrantToken());
AccessTokenResponse response = oAuthClient.jwtAuthorizationGrantRequest(jwt).send();

Assertions.assertFalse(response.isSuccess());
Assertions.assertEquals(OAuthErrorException.INVALID_SCOPE, response.getError());
Assertions.assertEquals("Missing consents for the client test-app", response.getErrorDescription());
EventAssertion.assertError(events.poll())
.type(EventType.JWT_AUTHORIZATION_GRANT_ERROR)
.userId(user.getId())
.error(Errors.CONSENT_DENIED)
.details(Details.REASON, "Missing consents for the client test-app");
} finally {
rep.setConsentRequired(false);
clientResource.update(rep);
}
}

@Test
public void testConsentRequiredWithGrantedConsentSucceeds() {
ClientResource clientResource = AdminApiUtil.findClientByClientId(realm.admin(), "test-app");
ClientRepresentation rep = clientResource.toRepresentation();
rep.setConsentRequired(true);
clientResource.update(rep);
try {
runOnServer.run(session -> {
RealmModel r = session.getContext().getRealm();
ClientModel client = session.clients().getClientByClientId(r, "test-app");
UserModel u = session.users().getUserByUsername(r, "basic-user");
UserConsentModel consent = new UserConsentModel(client);
client.getClientScopes(true).values().stream()
.filter(ClientScopeModel::isDisplayOnConsentScreen)
.forEach(consent::addGrantedClientScope);
UserConsentManager.addConsent(session, r, u, consent);
});

String jwt = getIdentityProvider().encodeToken(createDefaultAuthorizationGrantToken());
AccessTokenResponse response = oAuthClient.jwtAuthorizationGrantRequest(jwt).send();
assertSuccess("test-app", response);
} finally {
realm.admin().users().get(user.getId()).revokeConsent("test-app");
rep.setConsentRequired(false);
clientResource.update(rep);
}
}
}
Loading
0