Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
986f39838c
11 changed files with 273 additions and 53 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,8 +1082,11 @@ public class AuthenticationManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UserModel user = session.users().getUserById(token.getSubject(), realm);
|
UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
|
||||||
if (user == null || !user.isEnabled() ) {
|
UserModel user = null;
|
||||||
|
if (userSession != null) {
|
||||||
|
user = userSession.getUser();
|
||||||
|
if (user == null || !user.isEnabled()) {
|
||||||
logger.debug("Unknown user in identity token");
|
logger.debug("Unknown user in identity token");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1093,13 +1096,14 @@ public class AuthenticationManager {
|
||||||
logger.debug("User notBefore newer than token");
|
logger.debug("User notBefore newer than token");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
|
|
||||||
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,19 +53,38 @@ 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")
|
||||||
|
.authorizationServicesEnabled(true)
|
||||||
|
.redirectUris("http://localhost/test-client")
|
||||||
|
.directAccessGrants())
|
||||||
|
.client(ClientBuilder.create().clientId(PAIRWISE_TEST_CLIENT)
|
||||||
.secret("secret")
|
.secret("secret")
|
||||||
.authorizationServicesEnabled(true)
|
.authorizationServicesEnabled(true)
|
||||||
.redirectUris("http://localhost/test-client")
|
.redirectUris("http://localhost/test-client")
|
||||||
|
@ -75,7 +94,12 @@ public class AuthorizationAPITest extends AbstractAuthzTest {
|
||||||
|
|
||||||
@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")
|
||||||
|
.authorizationServicesEnabled(true)
|
||||||
|
.redirectUris("http://localhost/resource-server-test")
|
||||||
|
.defaultRoles("uma_protection")
|
||||||
|
.pairwise("http://pairwise.com")
|
||||||
|
.directAccessGrants())
|
||||||
|
.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")
|
||||||
|
.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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -940,6 +940,8 @@ no-required-actions-configured=No required actions configured
|
||||||
defaults-to-id=Defaults to id
|
defaults-to-id=Defaults to id
|
||||||
flows=Flows
|
flows=Flows
|
||||||
bindings=Bindings
|
bindings=Bindings
|
||||||
|
client-flow-bindings=Authentication Flow Overrides
|
||||||
|
client-flow-bindings.tooltip=Override realm authentication flow bindings.
|
||||||
required-actions=Required Actions
|
required-actions=Required Actions
|
||||||
password-policy=Password Policy
|
password-policy=Password Policy
|
||||||
otp-policy=OTP Policy
|
otp-policy=OTP Policy
|
||||||
|
|
|
@ -1332,6 +1332,9 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
client : function() {
|
client : function() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
flows : function(AuthenticationFlowsLoader) {
|
||||||
|
return AuthenticationFlowsLoader();
|
||||||
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
}
|
}
|
||||||
|
@ -1353,6 +1356,9 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
client : function(ClientLoader) {
|
client : function(ClientLoader) {
|
||||||
return ClientLoader();
|
return ClientLoader();
|
||||||
},
|
},
|
||||||
|
flows : function(AuthenticationFlowsLoader) {
|
||||||
|
return AuthenticationFlowsLoader();
|
||||||
|
},
|
||||||
serverInfo : function(ServerInfoLoader) {
|
serverInfo : function(ServerInfoLoader) {
|
||||||
return ServerInfoLoader();
|
return ServerInfoLoader();
|
||||||
}
|
}
|
||||||
|
|
|
@ -829,7 +829,16 @@ module.controller('ClientInstallationCtrl', function($scope, realm, client, serv
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('ClientDetailCtrl', function($scope, realm, client, templates, $route, serverInfo, Client, ClientDescriptionConverter, Components, ClientStorageOperations, $location, $modal, Dialog, Notifications) {
|
module.controller('ClientDetailCtrl', function($scope, realm, client, templates, flows, $route, serverInfo, Client, ClientDescriptionConverter, Components, ClientStorageOperations, $location, $modal, Dialog, Notifications) {
|
||||||
|
$scope.flows = [];
|
||||||
|
$scope.clientFlows = [];
|
||||||
|
for (var i=0 ; i<flows.length ; i++) {
|
||||||
|
if (flows[i].providerId == 'client-flow') {
|
||||||
|
$scope.clientFlows.push(flows[i]);
|
||||||
|
} else {
|
||||||
|
$scope.flows.push(flows[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -422,6 +422,32 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend collapsed><span class="text">{{:: 'client-flow-bindings' | translate}}</span> <kc-tooltip>{{:: 'client-flow-bindings.tooltip' | translate}}</kc-tooltip></legend>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="browser" class="col-md-2 control-label">{{:: 'browser-flow' | translate}}</label>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div>
|
||||||
|
<select id="browser" data-ng-model="clientEdit.authenticationFlowBindingOverrides['browser']" class="form-control" ng-options="flow.alias as flow.alias for flow in flows">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'browser-flow.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" data-ng-show="protocol == 'openid-connect'">
|
||||||
|
<label for="grant" class="col-md-2 control-label">{{:: 'direct-grant-flow' | translate}}</label>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div>
|
||||||
|
<select id="grant" ng-model="clientEdit.authenticationFlowBindingOverrides['direct_grant']" class="form-control" ng-options="flow.alias as flow.alias for flow in flows">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<kc-tooltip>{{:: 'direct-grant-flow.tooltip' | translate}}</kc-tooltip>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
<div class="col-md-10 col-md-offset-2" data-ng-show="client.access.configure">
|
||||||
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
|
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
|
||||||
|
|
Loading…
Reference in a new issue