keycloak-uncached
Changes
services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java 34(+28 -6)
Details
diff --git a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java
index bc61c3a..c703332 100644
--- a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java
+++ b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java
@@ -65,6 +65,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UserSessionProvider;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.protocol.oidc.TokenManager.AccessTokenResponseBuilder;
import org.keycloak.representations.AccessToken;
@@ -78,7 +79,11 @@ import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.representations.idm.authorization.PermissionTicketToken;
import org.keycloak.services.CorsErrorResponseException;
import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.Urls;
+import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resources.Cors;
+import org.keycloak.sessions.AuthenticationSessionModel;
+import org.keycloak.sessions.RootAuthenticationSessionModel;
import org.keycloak.util.JsonSerialization;
import org.keycloak.services.util.DefaultClientSessionContext;
@@ -246,17 +251,34 @@ public class AuthorizationTokenService {
}
ClientModel client = realm.getClientByClientId(accessToken.getIssuedFor());
- AuthenticatedClientSessionModel clientSession = userSessionModel.getAuthenticatedClientSessionByClient(client.getId());
- ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession);
+ AuthenticatedClientSessionModel clientSession = userSessionModel.getAuthenticatedClientSessionByClient(targetClient.getId());
+ ClientSessionContext clientSessionCtx;
+
+ if (clientSession == null) {
+ RootAuthenticationSessionModel rootAuthSession = keycloakSession.authenticationSessions().getRootAuthenticationSession(realm, userSessionModel.getId());
+
+ if (rootAuthSession == null) {
+ rootAuthSession = keycloakSession.authenticationSessions().createRootAuthenticationSession(userSessionModel.getId(), realm);
+ }
+
+ AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(targetClient);
+
+ authSession.setAuthenticatedUser(userSessionModel.getUser());
+ authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+ authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(keycloakSession.getContext().getUri().getBaseUri(), realm.getName()));
+
+ AuthenticationManager.setClientScopesInSession(authSession);
+ clientSessionCtx = TokenManager.attachAuthenticationSession(keycloakSession, userSessionModel, authSession);
+ } else {
+ clientSessionCtx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession);
+ }
+
TokenManager tokenManager = request.getTokenManager();
EventBuilder event = request.getEvent();
- AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, clientSession.getClient(), event, keycloakSession, userSessionModel, clientSessionCtx)
+ AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, client, event, keycloakSession, userSessionModel, clientSessionCtx)
.generateAccessToken()
.generateRefreshToken();
AccessToken rpt = responseBuilder.getAccessToken();
-
- rpt.issuedFor(client.getClientId());
-
Authorization authorization = new Authorization();
authorization.setPermissions(entitlements);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java
index 7760791..84f0cc1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/AuthzClientCredentialsTest.java
@@ -176,6 +176,39 @@ public class AuthzClientCredentialsTest extends AbstractAuthzTest {
assertEquals(1, userSessions.size());
}
+ @Test
+ public void testSingleSessionPerUser() throws Exception {
+ ClientsResource clients = getAdminClient().realm("authz-test-session").clients();
+ ClientRepresentation clientRepresentation = clients.findByClientId("resource-server-test").get(0);
+ List<UserSessionRepresentation> userSessions = clients.get(clientRepresentation.getId()).getUserSessions(-1, -1);
+
+ assertEquals(0, userSessions.size());
+
+ AuthzClient authzClient = getAuthzClient("default-session-keycloak.json");
+ org.keycloak.authorization.client.resource.AuthorizationResource authorization = authzClient.authorization("marta", "password");
+ AuthorizationResponse response = authorization.authorize();
+ AccessToken accessToken = toAccessToken(response.getToken());
+ String sessionState = accessToken.getSessionState();
+
+ assertEquals(1, accessToken.getAuthorization().getPermissions().size());
+ assertEquals("Default Resource", accessToken.getAuthorization().getPermissions().iterator().next().getResourceName());
+
+ userSessions = clients.get(clientRepresentation.getId()).getUserSessions(null, null);
+
+ assertEquals(1, userSessions.size());
+
+ for (int i = 0; i < 3; i++) {
+ response = authorization.authorize();
+ accessToken = toAccessToken(response.getToken());
+ assertEquals(sessionState, accessToken.getSessionState());
+ Thread.sleep(1000);
+ }
+
+ userSessions = clients.get(clientRepresentation.getId()).getUserSessions(null, null);
+
+ assertEquals(1, userSessions.size());
+ }
+
private RealmBuilder configureRealm(RealmBuilder builder, ClientBuilder clientBuilder) {
return builder
.roles(RolesBuilder.create().realmRole(new RoleRepresentation("uma_authorization", "", false)))
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/EntitlementAPITest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/EntitlementAPITest.java
index d89748c..a3d0441 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/EntitlementAPITest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/authz/EntitlementAPITest.java
@@ -54,10 +54,14 @@ import org.keycloak.authorization.client.representation.TokenIntrospectionRespon
import org.keycloak.authorization.client.util.HttpResponseException;
import org.keycloak.common.util.Base64Url;
import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
+import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.AccessToken.Authorization;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
import org.keycloak.representations.idm.authorization.AuthorizationRequest.Metadata;
@@ -1208,6 +1212,78 @@ public class EntitlementAPITest extends AbstractAuthzTest {
assertNotNull(response.getToken());
}
+ @Test
+ public void testProcessMappersForTargetAudience() throws Exception {
+ ClientResource publicClient = getClient(getRealm(), PUBLIC_TEST_CLIENT);
+
+ ProtocolMapperRepresentation customClaimMapper = new ProtocolMapperRepresentation();
+
+ customClaimMapper.setName("custom_claim");
+ customClaimMapper.setProtocolMapper(HardcodedClaim.PROVIDER_ID);
+ customClaimMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+ Map<String, String> config = new HashMap<>();
+ config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "custom_claim");
+ config.put(HardcodedClaim.CLAIM_VALUE, PUBLIC_TEST_CLIENT);
+ config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
+ customClaimMapper.setConfig(config);
+
+ publicClient.getProtocolMappers().createMapper(customClaimMapper);
+
+ ClientResource client = getClient(getRealm(), RESOURCE_SERVER_TEST);
+
+ config.put(HardcodedClaim.CLAIM_VALUE, RESOURCE_SERVER_TEST);
+
+ client.getProtocolMappers().createMapper(customClaimMapper);
+
+ AuthorizationResource authorization = client.authorization();
+
+ JSPolicyRepresentation policy = new JSPolicyRepresentation();
+
+ policy.setName(KeycloakModelUtils.generateId());
+ policy.setCode("$evaluation.grant();");
+
+ authorization.policies().js().create(policy).close();
+
+ ResourceRepresentation resource = new ResourceRepresentation();
+
+ resource.setName("Sensors");
+
+ resource = authorization.resources().create(resource).readEntity(ResourceRepresentation.class);
+
+ ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
+
+ permission.setName("View Sensor");
+ permission.addResource(resource.getName());
+ permission.addPolicy(policy.getName());
+
+ authorization.permissions().resource().create(permission);
+
+ oauth.realm("authz-test");
+ oauth.clientId(PUBLIC_TEST_CLIENT);
+ oauth.doLogin("marta", "password");
+
+ // Token request
+ String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+ OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null);
+ AccessToken token = toAccessToken(response.getAccessToken());
+
+ assertEquals(PUBLIC_TEST_CLIENT, token.getOtherClaims().get("custom_claim"));
+
+ AuthorizationRequest request = new AuthorizationRequest();
+
+ request.addPermission("Sensors");
+
+ AuthorizationResponse authorizationResponse = getAuthzClient(AUTHZ_CLIENT_CONFIG).authorization(response.getAccessToken()).authorize(request);
+ token = toAccessToken(authorizationResponse.getToken());
+ assertEquals(RESOURCE_SERVER_TEST, token.getOtherClaims().get("custom_claim"));
+ assertEquals(PUBLIC_TEST_CLIENT, token.getIssuedFor());
+
+ authorizationResponse = getAuthzClient(AUTHZ_CLIENT_CONFIG).authorization(response.getAccessToken()).authorize(request);
+ token = toAccessToken(authorizationResponse.getToken());
+ assertEquals(RESOURCE_SERVER_TEST, token.getOtherClaims().get("custom_claim"));
+ assertEquals(PUBLIC_TEST_CLIENT, token.getIssuedFor());
+ }
+
private void testRptRequestWithResourceName(String configFile) {
Metadata metadata = new Metadata();