diff --git a/docbook/reference/en/en-US/modules/kerberos.xml b/docbook/reference/en/en-US/modules/kerberos.xml index 3a858a15bb..d262a1d9db 100644 --- a/docbook/reference/en/en-US/modules/kerberos.xml +++ b/docbook/reference/en/en-US/modules/kerberos.xml @@ -216,7 +216,7 @@ ktadd -k /tmp/http.keytab HTTP/www.mydomain.org@MYDOMAIN.ORG GSS credential will need to be used by your application. So you need to enable built-in gss delegation credential protocol mapper in admin console for your application. This will cause that Keycloak will deserialize GSS credential and transmit it to the application in access token. Application will need to deserialize it and use it for further GSS calls against other services. We have an example, which is showing it in details. It's in examples/kerberos - in the Keycloak appliance distribution or WAR distribution download. You can also check the example sources directly here . + in the Keycloak example distribution or demo distribution download. You can also check the example sources directly here . Once you deserialize the credential from the access token to the GSSCredential object, then GSSContext will need to diff --git a/docbook/reference/en/en-US/modules/user-federation.xml b/docbook/reference/en/en-US/modules/user-federation.xml index c8e9856a3c..58a8727c06 100755 --- a/docbook/reference/en/en-US/modules/user-federation.xml +++ b/docbook/reference/en/en-US/modules/user-federation.xml @@ -208,6 +208,10 @@ more attribute mappings (For example to street, postalCode etc), delete firstName/lastname mapper and put fullName mapper instead, add role mappers etc. Admin console provides tooltips, which should help on how to configure corresponding mappers. + + We have an example, which is showing LDAP integration and set of base mappers and sample mappers (mappers for street and postalCode) . It's in examples/ldap + in the Keycloak example distribution or demo distribution download. You can also check the example sources directly here . +
Writing your own User Federation Provider diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js index f205ab0973..aafb17419c 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js @@ -388,7 +388,7 @@ module.config([ '$routeProvider', function($routeProvider) { controller : 'UserSessionsCtrl' }) .when('/realms/:realm/users/:user/federated-identity', { - templateUrl : resourceUrl + '/partials/user-federated-identity.html', + templateUrl : resourceUrl + '/partials/user-federated-identity-list.html', resolve : { realm : function(RealmLoader) { return RealmLoader(); @@ -402,6 +402,21 @@ module.config([ '$routeProvider', function($routeProvider) { }, controller : 'UserFederatedIdentityCtrl' }) + .when('/create/federated-identity/:realm/:user', { + templateUrl : resourceUrl + '/partials/user-federated-identity-detail.html', + resolve : { + realm : function(RealmLoader) { + return RealmLoader(); + }, + user : function(UserLoader) { + return UserLoader(); + }, + federatedIdentities : function(UserFederatedIdentityLoader) { + return UserFederatedIdentityLoader(); + } + }, + controller : 'UserFederatedIdentityAddCtrl' + }) .when('/realms/:realm/users/:user/consents', { templateUrl : resourceUrl + '/partials/user-consents.html', resolve : { diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js index 93e321bf15..55f6788ff3 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js @@ -129,10 +129,66 @@ module.controller('UserSessionsCtrl', function($scope, realm, user, sessions, Us } }); -module.controller('UserFederatedIdentityCtrl', function($scope, realm, user, federatedIdentities) { +module.controller('UserFederatedIdentityCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications, Dialog) { $scope.realm = realm; $scope.user = user; $scope.federatedIdentities = federatedIdentities; + + $scope.hasAnyProvidersToCreate = function() { + return realm.identityProviders.length - $scope.federatedIdentities.length > 0; + } + + $scope.removeProviderLink = function(providerLink) { + + console.log("Removing provider link: " + providerLink.identityProvider); + + Dialog.confirmDelete(providerLink.identityProvider, 'Identity Provider Link', function() { + UserFederatedIdentity.remove({ realm: realm.realm, user: user.id, provider: providerLink.identityProvider }, function() { + Notifications.success("The provider link has been deleted."); + var indexToRemove = $scope.federatedIdentities.indexOf(providerLink); + $scope.federatedIdentities.splice(indexToRemove, 1); + }); + }); + } +}); + +module.controller('UserFederatedIdentityAddCtrl', function($scope, $location, realm, user, federatedIdentities, UserFederatedIdentity, Notifications) { + $scope.realm = realm; + $scope.user = user; + $scope.federatedIdentity = {}; + + var getAvailableProvidersToCreate = function() { + var realmProviders = []; + for (var i=0 ; i + + +

Add Identity Provider Link

+ + + +
+
+
+ +
+
+ +
+
+
+
+ +
+ +
+ Unique ID of the user on the Identity Provider side +
+
+ +
+ +
+ Username on the Identity Provider side +
+ +
+ +
+ + +
+ +
+ + + \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity-list.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity-list.html new file mode 100644 index 0000000000..dfc8c45cca --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity-list.html @@ -0,0 +1,45 @@ +
+ + +

{{user.username|capitalize}}

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ Create +
+
+
Identity Provider AliasProvider user IDProvider usernameAction
{{identity.identityProvider}}{{identity.userId}}{{identity.userName}} +
+
No identity provider links available
+
+ + \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity.html deleted file mode 100644 index 14d8d67d89..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-federated-identity.html +++ /dev/null @@ -1,27 +0,0 @@ -
- - -

{{user.username|capitalize}}

- - - - - - - - - - - - - - - - -
Identity Provider AliasUsername
{{identity.identityProvider}}{{identity.userName}}
-
- - \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html index 0b0a499c46..caee5c1142 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/templates/kc-tabs-user.html @@ -1,8 +1,8 @@ \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java index b6f1fb179e..0b562786c3 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java @@ -259,14 +259,8 @@ public class UsersResource { UserRepresentation rep = ModelToRepresentation.toRepresentation(user); if (realm.isIdentityFederationEnabled()) { - Set identities = session.users().getFederatedIdentities(user, realm); - if (!identities.isEmpty()) { - List reps = new LinkedList<>(); - for (FederatedIdentityModel m : identities) { - reps.add(ModelToRepresentation.toRepresentation(m)); - } - rep.setFederatedIdentities(reps); - } + List reps = getFederatedIdentities(user); + rep.setFederatedIdentities(reps); } if ((protector != null) && protector.isTemporarilyDisabled(session, realm, rep.getUsername())) { @@ -318,6 +312,10 @@ public class UsersResource { throw new NotFoundException("User not found"); } + return getFederatedIdentities(user); + } + + private List getFederatedIdentities(UserModel user) { Set identities = session.users().getFederatedIdentities(user, realm); List result = new ArrayList(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPExampleServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPExampleServlet.java index a629ddbca8..80bc9f0e84 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPExampleServlet.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPExampleServlet.java @@ -36,17 +36,7 @@ public class LDAPExampleServlet extends HttpServlet { out.println(); for (Map.Entry claim : idToken.getOtherClaims().entrySet()) { - Object value = claim.getValue(); - - if (value instanceof List) { - List asList = (List) value; - StringBuilder result = new StringBuilder(); - for (String item : asList) { - result.append(item + "
"); - } - value = result.toString(); - } - + String value = claim.getValue().toString(); out.printf("%s%s", claim.getKey(), value); out.println(); }