Add pairwise sub support to authorization services
Identity token verification will now fetch the user from the session state instead of relying on the sub provided in the token. Also done in KeycloakIdentity. Resolves: KEYCLOAK-6659
This commit is contained in:
parent
9b1275f182
commit
8549bd70b7
7 changed files with 229 additions and 52 deletions
|
@ -212,7 +212,7 @@ public class KeycloakIdentity implements Identity {
|
||||||
return client==null ? null : client.getId();
|
return client==null ? null : client.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.accessToken.getSubject();
|
return this.getUserFromSessionState().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -237,7 +237,7 @@ public class KeycloakIdentity implements Identity {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.accessToken.getSubject().equals(clientUser.getId());
|
return this.getUserFromSessionState().getId().equals(clientUser.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientModel getTargetClient() {
|
private ClientModel getTargetClient() {
|
||||||
|
@ -252,4 +252,9 @@ public class KeycloakIdentity implements Identity {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private UserModel getUserFromSessionState() {
|
||||||
|
UserSessionModel userSession = keycloakSession.sessions().getUserSession(realm, accessToken.getSessionState());
|
||||||
|
return userSession.getUser();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1082,24 +1082,28 @@ public class AuthenticationManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UserModel user = session.users().getUserById(token.getSubject(), realm);
|
|
||||||
if (user == null || !user.isEnabled() ) {
|
|
||||||
logger.debug("Unknown user in identity token");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int userNotBefore = session.users().getNotBeforeOfUser(realm, user);
|
|
||||||
if (token.getIssuedAt() < userNotBefore) {
|
|
||||||
logger.debug("User notBefore newer than token");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
|
UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
|
||||||
|
UserModel user = null;
|
||||||
|
if (userSession != null) {
|
||||||
|
user = userSession.getUser();
|
||||||
|
if (user == null || !user.isEnabled()) {
|
||||||
|
logger.debug("Unknown user in identity token");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int userNotBefore = session.users().getNotBeforeOfUser(realm, user);
|
||||||
|
if (token.getIssuedAt() < userNotBefore) {
|
||||||
|
logger.debug("User notBefore newer than token");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isSessionValid(realm, userSession)) {
|
if (!isSessionValid(realm, userSession)) {
|
||||||
// Check if accessToken was for the offline session.
|
// Check if accessToken was for the offline session.
|
||||||
if (!isCookie) {
|
if (!isCookie) {
|
||||||
UserSessionModel offlineUserSession = session.sessions().getOfflineUserSession(realm, token.getSessionState());
|
UserSessionModel offlineUserSession = session.sessions().getOfflineUserSession(realm, token.getSessionState());
|
||||||
if (isOfflineSessionValid(realm, offlineUserSession)) {
|
if (isOfflineSessionValid(realm, offlineUserSession)) {
|
||||||
|
user = offlineUserSession.getUser();
|
||||||
return new AuthResult(user, offlineUserSession, token);
|
return new AuthResult(user, offlineUserSession, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,29 +53,53 @@ import org.keycloak.util.JsonSerialization;
|
||||||
*/
|
*/
|
||||||
public class AuthorizationAPITest extends AbstractAuthzTest {
|
public class AuthorizationAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
|
private static final String RESOURCE_SERVER_TEST = "resource-server-test";
|
||||||
|
private static final String TEST_CLIENT = "test-client";
|
||||||
|
private static final String AUTHZ_CLIENT_CONFIG = "default-keycloak.json";
|
||||||
|
private static final String PAIRWISE_RESOURCE_SERVER_TEST = "pairwise-resource-server-test";
|
||||||
|
private static final String PAIRWISE_TEST_CLIENT = "test-client-pairwise";
|
||||||
|
private static final String PAIRWISE_AUTHZ_CLIENT_CONFIG = "default-keycloak-pairwise.json";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||||
testRealms.add(RealmBuilder.create().name("authz-test")
|
testRealms.add(RealmBuilder.create().name("authz-test")
|
||||||
.roles(RolesBuilder.create().realmRole(RoleBuilder.create().name("uma_authorization").build()))
|
.roles(RolesBuilder.create().realmRole(RoleBuilder.create().name("uma_authorization").build()))
|
||||||
.user(UserBuilder.create().username("marta").password("password").addRoles("uma_authorization"))
|
.user(UserBuilder.create().username("marta").password("password").addRoles("uma_authorization"))
|
||||||
.user(UserBuilder.create().username("kolo").password("password"))
|
.user(UserBuilder.create().username("kolo").password("password"))
|
||||||
.client(ClientBuilder.create().clientId("resource-server-test")
|
.client(ClientBuilder.create().clientId(RESOURCE_SERVER_TEST)
|
||||||
.secret("secret")
|
.secret("secret")
|
||||||
.authorizationServicesEnabled(true)
|
.authorizationServicesEnabled(true)
|
||||||
.redirectUris("http://localhost/resource-server-test")
|
.redirectUris("http://localhost/resource-server-test")
|
||||||
.defaultRoles("uma_protection")
|
.defaultRoles("uma_protection")
|
||||||
.directAccessGrants())
|
.directAccessGrants())
|
||||||
.client(ClientBuilder.create().clientId("test-client")
|
.client(ClientBuilder.create().clientId(PAIRWISE_RESOURCE_SERVER_TEST)
|
||||||
|
.secret("secret")
|
||||||
|
.authorizationServicesEnabled(true)
|
||||||
|
.redirectUris("http://localhost/resource-server-test")
|
||||||
|
.defaultRoles("uma_protection")
|
||||||
|
.directAccessGrants()
|
||||||
|
.pairwise("http://pairwise.com"))
|
||||||
|
.client(ClientBuilder.create().clientId(TEST_CLIENT)
|
||||||
.secret("secret")
|
.secret("secret")
|
||||||
.authorizationServicesEnabled(true)
|
.authorizationServicesEnabled(true)
|
||||||
.redirectUris("http://localhost/test-client")
|
.redirectUris("http://localhost/test-client")
|
||||||
.directAccessGrants())
|
.directAccessGrants())
|
||||||
|
.client(ClientBuilder.create().clientId(PAIRWISE_TEST_CLIENT)
|
||||||
|
.secret("secret")
|
||||||
|
.authorizationServicesEnabled(true)
|
||||||
|
.redirectUris("http://localhost/test-client")
|
||||||
|
.directAccessGrants())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void configureAuthorization() throws Exception {
|
public void configureAuthorization() throws Exception {
|
||||||
ClientResource client = getClient(getRealm());
|
configureAuthorization(RESOURCE_SERVER_TEST);
|
||||||
|
configureAuthorization(PAIRWISE_RESOURCE_SERVER_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureAuthorization(String clientId) throws Exception {
|
||||||
|
ClientResource client = getClient(getRealm(), clientId);
|
||||||
AuthorizationResource authorization = client.authorization();
|
AuthorizationResource authorization = client.authorization();
|
||||||
ResourceRepresentation resource = new ResourceRepresentation("Resource A");
|
ResourceRepresentation resource = new ResourceRepresentation("Resource A");
|
||||||
|
|
||||||
|
@ -102,7 +126,16 @@ public class AuthorizationAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAccessTokenWithUmaAuthorization() {
|
public void testAccessTokenWithUmaAuthorization() {
|
||||||
AuthzClient authzClient = getAuthzClient();
|
testAccessTokenWithUmaAuthorization(AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccessTokenWithUmaAuthorizationPairwise() {
|
||||||
|
testAccessTokenWithUmaAuthorization(PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAccessTokenWithUmaAuthorization(String authzConfigFile) {
|
||||||
|
AuthzClient authzClient = getAuthzClient(authzConfigFile);
|
||||||
PermissionRequest request = new PermissionRequest("Resource A");
|
PermissionRequest request = new PermissionRequest("Resource A");
|
||||||
|
|
||||||
String ticket = authzClient.protection().permission().create(request).getTicket();
|
String ticket = authzClient.protection().permission().create(request).getTicket();
|
||||||
|
@ -113,32 +146,63 @@ public class AuthorizationAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResourceServerAsAudience() throws Exception {
|
public void testResourceServerAsAudience() throws Exception {
|
||||||
AuthzClient authzClient = getAuthzClient();
|
testResourceServerAsAudience(
|
||||||
|
TEST_CLIENT,
|
||||||
|
RESOURCE_SERVER_TEST,
|
||||||
|
AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceServerAsAudienceWithPairwiseClient() throws Exception {
|
||||||
|
testResourceServerAsAudience(
|
||||||
|
PAIRWISE_TEST_CLIENT,
|
||||||
|
RESOURCE_SERVER_TEST,
|
||||||
|
AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPairwiseResourceServerAsAudience() throws Exception {
|
||||||
|
testResourceServerAsAudience(
|
||||||
|
TEST_CLIENT,
|
||||||
|
PAIRWISE_RESOURCE_SERVER_TEST,
|
||||||
|
PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPairwiseResourceServerAsAudienceWithPairwiseClient() throws Exception {
|
||||||
|
testResourceServerAsAudience(
|
||||||
|
PAIRWISE_TEST_CLIENT,
|
||||||
|
PAIRWISE_RESOURCE_SERVER_TEST,
|
||||||
|
PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResourceServerAsAudience(String clientId, String resourceServerClientId, String authzConfigFile) throws Exception {
|
||||||
|
AuthzClient authzClient = getAuthzClient(authzConfigFile);
|
||||||
PermissionRequest request = new PermissionRequest();
|
PermissionRequest request = new PermissionRequest();
|
||||||
|
|
||||||
request.setResourceId("Resource A");
|
request.setResourceId("Resource A");
|
||||||
|
|
||||||
String accessToken = new OAuthClient().realm("authz-test").clientId("test-client").doGrantAccessTokenRequest("secret", "marta", "password").getAccessToken();
|
String accessToken = new OAuthClient().realm("authz-test").clientId(clientId).doGrantAccessTokenRequest("secret", "marta", "password").getAccessToken();
|
||||||
String ticket = authzClient.protection().permission().create(request).getTicket();
|
String ticket = authzClient.protection().permission().create(request).getTicket();
|
||||||
AuthorizationResponse response = authzClient.authorization(accessToken).authorize(new AuthorizationRequest(ticket));
|
AuthorizationResponse response = authzClient.authorization(accessToken).authorize(new AuthorizationRequest(ticket));
|
||||||
|
|
||||||
assertNotNull(response.getToken());
|
assertNotNull(response.getToken());
|
||||||
AccessToken rpt = toAccessToken(response.getToken());
|
AccessToken rpt = toAccessToken(response.getToken());
|
||||||
assertEquals("resource-server-test", rpt.getAudience()[0]);
|
assertEquals(resourceServerClientId, rpt.getAudience()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RealmResource getRealm() throws Exception {
|
private RealmResource getRealm() throws Exception {
|
||||||
return adminClient.realm("authz-test");
|
return adminClient.realm("authz-test");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientResource getClient(RealmResource realm) {
|
private ClientResource getClient(RealmResource realm, String clientId) {
|
||||||
ClientsResource clients = realm.clients();
|
ClientsResource clients = realm.clients();
|
||||||
return clients.findByClientId("resource-server-test").stream().map(representation -> clients.get(representation.getId())).findFirst().orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
|
return clients.findByClientId(clientId).stream().map(representation -> clients.get(representation.getId())).findFirst().orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthzClient getAuthzClient() {
|
private AuthzClient getAuthzClient(String configFile) {
|
||||||
try {
|
try {
|
||||||
return AuthzClient.create(JsonSerialization.readValue(getClass().getResourceAsStream("/authorization-test/default-keycloak.json"), Configuration.class));
|
return AuthzClient.create(JsonSerialization.readValue(getClass().getResourceAsStream("/authorization-test/" + configFile), Configuration.class));
|
||||||
} catch (IOException cause) {
|
} catch (IOException cause) {
|
||||||
throw new RuntimeException("Failed to create authz client", cause);
|
throw new RuntimeException("Failed to create authz client", cause);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,13 @@ import org.keycloak.util.JsonSerialization;
|
||||||
*/
|
*/
|
||||||
public class EntitlementAPITest extends AbstractAuthzTest {
|
public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
|
private static final String RESOURCE_SERVER_TEST = "resource-server-test";
|
||||||
|
private static final String TEST_CLIENT = "test-client";
|
||||||
|
private static final String AUTHZ_CLIENT_CONFIG = "default-keycloak.json";
|
||||||
|
private static final String PAIRWISE_RESOURCE_SERVER_TEST = "pairwise-resource-server-test";
|
||||||
|
private static final String PAIRWISE_TEST_CLIENT = "test-client-pairwise";
|
||||||
|
private static final String PAIRWISE_AUTHZ_CLIENT_CONFIG = "default-keycloak-pairwise.json";
|
||||||
|
|
||||||
private AuthzClient authzClient;
|
private AuthzClient authzClient;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,23 +70,41 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
.roles(RolesBuilder.create().realmRole(RoleBuilder.create().name("uma_authorization").build()))
|
.roles(RolesBuilder.create().realmRole(RoleBuilder.create().name("uma_authorization").build()))
|
||||||
.user(UserBuilder.create().username("marta").password("password").addRoles("uma_authorization"))
|
.user(UserBuilder.create().username("marta").password("password").addRoles("uma_authorization"))
|
||||||
.user(UserBuilder.create().username("kolo").password("password"))
|
.user(UserBuilder.create().username("kolo").password("password"))
|
||||||
.client(ClientBuilder.create().clientId("resource-server-test")
|
.client(ClientBuilder.create().clientId(RESOURCE_SERVER_TEST)
|
||||||
.secret("secret")
|
.secret("secret")
|
||||||
.authorizationServicesEnabled(true)
|
.authorizationServicesEnabled(true)
|
||||||
.redirectUris("http://localhost/resource-server-test")
|
.redirectUris("http://localhost/resource-server-test")
|
||||||
.defaultRoles("uma_protection")
|
.defaultRoles("uma_protection")
|
||||||
.directAccessGrants())
|
.directAccessGrants())
|
||||||
.client(ClientBuilder.create().clientId("test-client")
|
.client(ClientBuilder.create().clientId(PAIRWISE_RESOURCE_SERVER_TEST)
|
||||||
.secret("secret")
|
.secret("secret")
|
||||||
.authorizationServicesEnabled(true)
|
.authorizationServicesEnabled(true)
|
||||||
.redirectUris("http://localhost/test-client")
|
.redirectUris("http://localhost/resource-server-test")
|
||||||
.directAccessGrants())
|
.defaultRoles("uma_protection")
|
||||||
|
.pairwise("http://pairwise.com")
|
||||||
|
.directAccessGrants())
|
||||||
|
.client(ClientBuilder.create().clientId(TEST_CLIENT)
|
||||||
|
.secret("secret")
|
||||||
|
.authorizationServicesEnabled(true)
|
||||||
|
.redirectUris("http://localhost/test-client")
|
||||||
|
.directAccessGrants())
|
||||||
|
.client(ClientBuilder.create().clientId(PAIRWISE_TEST_CLIENT)
|
||||||
|
.secret("secret")
|
||||||
|
.authorizationServicesEnabled(true)
|
||||||
|
.redirectUris("http://localhost/test-client")
|
||||||
|
.pairwise("http://pairwise.com")
|
||||||
|
.directAccessGrants())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void configureAuthorization() throws Exception {
|
public void configureAuthorization() throws Exception {
|
||||||
ClientResource client = getClient(getRealm());
|
configureAuthorization(RESOURCE_SERVER_TEST);
|
||||||
|
configureAuthorization(PAIRWISE_RESOURCE_SERVER_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configureAuthorization(String clientId) throws Exception {
|
||||||
|
ClientResource client = getClient(getRealm(), clientId);
|
||||||
AuthorizationResource authorization = client.authorization();
|
AuthorizationResource authorization = client.authorization();
|
||||||
|
|
||||||
JSPolicyRepresentation policy = new JSPolicyRepresentation();
|
JSPolicyRepresentation policy = new JSPolicyRepresentation();
|
||||||
|
@ -106,6 +131,15 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRptRequestWithoutResourceName() {
|
public void testRptRequestWithoutResourceName() {
|
||||||
|
testRptRequestWithoutResourceName(AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRptRequestWithoutResourceNamePairwise() {
|
||||||
|
testRptRequestWithoutResourceName(PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRptRequestWithoutResourceName(String configFile) {
|
||||||
Metadata metadata = new Metadata();
|
Metadata metadata = new Metadata();
|
||||||
|
|
||||||
metadata.setIncludeResourceName(false);
|
metadata.setIncludeResourceName(false);
|
||||||
|
@ -116,32 +150,51 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
request.setMetadata(metadata);
|
request.setMetadata(metadata);
|
||||||
request.addPermission("Resource 1");
|
request.addPermission("Resource 1");
|
||||||
|
|
||||||
return getAuthzClient().authorization("marta", "password").authorize(request);
|
return getAuthzClient(configFile).authorization("marta", "password").authorize(request);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRptRequestWithResourceName() {
|
public void testRptRequestWithResourceName() {
|
||||||
|
testRptRequestWithResourceName(AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRptRequestWithResourceNamePairwise() {
|
||||||
|
testRptRequestWithResourceName(PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testRptRequestWithResourceName(String configFile) {
|
||||||
Metadata metadata = new Metadata();
|
Metadata metadata = new Metadata();
|
||||||
|
|
||||||
metadata.setIncludeResourceName(true);
|
metadata.setIncludeResourceName(true);
|
||||||
|
|
||||||
assertResponse(metadata, () -> getAuthzClient().authorization("marta", "password").authorize());
|
assertResponse(metadata, () -> getAuthzClient(configFile).authorization("marta", "password").authorize());
|
||||||
|
|
||||||
AuthorizationRequest request = new AuthorizationRequest();
|
AuthorizationRequest request = new AuthorizationRequest();
|
||||||
|
|
||||||
request.setMetadata(metadata);
|
request.setMetadata(metadata);
|
||||||
request.addPermission("Resource 13");
|
request.addPermission("Resource 13");
|
||||||
|
|
||||||
assertResponse(metadata, () -> getAuthzClient().authorization("marta", "password").authorize(request));
|
assertResponse(metadata, () -> getAuthzClient(configFile).authorization("marta", "password").authorize(request));
|
||||||
|
|
||||||
request.setMetadata(null);
|
request.setMetadata(null);
|
||||||
|
|
||||||
assertResponse(metadata, () -> getAuthzClient().authorization("marta", "password").authorize(request));
|
assertResponse(metadata, () -> getAuthzClient(configFile).authorization("marta", "password").authorize(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPermissionLimit() {
|
public void testPermissionLimit() {
|
||||||
|
testPermissionLimit(AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPermissionLimitPairwise() {
|
||||||
|
testPermissionLimit(PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPermissionLimit(String configFile) {
|
||||||
AuthorizationRequest request = new AuthorizationRequest();
|
AuthorizationRequest request = new AuthorizationRequest();
|
||||||
|
|
||||||
for (int i = 1; i <= 10; i++) {
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
@ -154,7 +207,7 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
request.setMetadata(metadata);
|
request.setMetadata(metadata);
|
||||||
|
|
||||||
AuthorizationResponse response = getAuthzClient().authorization("marta", "password").authorize(request);
|
AuthorizationResponse response = getAuthzClient(configFile).authorization("marta", "password").authorize(request);
|
||||||
AccessToken rpt = toAccessToken(response.getToken());
|
AccessToken rpt = toAccessToken(response.getToken());
|
||||||
|
|
||||||
List<Permission> permissions = rpt.getAuthorization().getPermissions();
|
List<Permission> permissions = rpt.getAuthorization().getPermissions();
|
||||||
|
@ -174,7 +227,7 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
request.setMetadata(metadata);
|
request.setMetadata(metadata);
|
||||||
request.setRpt(response.getToken());
|
request.setRpt(response.getToken());
|
||||||
|
|
||||||
response = getAuthzClient().authorization("marta", "password").authorize(request);
|
response = getAuthzClient(configFile).authorization("marta", "password").authorize(request);
|
||||||
rpt = toAccessToken(response.getToken());
|
rpt = toAccessToken(response.getToken());
|
||||||
|
|
||||||
permissions = rpt.getAuthorization().getPermissions();
|
permissions = rpt.getAuthorization().getPermissions();
|
||||||
|
@ -198,7 +251,7 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
request.setMetadata(metadata);
|
request.setMetadata(metadata);
|
||||||
request.setRpt(response.getToken());
|
request.setRpt(response.getToken());
|
||||||
|
|
||||||
response = getAuthzClient().authorization("marta", "password").authorize(request);
|
response = getAuthzClient(configFile).authorization("marta", "password").authorize(request);
|
||||||
rpt = toAccessToken(response.getToken());
|
rpt = toAccessToken(response.getToken());
|
||||||
|
|
||||||
permissions = rpt.getAuthorization().getPermissions();
|
permissions = rpt.getAuthorization().getPermissions();
|
||||||
|
@ -221,7 +274,7 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
request.setMetadata(metadata);
|
request.setMetadata(metadata);
|
||||||
request.setRpt(response.getToken());
|
request.setRpt(response.getToken());
|
||||||
|
|
||||||
response = getAuthzClient().authorization("marta", "password").authorize(request);
|
response = getAuthzClient(configFile).authorization("marta", "password").authorize(request);
|
||||||
rpt = toAccessToken(response.getToken());
|
rpt = toAccessToken(response.getToken());
|
||||||
|
|
||||||
permissions = rpt.getAuthorization().getPermissions();
|
permissions = rpt.getAuthorization().getPermissions();
|
||||||
|
@ -236,15 +289,46 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResourceServerAsAudience() throws Exception {
|
public void testResourceServerAsAudience() throws Exception {
|
||||||
|
testResourceServerAsAudience(
|
||||||
|
TEST_CLIENT,
|
||||||
|
RESOURCE_SERVER_TEST,
|
||||||
|
AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceServerAsAudienceWithPairwiseClient() throws Exception {
|
||||||
|
testResourceServerAsAudience(
|
||||||
|
PAIRWISE_TEST_CLIENT,
|
||||||
|
RESOURCE_SERVER_TEST,
|
||||||
|
AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPairwiseResourceServerAsAudience() throws Exception {
|
||||||
|
testResourceServerAsAudience(
|
||||||
|
TEST_CLIENT,
|
||||||
|
PAIRWISE_RESOURCE_SERVER_TEST,
|
||||||
|
PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPairwiseResourceServerAsAudienceWithPairwiseClient() throws Exception {
|
||||||
|
testResourceServerAsAudience(
|
||||||
|
PAIRWISE_TEST_CLIENT,
|
||||||
|
PAIRWISE_RESOURCE_SERVER_TEST,
|
||||||
|
PAIRWISE_AUTHZ_CLIENT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResourceServerAsAudience(String testClientId, String resourceServerClientId, String configFile) throws Exception {
|
||||||
AuthorizationRequest request = new AuthorizationRequest();
|
AuthorizationRequest request = new AuthorizationRequest();
|
||||||
|
|
||||||
request.addPermission("Resource 1");
|
request.addPermission("Resource 1");
|
||||||
|
|
||||||
String accessToken = new OAuthClient().realm("authz-test").clientId("test-client").doGrantAccessTokenRequest("secret", "marta", "password").getAccessToken();
|
String accessToken = new OAuthClient().realm("authz-test").clientId(testClientId).doGrantAccessTokenRequest("secret", "marta", "password").getAccessToken();
|
||||||
AuthorizationResponse response = getAuthzClient().authorization(accessToken).authorize(request);
|
AuthorizationResponse response = getAuthzClient(configFile).authorization(accessToken).authorize(request);
|
||||||
AccessToken rpt = toAccessToken(response.getToken());
|
AccessToken rpt = toAccessToken(response.getToken());
|
||||||
|
|
||||||
assertEquals("resource-server-test", rpt.getAudience()[0]);
|
assertEquals(resourceServerClientId, rpt.getAudience()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertResponse(Metadata metadata, Supplier<AuthorizationResponse> responseSupplier) {
|
private void assertResponse(Metadata metadata, Supplier<AuthorizationResponse> responseSupplier) {
|
||||||
|
@ -268,15 +352,15 @@ public class EntitlementAPITest extends AbstractAuthzTest {
|
||||||
return adminClient.realm("authz-test");
|
return adminClient.realm("authz-test");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientResource getClient(RealmResource realm) {
|
private ClientResource getClient(RealmResource realm, String clientId) {
|
||||||
ClientsResource clients = realm.clients();
|
ClientsResource clients = realm.clients();
|
||||||
return clients.findByClientId("resource-server-test").stream().map(representation -> clients.get(representation.getId())).findFirst().orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
|
return clients.findByClientId(clientId).stream().map(representation -> clients.get(representation.getId())).findFirst().orElseThrow(() -> new RuntimeException("Expected client [resource-server-test]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthzClient getAuthzClient() {
|
private AuthzClient getAuthzClient(String configFile) {
|
||||||
if (authzClient == null) {
|
if (authzClient == null) {
|
||||||
try {
|
try {
|
||||||
authzClient = AuthzClient.create(JsonSerialization.readValue(getClass().getResourceAsStream("/authorization-test/default-keycloak.json"), Configuration.class));
|
authzClient = AuthzClient.create(JsonSerialization.readValue(getClass().getResourceAsStream("/authorization-test/" + configFile), Configuration.class));
|
||||||
} catch (IOException cause) {
|
} catch (IOException cause) {
|
||||||
throw new RuntimeException("Failed to create authz client", cause);
|
throw new RuntimeException("Failed to create authz client", cause);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,4 +198,12 @@ public class ClientBuilder {
|
||||||
rep.getProtocolMappers().addAll(Arrays.asList(mappers));
|
rep.getProtocolMappers().addAll(Arrays.asList(mappers));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClientBuilder pairwise(String sectorIdentifierUri, String salt) {
|
||||||
|
return protocolMapper(ProtocolMapperUtil.createPairwiseMapper(sectorIdentifierUri, salt));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientBuilder pairwise(String sectorIdentifierUri) {
|
||||||
|
return protocolMapper(ProtocolMapperUtil.createPairwiseMapper(sectorIdentifierUri, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.protocol.oidc.mappers.AddressMapper;
|
||||||
import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
|
import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
|
||||||
import org.keycloak.protocol.oidc.mappers.HardcodedRole;
|
import org.keycloak.protocol.oidc.mappers.HardcodedRole;
|
||||||
import org.keycloak.protocol.oidc.mappers.RoleNameMapper;
|
import org.keycloak.protocol.oidc.mappers.RoleNameMapper;
|
||||||
|
import org.keycloak.protocol.oidc.mappers.SHA256PairwiseSubMapper;
|
||||||
import org.keycloak.protocol.oidc.mappers.ScriptBasedOIDCProtocolMapper;
|
import org.keycloak.protocol.oidc.mappers.ScriptBasedOIDCProtocolMapper;
|
||||||
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
|
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
|
||||||
import org.keycloak.protocol.oidc.mappers.UserClientRoleMappingMapper;
|
import org.keycloak.protocol.oidc.mappers.UserClientRoleMappingMapper;
|
||||||
|
@ -164,4 +165,7 @@ public class ProtocolMapperUtil {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ProtocolMapperRepresentation createPairwiseMapper(String sectorIdentifierUri, String salt) {
|
||||||
|
return SHA256PairwiseSubMapper.createPairwiseMapper(sectorIdentifierUri, salt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"realm": "authz-test",
|
||||||
|
"auth-server-url" : "http://localhost:8180/auth",
|
||||||
|
"resource" : "pairwise-resource-server-test",
|
||||||
|
"credentials": {
|
||||||
|
"secret": "secret"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue