Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bill Burke 2018-03-02 18:54:22 -05:00
commit 986f39838c
11 changed files with 273 additions and 53 deletions

View file

@ -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();
}
} }

View file

@ -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);
} }
} }

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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));
}
} }

View file

@ -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);
}
} }

View file

@ -0,0 +1,8 @@
{
"realm": "authz-test",
"auth-server-url" : "http://localhost:8180/auth",
"resource" : "pairwise-resource-server-test",
"credentials": {
"secret": "secret"
}
}

View file

@ -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

View file

@ -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();
} }

View file

@ -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]);
}
}

View file

@ -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>