diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js index 62142edd6e..411277602a 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js +++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js @@ -276,6 +276,21 @@ module.config([ '$routeProvider', function($routeProvider) { }, controller : 'ApplicationRoleDetailCtrl' }) + .when('/realms/:realm/applications/:application/claims', { + templateUrl : 'partials/application-claims.html', + resolve : { + realm : function(RealmLoader) { + return RealmLoader(); + }, + application : function(ApplicationLoader) { + return ApplicationLoader(); + }, + claims : function(ApplicationClaimsLoader) { + return ApplicationClaimsLoader(); + } + }, + controller : 'ApplicationClaimsCtrl' + }) .when('/realms/:realm/applications/:application/credentials', { templateUrl : 'partials/application-credentials.html', resolve : { @@ -390,6 +405,21 @@ module.config([ '$routeProvider', function($routeProvider) { // OAUTH Client + .when('/realms/:realm/oauth-clients/:oauth/claims', { + templateUrl : 'partials/oauth-client-claims.html', + resolve : { + realm : function(RealmLoader) { + return RealmLoader(); + }, + oauth : function(OAuthClientLoader) { + return OAuthClientLoader(); + }, + claims : function(OAuthClientClaimsLoader) { + return OAuthClientClaimsLoader(); + } + }, + controller : 'OAuthClientClaimsCtrl' + }) .when('/realms/:realm/oauth-clients/:oauth/credentials', { templateUrl : 'partials/oauth-client-credentials.html', resolve : { diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js index b6be8d0f4f..8bcacd1f62 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js +++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js @@ -44,6 +44,41 @@ module.controller('ApplicationSessionsCtrl', function($scope, $location, realm, $scope.application = application; }); +module.controller('ApplicationClaimsCtrl', function($scope, realm, application, claims, + ApplicationClaims, + $http, $location, Dialog, Notifications) { + $scope.realm = realm; + $scope.application = application; + $scope.claims = angular.copy(claims); + + $scope.changed = false; + + $scope.$watch('claims', function () { + if (!angular.equals($scope.claims, claims)) { + $scope.changed = true; + } + }, true); + + + $scope.save = function () { + ApplicationClaims.update({ + realm: realm.realm, + application: application.name + }, $scope.claims, function () { + $scope.changed = false; + claims = angular.copy($scope.claims); + + Notifications.success("Your claim changes have been saved."); + }); + }; + + $scope.reset = function () { + $location.url("/realms/" + realm.realm + "/applications/" + application.name + "/claims"); + }; + +}); + + module.controller('ApplicationRoleDetailCtrl', function($scope, realm, application, role, roles, applications, Role, ApplicationRole, RoleById, RoleRealmComposites, RoleApplicationComposites, $http, $location, Dialog, Notifications) { diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js index 4998583cae..542d5e18c2 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js +++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js @@ -1,3 +1,37 @@ +module.controller('OAuthClientClaimsCtrl', function($scope, realm, oauth, claims, + OAuthClientClaims, + $location, Dialog, Notifications) { + $scope.realm = realm; + $scope.oauth = oauth; + $scope.claims = angular.copy(claims); + + $scope.changed = false; + + $scope.$watch('claims', function () { + if (!angular.equals($scope.claims, claims)) { + $scope.changed = true; + } + }, true); + + + $scope.save = function () { + OAuthClientClaims.update({ + realm: realm.realm, + oauth: oauth.id + }, $scope.claims, function () { + $scope.changed = false; + claims = angular.copy($scope.claims); + + Notifications.success("Your claim changes have been saved."); + }); + }; + + $scope.reset = function () { + $location.url("/realms/" + realm.realm + "/oauth-clients/" + oauth.id + "/claims"); + }; + +}); + module.controller('OAuthClientCredentialsCtrl', function($scope, $location, realm, oauth, OAuthClientCredentials, Notifications) { $scope.realm = realm; $scope.oauth = oauth; diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js index faf05cd2b9..d5b391772d 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js +++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js @@ -91,6 +91,15 @@ module.factory('ApplicationRoleLoader', function(Loader, ApplicationRole, $route }); }); +module.factory('ApplicationClaimsLoader', function(Loader, ApplicationClaims, $route, $q) { + return Loader.get(ApplicationClaims, function() { + return { + realm : $route.current.params.realm, + application : $route.current.params.application + } + }); +}); + module.factory('ApplicationInstallationLoader', function(Loader, ApplicationInstallation, $route, $q) { return Loader.get(ApplicationInstallation, function() { return { @@ -149,6 +158,16 @@ module.factory('OAuthClientLoader', function(Loader, OAuthClient, $route, $q) { }); }); +module.factory('OAuthClientClaimsLoader', function(Loader, OAuthClientClaims, $route, $q) { + return Loader.get(OAuthClientClaims, function() { + return { + realm : $route.current.params.realm, + oauth : $route.current.params.oauth + } + }); +}); + + module.factory('OAuthClientListLoader', function(Loader, OAuthClient, $route, $q) { return Loader.query(OAuthClient, function() { return { diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js index cd0376f89e..cff788d125 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js +++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js @@ -450,6 +450,16 @@ module.factory('ApplicationRole', function($resource) { } }); }); +module.factory('ApplicationClaims', function($resource) { + return $resource('/auth/rest/admin/realms/:realm/applications/:application/claims', { + realm : '@realm', + application : "@application" + }, { + update : { + method : 'PUT' + } + }); +}); module.factory('Application', function($resource) { @@ -516,6 +526,18 @@ module.factory('OAuthClient', function($resource) { }); }); +module.factory('OAuthClientClaims', function($resource) { + return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/claims', { + realm : '@realm', + oauth : "@oauth" + }, { + update : { + method : 'PUT' + } + }); +}); + + module.factory('OAuthClientCredentials', function($resource) { return $resource('/auth/rest/admin/realms/:realm/oauth-clients/:oauth/client-secret', { realm : '@realm', diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-claims.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-claims.html new file mode 100755 index 0000000000..d20118563f --- /dev/null +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-claims.html @@ -0,0 +1,28 @@ +
+
+ +
+ +

{{application.name}} Allowed Claims

+
+
+
+ + +
+
+
+
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html index a839ccf36a..eda151816c 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html @@ -5,6 +5,7 @@
  • Credentials
  • Installation
  • Roles
  • +
  • Claims
  • Scope
  • Sessions
  • diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html index f123d1c3b5..70491bb186 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html @@ -5,6 +5,7 @@
  • Credentials
  • Installation
  • Roles
  • +
  • Claims
  • Scope
  • Sessions
  • diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-installation.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-installation.html index eeaa134bd4..d6ffd1edae 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-installation.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-installation.html @@ -6,6 +6,7 @@
  • Credentials
  • Installation
  • Roles
  • +
  • Claims
  • Scope
  • Sessions
  • diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html index e103b1296f..3a93fc66e8 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html @@ -5,6 +5,7 @@
  • Credentials
  • Installation
  • Roles
  • +
  • Claims
  • Scope
  • Sessions
  • diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html index 087d11d925..40e8d4d859 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html @@ -6,6 +6,7 @@
  • Credentials
  • Installation
  • Roles
  • +
  • Claims
  • Scope
  • Sessions
  • diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-scope-mappings.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-scope-mappings.html index 865f9d697a..98fa8ea6cc 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-scope-mappings.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-scope-mappings.html @@ -6,6 +6,7 @@
  • Credentials
  • Installation
  • Roles
  • +
  • Claims
  • Scope
  • Sessions
  • diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-sessions.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-sessions.html index 5f110beb7f..432ae2aea1 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-sessions.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-sessions.html @@ -6,6 +6,7 @@
  • Credentials
  • Installation
  • Roles
  • +
  • Claims
  • Scope
  • Sessions
  • diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/claims.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/claims.html new file mode 100755 index 0000000000..2701792167 --- /dev/null +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/claims.html @@ -0,0 +1,62 @@ +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    \ No newline at end of file diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-claims.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-claims.html new file mode 100755 index 0000000000..05bca000dc --- /dev/null +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-claims.html @@ -0,0 +1,20 @@ +
    +
    + +
    +

    {{oauth.name}} Allowed Claims

    +
    +
    +
    + + +
    +
    +
    +
    diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html index f931492e72..08ceee81ef 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html @@ -3,6 +3,7 @@ diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html index 01e18350d5..693041ffb5 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html @@ -3,6 +3,7 @@ diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html index 19afcde9da..14a4c503a2 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html @@ -3,6 +3,7 @@ diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html index 424fab27b2..72c4799b32 100755 --- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html +++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html @@ -4,6 +4,7 @@ diff --git a/core/src/main/java/org/keycloak/KeycloakAuthenticatedSession.java b/core/src/main/java/org/keycloak/KeycloakAuthenticatedSession.java index 658e19adff..6593f2dbcf 100755 --- a/core/src/main/java/org/keycloak/KeycloakAuthenticatedSession.java +++ b/core/src/main/java/org/keycloak/KeycloakAuthenticatedSession.java @@ -2,6 +2,7 @@ package org.keycloak; import org.keycloak.adapters.ResourceMetadata; import org.keycloak.representations.AccessToken; +import org.keycloak.representations.IDToken; import java.io.Serializable; @@ -12,14 +13,18 @@ import java.io.Serializable; public class KeycloakAuthenticatedSession implements Serializable { protected String tokenString; protected AccessToken token; + protected IDToken idToken; + protected String idTokenString; protected transient ResourceMetadata metadata; public KeycloakAuthenticatedSession() { } - public KeycloakAuthenticatedSession(String tokenString, AccessToken token, ResourceMetadata metadata) { + public KeycloakAuthenticatedSession(String tokenString, AccessToken token, String idTokenString, IDToken idToken, ResourceMetadata metadata) { this.tokenString = tokenString; this.token = token; + this.idToken = idToken; + this.idTokenString = idTokenString; this.metadata = metadata; } @@ -38,4 +43,12 @@ public class KeycloakAuthenticatedSession implements Serializable { public void setMetadata(ResourceMetadata metadata) { this.metadata = metadata; } + + public IDToken getIdToken() { + return idToken; + } + + public String getIdTokenString() { + return idTokenString; + } } diff --git a/core/src/main/java/org/keycloak/representations/AccessToken.java b/core/src/main/java/org/keycloak/representations/AccessToken.java index c99a509a3a..7f55dd9dff 100755 --- a/core/src/main/java/org/keycloak/representations/AccessToken.java +++ b/core/src/main/java/org/keycloak/representations/AccessToken.java @@ -12,7 +12,7 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public class AccessToken extends JsonWebToken { +public class AccessToken extends IDToken { public static class Access { @JsonProperty("roles") protected Set roles; diff --git a/core/src/main/java/org/keycloak/representations/AccessTokenResponse.java b/core/src/main/java/org/keycloak/representations/AccessTokenResponse.java index 985dae4aa4..2ed50812ca 100755 --- a/core/src/main/java/org/keycloak/representations/AccessTokenResponse.java +++ b/core/src/main/java/org/keycloak/representations/AccessTokenResponse.java @@ -21,6 +21,9 @@ public class AccessTokenResponse { @JsonProperty("token_type") protected String tokenType; + @JsonProperty("id_token") + protected String idToken; + public String getToken() { return token; } @@ -52,4 +55,12 @@ public class AccessTokenResponse { public void setTokenType(String tokenType) { this.tokenType = tokenType; } + + public String getIdToken() { + return idToken; + } + + public void setIdToken(String idToken) { + this.idToken = idToken; + } } diff --git a/core/src/main/java/org/keycloak/representations/IDToken.java b/core/src/main/java/org/keycloak/representations/IDToken.java new file mode 100755 index 0000000000..08514a9fa3 --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/IDToken.java @@ -0,0 +1,306 @@ +package org.keycloak.representations; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class IDToken extends JsonWebToken { + @JsonProperty("nonce") + protected String nonce; + + @JsonProperty("name") + protected String name; + + @JsonProperty("given_name") + protected String givenName; + + @JsonProperty("family_name") + protected String familyName; + + @JsonProperty("middle_name") + protected String middleName; + + @JsonProperty("nickname") + protected String nickName; + + @JsonProperty("preferred_username") + protected String preferredUsername; + + @JsonProperty("profile") + protected String profile; + + @JsonProperty("picture") + protected String picture; + + @JsonProperty("website") + protected String website; + + @JsonProperty("email") + protected String email; + + @JsonProperty("email_verified") + protected Boolean emailVerified; + + @JsonProperty("gender") + protected String gender; + + @JsonProperty("birthdate") + protected String birthdate; + + @JsonProperty("zoneinfo") + protected String zoneinfo; + + @JsonProperty("locale") + protected String locale; + + @JsonProperty("phone_number") + protected String phoneNumber; + + @JsonProperty("phone_number_verified") + protected Boolean phoneNumberVerified; + + @JsonProperty("address") + protected String address; + + @JsonProperty("updated_at") + protected Long updatedAt; + + @JsonProperty("formatted") + protected String formattedAddress; + + @JsonProperty("street_address") + protected String streetAddress; + + @JsonProperty("locality") + protected String locality; + + @JsonProperty("region") + protected String region; + + @JsonProperty("postal_code") + protected String postalCode; + + @JsonProperty("country") + protected String country; + + @JsonProperty("claims_locales") + protected String claimsLocales; + + public String getNonce() { + return nonce; + } + + public void setNonce(String nonce) { + this.nonce = nonce; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGivenName() { + return givenName; + } + + public void setGivenName(String givenName) { + this.givenName = givenName; + } + + public String getFamilyName() { + return familyName; + } + + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getPreferredUsername() { + return preferredUsername; + } + + public void setPreferredUsername(String preferredUsername) { + this.preferredUsername = preferredUsername; + } + + public String getProfile() { + return profile; + } + + public void setProfile(String profile) { + this.profile = profile; + } + + public String getPicture() { + return picture; + } + + public void setPicture(String picture) { + this.picture = picture; + } + + public String getWebsite() { + return website; + } + + public void setWebsite(String website) { + this.website = website; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Boolean getEmailVerified() { + return emailVerified; + } + + public void setEmailVerified(Boolean emailVerified) { + this.emailVerified = emailVerified; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getBirthdate() { + return birthdate; + } + + public void setBirthdate(String birthdate) { + this.birthdate = birthdate; + } + + public String getZoneinfo() { + return zoneinfo; + } + + public void setZoneinfo(String zoneinfo) { + this.zoneinfo = zoneinfo; + } + + public String getLocale() { + return locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public Boolean getPhoneNumberVerified() { + return phoneNumberVerified; + } + + public void setPhoneNumberVerified(Boolean phoneNumberVerified) { + this.phoneNumberVerified = phoneNumberVerified; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Long getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Long updatedAt) { + this.updatedAt = updatedAt; + } + + public String getFormattedAddress() { + return formattedAddress; + } + + public void setFormattedAddress(String formattedAddress) { + this.formattedAddress = formattedAddress; + } + + public String getStreetAddress() { + return streetAddress; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } + + public String getLocality() { + return locality; + } + + public void setLocality(String locality) { + this.locality = locality; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getPostalCode() { + return postalCode; + } + + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getClaimsLocales() { + return claimsLocales; + } + + public void setClaimsLocales(String claimsLocales) { + this.claimsLocales = claimsLocales; + } +} diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java index 5cb4a1d240..601bce52e8 100755 --- a/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationRepresentation.java @@ -18,6 +18,7 @@ public class ApplicationRepresentation { protected String[] defaultRoles; protected List redirectUris; protected List webOrigins; + protected ClaimRepresentation claims; public String getId() { return id; @@ -107,4 +108,12 @@ public class ApplicationRepresentation { public void setDefaultRoles(String[] defaultRoles) { this.defaultRoles = defaultRoles; } + + public ClaimRepresentation getClaims() { + return claims; + } + + public void setClaims(ClaimRepresentation claims) { + this.claims = claims; + } } diff --git a/core/src/main/java/org/keycloak/representations/idm/ClaimRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClaimRepresentation.java new file mode 100755 index 0000000000..1783d89239 --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/idm/ClaimRepresentation.java @@ -0,0 +1,98 @@ +package org.keycloak.representations.idm; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClaimRepresentation { + protected boolean name; + protected boolean username; + protected boolean profile; + protected boolean picture; + protected boolean website; + protected boolean email; + protected boolean gender; + protected boolean locale; + protected boolean address; + protected boolean phone; + + public boolean getName() { + return name; + } + + public void setName(boolean name) { + this.name = name; + } + + public boolean getUsername() { + return username; + } + + public void setUsername(boolean username) { + this.username = username; + } + + public boolean getProfile() { + return profile; + } + + public void setProfile(boolean profile) { + this.profile = profile; + } + + public boolean getPicture() { + return picture; + } + + public void setPicture(boolean picture) { + this.picture = picture; + } + + public boolean getWebsite() { + return website; + } + + public void setWebsite(boolean website) { + this.website = website; + } + + public boolean getEmail() { + return email; + } + + public void setEmail(boolean email) { + this.email = email; + } + + public boolean getGender() { + return gender; + } + + public void setGender(boolean gender) { + this.gender = gender; + } + + public boolean getLocale() { + return locale; + } + + public void setLocale(boolean locale) { + this.locale = locale; + } + + public boolean getAddress() { + return address; + } + + public void setAddress(boolean address) { + this.address = address; + } + + public boolean getPhone() { + return phone; + } + + public void setPhone(boolean phone) { + this.phone = phone; + } +} diff --git a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java index be44c4344a..cfd33dd9b1 100755 --- a/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/OAuthClientRepresentation.java @@ -14,6 +14,7 @@ public class OAuthClientRepresentation { protected List webOrigins; protected boolean enabled; protected List credentials; + protected ClaimRepresentation claims; public String getId() { return id; @@ -70,4 +71,12 @@ public class OAuthClientRepresentation { public void setCredentials(List credentials) { this.credentials = credentials; } + + public ClaimRepresentation getClaims() { + return claims; + } + + public void setClaims(ClaimRepresentation claims) { + this.claims = claims; + } } diff --git a/docbook/reference/en/en-US/modules/Overview.xml b/docbook/reference/en/en-US/modules/Overview.xml index bdd3b2b9e9..3910cea1aa 100755 --- a/docbook/reference/en/en-US/modules/Overview.xml +++ b/docbook/reference/en/en-US/modules/Overview.xml @@ -31,6 +31,10 @@ Password and TOTP support (via Google Authenticator). Client cert auth coming soon. + + Pluggable theme and style support for user facing screens. + + OAuth Bearer token auth for REST Services @@ -60,7 +64,7 @@ Deployable as a WAR, appliance, or on Openshift. - Supports JBoss AS7, EAP 6.x, and Wildfly applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java application + Supports JBoss AS7, EAP 6.x, and Wildfly applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java deployments diff --git a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java index 196579da59..16b6a9623a 100755 --- a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java +++ b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java @@ -6,6 +6,7 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.keycloak.KeycloakAuthenticatedSession; import org.keycloak.adapters.HttpClientBuilder; +import org.keycloak.representations.IDToken; import org.keycloak.util.JsonSerialization; import javax.servlet.http.HttpServletRequest; @@ -35,6 +36,12 @@ public class CustomerDatabaseClient { } } + public static IDToken getIDToken(HttpServletRequest req) { + KeycloakAuthenticatedSession session = (KeycloakAuthenticatedSession) req.getAttribute(KeycloakAuthenticatedSession.class.getName()); + return session.getIdToken(); + + } + public static List getCustomers(HttpServletRequest req) throws Failure { KeycloakAuthenticatedSession session = (KeycloakAuthenticatedSession) req.getAttribute(KeycloakAuthenticatedSession.class.getName()); diff --git a/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp b/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp index 0e9ab0ed84..f966321212 100755 --- a/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp +++ b/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp @@ -2,6 +2,7 @@ pageEncoding="ISO-8859-1" %> <%@ page import="org.keycloak.example.CustomerDatabaseClient" %> <%@ page import="org.keycloak.util.KeycloakUriBuilder" %> +<%@ page import="org.keycloak.representations.IDToken" %> Customer View Page @@ -11,11 +12,18 @@ String logoutUri = KeycloakUriBuilder.fromUri("http://localhost:8080/auth/rest/realms/demo/tokens/logout") .queryParam("redirect_uri", "http://localhost:8080/customer-portal").build().toString(); String acctUri = "http://localhost:8080/auth/rest/realms/demo/account"; + IDToken idToken = CustomerDatabaseClient.getIDToken(request); %>

    Goto: products | logout | manage acct

    -User <%=request.getUserPrincipal().getName()%> +Servlet User Principal <%=request.getUserPrincipal().getName()%> made this request. +

    Caller IDToken values (You can specify what is returned in IDToken in the customer-portal claims page in the admin console:

    +

    Username: <%=idToken.getPreferredUsername()%>

    +

    Email: <%=idToken.getEmail()%>

    +

    Full Name: <%=idToken.getName()%>

    +

    First: <%=idToken.getGivenName()%>

    +

    Last: <%=idToken.getFamilyName()%>

    Customer Listing

    <% java.util.List list = null; diff --git a/forms/login-api/src/main/java/org/keycloak/login/LoginForms.java b/forms/login-api/src/main/java/org/keycloak/login/LoginForms.java old mode 100644 new mode 100755 index 3cce80c972..9f91751c00 --- a/forms/login-api/src/main/java/org/keycloak/login/LoginForms.java +++ b/forms/login-api/src/main/java/org/keycloak/login/LoginForms.java @@ -1,47 +1,47 @@ -package org.keycloak.login; - -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserModel; - -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import java.util.List; - -/** - * @author Stian Thorgersen - */ -public interface LoginForms { - - public Response createResponse(UserModel.RequiredAction action); - - public Response createLogin(); - - public Response createPasswordReset(); - - public Response createLoginTotp(); - - public Response createRegistration(); - - public Response createErrorPage(); - - public Response createOAuthGrant(); - - public LoginForms setAccessCode(String accessCodeId, String accessCode); - - public LoginForms setAccessRequest(List realmRolesRequested, MultivaluedMap resourceRolesRequested); - - public LoginForms setError(String message); - - public LoginForms setSuccess(String message); - - public LoginForms setWarning(String message); - - public LoginForms setUser(UserModel user); - - public LoginForms setClient(UserModel client); - - public LoginForms setFormData(MultivaluedMap formData); - - public LoginForms setStatus(Response.Status status); - -} +package org.keycloak.login; + +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserModel; + +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import java.util.List; + +/** + * @author Stian Thorgersen + */ +public interface LoginForms { + + public Response createResponse(UserModel.RequiredAction action); + + public Response createLogin(); + + public Response createPasswordReset(); + + public Response createLoginTotp(); + + public Response createRegistration(); + + public Response createErrorPage(); + + public Response createOAuthGrant(); + + public LoginForms setAccessCode(String accessCodeId, String accessCode); + + public LoginForms setAccessRequest(List realmRolesRequested, MultivaluedMap resourceRolesRequested); + + public LoginForms setError(String message); + + public LoginForms setSuccess(String message); + + public LoginForms setWarning(String message); + + public LoginForms setUser(UserModel user); + + public LoginForms setClient(UserModel client); + + public LoginForms setFormData(MultivaluedMap formData); + + public LoginForms setStatus(Response.Status status); + +} diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginForms.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginForms.java old mode 100644 new mode 100755 index 30b15faf2e..95f005b9f2 --- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginForms.java +++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/FreeMarkerLoginForms.java @@ -1,273 +1,273 @@ -package org.keycloak.login.freemarker; - -import org.jboss.logging.Logger; -import org.jboss.resteasy.spi.HttpRequest; -import org.keycloak.freemarker.FreeMarkerException; -import org.keycloak.freemarker.FreeMarkerUtil; -import org.keycloak.freemarker.Theme; -import org.keycloak.freemarker.ThemeLoader; -import org.keycloak.login.LoginForms; -import org.keycloak.login.LoginFormsPages; -import org.keycloak.login.freemarker.model.LoginBean; -import org.keycloak.login.freemarker.model.MessageBean; -import org.keycloak.login.freemarker.model.OAuthGrantBean; -import org.keycloak.login.freemarker.model.ProfileBean; -import org.keycloak.login.freemarker.model.RealmBean; -import org.keycloak.login.freemarker.model.RegisterBean; -import org.keycloak.login.freemarker.model.SocialBean; -import org.keycloak.login.freemarker.model.TotpBean; -import org.keycloak.login.freemarker.model.UrlBean; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserModel; -import org.keycloak.services.email.EmailException; -import org.keycloak.services.email.EmailSender; -import org.keycloak.services.messages.Messages; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; -import java.io.IOException; -import java.net.URI; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * @author Stian Thorgersen - */ -public class FreeMarkerLoginForms implements LoginForms { - - private static final Logger logger = Logger.getLogger(FreeMarkerLoginForms.class); - - private String message; - private String accessCodeId; - private String accessCode; - private Response.Status status = Response.Status.OK; - private List realmRolesRequested; - private MultivaluedMap resourceRolesRequested; - - public static enum MessageType {SUCCESS, WARNING, ERROR} - - private MessageType messageType = MessageType.ERROR; - - private MultivaluedMap formData; - - private RealmModel realm; - - // TODO Remove - private HttpRequest request; - - private UserModel user; - - private UserModel client; - - private UriInfo uriInfo; - - FreeMarkerLoginForms(RealmModel realm, org.jboss.resteasy.spi.HttpRequest request, UriInfo uriInfo) { - this.realm = realm; - this.request = request; - this.uriInfo = uriInfo; - } - - public Response createResponse(UserModel.RequiredAction action) { - String actionMessage; - LoginFormsPages page; - - switch (action) { - case CONFIGURE_TOTP: - actionMessage = Messages.ACTION_WARN_TOTP; - page = LoginFormsPages.LOGIN_CONFIG_TOTP; - break; - case UPDATE_PROFILE: - actionMessage = Messages.ACTION_WARN_PROFILE; - page = LoginFormsPages.LOGIN_UPDATE_PROFILE; - break; - case UPDATE_PASSWORD: - actionMessage = Messages.ACTION_WARN_PASSWD; - page = LoginFormsPages.LOGIN_UPDATE_PASSWORD; - break; - case VERIFY_EMAIL: - try { - new EmailSender(realm.getSmtpConfig()).sendEmailVerification(user, realm, accessCodeId, uriInfo); - } catch (EmailException e) { - return setError("emailSendError").createErrorPage(); - } - - actionMessage = Messages.ACTION_WARN_EMAIL; - page = LoginFormsPages.LOGIN_VERIFY_EMAIL; - break; - default: - return Response.serverError().build(); - } - - if (message == null) { - setWarning(actionMessage); - } - - return createResponse(page); - } - - private Response createResponse(LoginFormsPages page) { - MultivaluedMap queryParameterMap = uriInfo.getQueryParameters(); - - String requestURI = uriInfo.getBaseUri().getPath(); - UriBuilder uriBuilder = UriBuilder.fromUri(requestURI); - - for (String k : queryParameterMap.keySet()) { - uriBuilder.replaceQueryParam(k, queryParameterMap.get(k).toArray()); - } - - if (accessCode != null) { - uriBuilder.replaceQueryParam("code", accessCode); - } - - Map attributes = new HashMap(); - - Theme theme; - try { - theme = ThemeLoader.createTheme(realm.getLoginTheme(), Theme.Type.LOGIN); - } catch (FreeMarkerException e) { - logger.error("Failed to create theme", e); - return Response.serverError().build(); - } - - try { - attributes.put("properties", theme.getProperties()); - } catch (IOException e) { - logger.warn("Failed to load properties", e); - } - - Properties messages; - try { - messages = theme.getMessages(); - attributes.put("rb", messages); - } catch (IOException e) { - logger.warn("Failed to load messages", e); - messages = new Properties(); - } - - if (message != null) { - attributes.put("message", new MessageBean(messages.containsKey(message) ? messages.getProperty(message) : message, messageType)); - } - - URI baseUri = uriBuilder.build(); - - if (realm != null) { - attributes.put("realm", new RealmBean(realm)); - attributes.put("social", new SocialBean(realm, baseUri)); - attributes.put("url", new UrlBean(realm, theme, baseUri)); - } - - attributes.put("login", new LoginBean(formData)); - - switch (page) { - case LOGIN_CONFIG_TOTP: - attributes.put("totp", new TotpBean(user, baseUri)); - break; - case LOGIN_UPDATE_PROFILE: - attributes.put("user", new ProfileBean(user)); - break; - case REGISTER: - attributes.put("register", new RegisterBean(formData)); - break; - case OAUTH_GRANT: - attributes.put("oauth", new OAuthGrantBean(accessCode, client, realmRolesRequested, resourceRolesRequested)); - break; - } - - try { - String result = FreeMarkerUtil.processTemplate(attributes, Templates.getTemplate(page), theme); - return Response.status(status).type(MediaType.TEXT_HTML).entity(result).build(); - } catch (FreeMarkerException e) { - logger.error("Failed to process template", e); - return Response.serverError().build(); - } - } - - public Response createLogin() { - return createResponse(LoginFormsPages.LOGIN); - } - - public Response createPasswordReset() { - return createResponse(LoginFormsPages.LOGIN_RESET_PASSWORD); - } - - public Response createUsernameReminder() { - return createResponse(LoginFormsPages.LOGIN_USERNAME_REMINDER); - } - - public Response createLoginTotp() { - return createResponse(LoginFormsPages.LOGIN_TOTP); - } - - public Response createRegistration() { - return createResponse(LoginFormsPages.REGISTER); - } - - public Response createErrorPage() { - setStatus(Response.Status.INTERNAL_SERVER_ERROR); - return createResponse(LoginFormsPages.ERROR); - } - - public Response createOAuthGrant() { - return createResponse(LoginFormsPages.OAUTH_GRANT); - } - - public FreeMarkerLoginForms setError(String message) { - this.message = message; - this.messageType = MessageType.ERROR; - return this; - } - - public FreeMarkerLoginForms setSuccess(String message) { - this.message = message; - this.messageType = MessageType.SUCCESS; - return this; - } - - public FreeMarkerLoginForms setWarning(String message) { - this.message = message; - this.messageType = MessageType.WARNING; - return this; - } - - public FreeMarkerLoginForms setUser(UserModel user) { - this.user = user; - return this; - } - - public FreeMarkerLoginForms setClient(UserModel client) { - this.client = client; - return this; - } - - public FreeMarkerLoginForms setFormData(MultivaluedMap formData) { - this.formData = formData; - return this; - } - - @Override - public LoginForms setAccessCode(String accessCodeId, String accessCode) { - this.accessCodeId = accessCodeId; - this.accessCode = accessCode; - return this; - } - - @Override - public LoginForms setAccessRequest(List realmRolesRequested, MultivaluedMap resourceRolesRequested) { - this.realmRolesRequested = realmRolesRequested; - this.resourceRolesRequested = resourceRolesRequested; - return this; - } - - @Override - public LoginForms setStatus(Response.Status status) { - this.status = status; - return this; - } - -} +package org.keycloak.login.freemarker; + +import org.jboss.logging.Logger; +import org.jboss.resteasy.spi.HttpRequest; +import org.keycloak.freemarker.FreeMarkerException; +import org.keycloak.freemarker.FreeMarkerUtil; +import org.keycloak.freemarker.Theme; +import org.keycloak.freemarker.ThemeLoader; +import org.keycloak.login.LoginForms; +import org.keycloak.login.LoginFormsPages; +import org.keycloak.login.freemarker.model.LoginBean; +import org.keycloak.login.freemarker.model.MessageBean; +import org.keycloak.login.freemarker.model.OAuthGrantBean; +import org.keycloak.login.freemarker.model.ProfileBean; +import org.keycloak.login.freemarker.model.RealmBean; +import org.keycloak.login.freemarker.model.RegisterBean; +import org.keycloak.login.freemarker.model.SocialBean; +import org.keycloak.login.freemarker.model.TotpBean; +import org.keycloak.login.freemarker.model.UrlBean; +import org.keycloak.models.RealmModel; +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserModel; +import org.keycloak.services.email.EmailException; +import org.keycloak.services.email.EmailSender; +import org.keycloak.services.messages.Messages; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * @author Stian Thorgersen + */ +public class FreeMarkerLoginForms implements LoginForms { + + private static final Logger logger = Logger.getLogger(FreeMarkerLoginForms.class); + + private String message; + private String accessCodeId; + private String accessCode; + private Response.Status status = Response.Status.OK; + private List realmRolesRequested; + private MultivaluedMap resourceRolesRequested; + + public static enum MessageType {SUCCESS, WARNING, ERROR} + + private MessageType messageType = MessageType.ERROR; + + private MultivaluedMap formData; + + private RealmModel realm; + + // TODO Remove + private HttpRequest request; + + private UserModel user; + + private UserModel client; + + private UriInfo uriInfo; + + FreeMarkerLoginForms(RealmModel realm, org.jboss.resteasy.spi.HttpRequest request, UriInfo uriInfo) { + this.realm = realm; + this.request = request; + this.uriInfo = uriInfo; + } + + public Response createResponse(UserModel.RequiredAction action) { + String actionMessage; + LoginFormsPages page; + + switch (action) { + case CONFIGURE_TOTP: + actionMessage = Messages.ACTION_WARN_TOTP; + page = LoginFormsPages.LOGIN_CONFIG_TOTP; + break; + case UPDATE_PROFILE: + actionMessage = Messages.ACTION_WARN_PROFILE; + page = LoginFormsPages.LOGIN_UPDATE_PROFILE; + break; + case UPDATE_PASSWORD: + actionMessage = Messages.ACTION_WARN_PASSWD; + page = LoginFormsPages.LOGIN_UPDATE_PASSWORD; + break; + case VERIFY_EMAIL: + try { + new EmailSender(realm.getSmtpConfig()).sendEmailVerification(user, realm, accessCodeId, uriInfo); + } catch (EmailException e) { + return setError("emailSendError").createErrorPage(); + } + + actionMessage = Messages.ACTION_WARN_EMAIL; + page = LoginFormsPages.LOGIN_VERIFY_EMAIL; + break; + default: + return Response.serverError().build(); + } + + if (message == null) { + setWarning(actionMessage); + } + + return createResponse(page); + } + + private Response createResponse(LoginFormsPages page) { + MultivaluedMap queryParameterMap = uriInfo.getQueryParameters(); + + String requestURI = uriInfo.getBaseUri().getPath(); + UriBuilder uriBuilder = UriBuilder.fromUri(requestURI); + + for (String k : queryParameterMap.keySet()) { + uriBuilder.replaceQueryParam(k, queryParameterMap.get(k).toArray()); + } + + if (accessCode != null) { + uriBuilder.replaceQueryParam("code", accessCode); + } + + Map attributes = new HashMap(); + + Theme theme; + try { + theme = ThemeLoader.createTheme(realm.getLoginTheme(), Theme.Type.LOGIN); + } catch (FreeMarkerException e) { + logger.error("Failed to create theme", e); + return Response.serverError().build(); + } + + try { + attributes.put("properties", theme.getProperties()); + } catch (IOException e) { + logger.warn("Failed to load properties", e); + } + + Properties messages; + try { + messages = theme.getMessages(); + attributes.put("rb", messages); + } catch (IOException e) { + logger.warn("Failed to load messages", e); + messages = new Properties(); + } + + if (message != null) { + attributes.put("message", new MessageBean(messages.containsKey(message) ? messages.getProperty(message) : message, messageType)); + } + + URI baseUri = uriBuilder.build(); + + if (realm != null) { + attributes.put("realm", new RealmBean(realm)); + attributes.put("social", new SocialBean(realm, baseUri)); + attributes.put("url", new UrlBean(realm, theme, baseUri)); + } + + attributes.put("login", new LoginBean(formData)); + + switch (page) { + case LOGIN_CONFIG_TOTP: + attributes.put("totp", new TotpBean(user, baseUri)); + break; + case LOGIN_UPDATE_PROFILE: + attributes.put("user", new ProfileBean(user)); + break; + case REGISTER: + attributes.put("register", new RegisterBean(formData)); + break; + case OAUTH_GRANT: + attributes.put("oauth", new OAuthGrantBean(accessCode, client, realmRolesRequested, resourceRolesRequested)); + break; + } + + try { + String result = FreeMarkerUtil.processTemplate(attributes, Templates.getTemplate(page), theme); + return Response.status(status).type(MediaType.TEXT_HTML).entity(result).build(); + } catch (FreeMarkerException e) { + logger.error("Failed to process template", e); + return Response.serverError().build(); + } + } + + public Response createLogin() { + return createResponse(LoginFormsPages.LOGIN); + } + + public Response createPasswordReset() { + return createResponse(LoginFormsPages.LOGIN_RESET_PASSWORD); + } + + public Response createUsernameReminder() { + return createResponse(LoginFormsPages.LOGIN_USERNAME_REMINDER); + } + + public Response createLoginTotp() { + return createResponse(LoginFormsPages.LOGIN_TOTP); + } + + public Response createRegistration() { + return createResponse(LoginFormsPages.REGISTER); + } + + public Response createErrorPage() { + setStatus(Response.Status.INTERNAL_SERVER_ERROR); + return createResponse(LoginFormsPages.ERROR); + } + + public Response createOAuthGrant() { + return createResponse(LoginFormsPages.OAUTH_GRANT); + } + + public FreeMarkerLoginForms setError(String message) { + this.message = message; + this.messageType = MessageType.ERROR; + return this; + } + + public FreeMarkerLoginForms setSuccess(String message) { + this.message = message; + this.messageType = MessageType.SUCCESS; + return this; + } + + public FreeMarkerLoginForms setWarning(String message) { + this.message = message; + this.messageType = MessageType.WARNING; + return this; + } + + public FreeMarkerLoginForms setUser(UserModel user) { + this.user = user; + return this; + } + + public FreeMarkerLoginForms setClient(UserModel client) { + this.client = client; + return this; + } + + public FreeMarkerLoginForms setFormData(MultivaluedMap formData) { + this.formData = formData; + return this; + } + + @Override + public LoginForms setAccessCode(String accessCodeId, String accessCode) { + this.accessCodeId = accessCodeId; + this.accessCode = accessCode; + return this; + } + + @Override + public LoginForms setAccessRequest(List realmRolesRequested, MultivaluedMap resourceRolesRequested) { + this.realmRolesRequested = realmRolesRequested; + this.resourceRolesRequested = resourceRolesRequested; + return this; + } + + @Override + public LoginForms setStatus(Response.Status status) { + this.status = status; + return this; + } + +} diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java index 4c04f12a48..d18dde5ccf 100755 --- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java +++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java @@ -1,66 +1,66 @@ -/* - * JBoss, Home of Professional Open Source. - * Copyright 2012, Red Hat, Inc., and individual contributors - * as indicated by the @author tags. See the copyright.txt file in the - * distribution for a full listing of individual contributors. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.keycloak.login.freemarker.model; - -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserModel; - -import javax.ws.rs.core.MultivaluedMap; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Viliam Rockai - */ -public class OAuthGrantBean { - - private List realmRolesRequested; - private MultivaluedMap resourceRolesRequested; - private String code; - private UserModel client; - private String oAuthCode; - private String action; - - public OAuthGrantBean(String code, UserModel client, List realmRolesRequested, MultivaluedMap resourceRolesRequested) { - this.code = code; - this.client = client; - this.realmRolesRequested = realmRolesRequested; - this.resourceRolesRequested = resourceRolesRequested; - } - - public String getCode() { - return code; - } - - public MultivaluedMap getResourceRolesRequested() { - return resourceRolesRequested; - } - - public List getRealmRolesRequested() { - return realmRolesRequested; - } - - public String getClient() { - return client.getLoginName(); - } - -} +/* + * JBoss, Home of Professional Open Source. + * Copyright 2012, Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.keycloak.login.freemarker.model; + +import org.keycloak.models.RoleModel; +import org.keycloak.models.UserModel; + +import javax.ws.rs.core.MultivaluedMap; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Viliam Rockai + */ +public class OAuthGrantBean { + + private List realmRolesRequested; + private MultivaluedMap resourceRolesRequested; + private String code; + private UserModel client; + private String oAuthCode; + private String action; + + public OAuthGrantBean(String code, UserModel client, List realmRolesRequested, MultivaluedMap resourceRolesRequested) { + this.code = code; + this.client = client; + this.realmRolesRequested = realmRolesRequested; + this.resourceRolesRequested = resourceRolesRequested; + } + + public String getCode() { + return code; + } + + public MultivaluedMap getResourceRolesRequested() { + return resourceRolesRequested; + } + + public List getRealmRolesRequested() { + return realmRolesRequested; + } + + public String getClient() { + return client.getLoginName(); + } + +} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java index 8716e0ef5c..7e14a79d1b 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java @@ -7,6 +7,7 @@ import org.keycloak.adapters.config.RealmConfiguration; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; import org.jboss.logging.Logger; +import org.keycloak.representations.IDToken; import java.io.IOException; @@ -24,8 +25,8 @@ public class RefreshableKeycloakSession extends KeycloakAuthenticatedSession { public RefreshableKeycloakSession() { } - public RefreshableKeycloakSession(String tokenString, AccessToken token, ResourceMetadata metadata, RealmConfiguration realmConfiguration, String refreshToken) { - super(tokenString, token, metadata); + public RefreshableKeycloakSession(String tokenString, AccessToken token, String idTokenString, IDToken idToken, ResourceMetadata metadata, RealmConfiguration realmConfiguration, String refreshToken) { + super(tokenString, token, idTokenString, idToken, metadata); this.realmConfiguration = realmConfiguration; this.refreshToken = refreshToken; } diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java index 86933f06de..93be4f4951 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java @@ -106,7 +106,7 @@ public class CatalinaBearerTokenAuthenticator { principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles); request.setUserPrincipal(principal); request.setAuthType("OAUTH_BEARER"); - KeycloakAuthenticatedSession skSession = new KeycloakAuthenticatedSession(tokenString, token, resourceMetadata); + KeycloakAuthenticatedSession skSession = new KeycloakAuthenticatedSession(tokenString, token, null, null, resourceMetadata); request.setAttribute(KeycloakAuthenticatedSession.class.getName(), skSession); return true; diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java index 430b3bd506..b6e8af9028 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java @@ -262,7 +262,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif Session session = request.getSessionInternal(true); session.setPrincipal(principal); session.setAuthType("OAUTH"); - KeycloakAuthenticatedSession skSession = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), resourceMetadata, realmConfiguration, oauth.getRefreshToken()); + KeycloakAuthenticatedSession skSession = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), resourceMetadata, realmConfiguration, oauth.getRefreshToken()); session.setNote(KeycloakAuthenticatedSession.class.getName(), skSession); String username = token.getSubject(); diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java index 35cb609396..1cec19f407 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java @@ -5,8 +5,10 @@ import org.keycloak.RSATokenVerifier; import org.keycloak.VerificationException; import org.keycloak.adapters.TokenGrantRequest; import org.keycloak.adapters.config.RealmConfiguration; +import org.keycloak.jose.jws.JWSInput; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; +import org.keycloak.representations.IDToken; import org.keycloak.util.KeycloakUriBuilder; import javax.servlet.http.Cookie; @@ -28,6 +30,8 @@ public class ServletOAuthLogin { protected RealmConfiguration realmInfo; protected int redirectPort; protected String tokenString; + protected String idTokenString; + protected IDToken idToken; protected AccessToken token; protected String refreshToken; @@ -50,6 +54,14 @@ public class ServletOAuthLogin { return refreshToken; } + public String getIdTokenString() { + return idTokenString; + } + + public IDToken getIdToken() { + return idToken; + } + public RealmConfiguration getRealmInfo() { return realmInfo; } @@ -246,8 +258,17 @@ public class ServletOAuthLogin { } tokenString = tokenResponse.getToken(); + idTokenString = tokenResponse.getIdToken(); try { token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata().getRealmKey(), realmInfo.getMetadata().getRealm()); + if (idTokenString != null) { + JWSInput input = new JWSInput(idTokenString); + try { + idToken = input.readJsonContent(IDToken.class); + } catch (IOException e) { + throw new VerificationException(); + } + } log.debug("Token Verification succeeded!"); } catch (VerificationException e) { log.error("failed verification of token"); diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java index 6e226365cc..88d29c404f 100755 --- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java +++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java @@ -67,7 +67,7 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter { try { AccessToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm()); - KeycloakAuthenticatedSession skSession = new KeycloakAuthenticatedSession(tokenString, token, resourceMetadata); + KeycloakAuthenticatedSession skSession = new KeycloakAuthenticatedSession(tokenString, token, null, null, resourceMetadata); ResteasyProviderFactory.pushContext(KeycloakAuthenticatedSession.class, skSession); String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null; diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java index 5b9ef86d34..ffa950561a 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java @@ -94,7 +94,7 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism protected void completeAuthentication(HttpServerExchange exchange, SecurityContext securityContext, OAuthAuthenticator oauth) { final KeycloakPrincipal principal = new KeycloakPrincipal(oauth.getToken().getSubject(), null); - RefreshableKeycloakSession session = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), resourceMetadata, realmConfig, oauth.getRefreshToken()); + RefreshableKeycloakSession session = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), resourceMetadata, realmConfig, oauth.getRefreshToken()); KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, adapterConfig, resourceMetadata); securityContext.authenticationComplete(account, "KEYCLOAK", true); login(exchange, account); @@ -107,7 +107,7 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism protected void completeAuthentication(SecurityContext securityContext, BearerTokenAuthenticator bearer) { final KeycloakPrincipal principal = new KeycloakPrincipal(bearer.getToken().getSubject(), bearer.getSurrogate()); - RefreshableKeycloakSession session = new RefreshableKeycloakSession(bearer.getTokenString(), bearer.getToken(), resourceMetadata, realmConfig, null); + RefreshableKeycloakSession session = new RefreshableKeycloakSession(bearer.getTokenString(), bearer.getToken(), null, null, resourceMetadata, realmConfig, null); KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, adapterConfig, resourceMetadata); securityContext.authenticationComplete(account, "KEYCLOAK", false); } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java index d21e5d3ed6..29bb28a00d 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java @@ -12,8 +12,10 @@ import org.keycloak.RSATokenVerifier; import org.keycloak.adapters.config.RealmConfiguration; import org.keycloak.VerificationException; import org.keycloak.adapters.TokenGrantRequest; +import org.keycloak.jose.jws.JWSInput; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; +import org.keycloak.representations.IDToken; import org.keycloak.util.KeycloakUriBuilder; import java.io.IOException; @@ -31,6 +33,8 @@ public class OAuthAuthenticator { protected RealmConfiguration realmInfo; protected int sslRedirectPort; protected String tokenString; + protected String idTokenString; + protected IDToken idToken; protected AccessToken token; protected HttpServerExchange exchange; protected KeycloakChallenge challenge; @@ -58,6 +62,22 @@ public class OAuthAuthenticator { return refreshToken; } + public String getIdTokenString() { + return idTokenString; + } + + public void setIdTokenString(String idTokenString) { + this.idTokenString = idTokenString; + } + + public IDToken getIdToken() { + return idToken; + } + + public void setIdToken(IDToken idToken) { + this.idToken = idToken; + } + protected String getRequestUrl() { KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(exchange.getRequestURI()) .replaceQuery(exchange.getQueryString()); @@ -255,8 +275,17 @@ public class OAuthAuthenticator { tokenString = tokenResponse.getToken(); refreshToken = tokenResponse.getRefreshToken(); + idTokenString = tokenResponse.getIdToken(); try { token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata().getRealmKey(), realmInfo.getMetadata().getRealm()); + if (idTokenString != null) { + JWSInput input = new JWSInput(idTokenString); + try { + idToken = input.readJsonContent(IDToken.class); + } catch (IOException e) { + throw new VerificationException(); + } + } log.debug("Token Verification succeeded!"); } catch (VerificationException e) { log.error("failed verification of token"); diff --git a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java index 46576448c9..6247cdca34 100755 --- a/model/api/src/main/java/org/keycloak/models/ApplicationModel.java +++ b/model/api/src/main/java/org/keycloak/models/ApplicationModel.java @@ -7,13 +7,9 @@ import java.util.Set; * @author Bill Burke * @version $Revision: 1 $ */ -public interface ApplicationModel extends RoleContainerModel { +public interface ApplicationModel extends RoleContainerModel, ClientModel { void updateApplication(); - UserModel getApplicationUser(); - - String getId(); - String getName(); void setName(String name); @@ -45,4 +41,5 @@ public interface ApplicationModel extends RoleContainerModel { Set getApplicationScopeMappings(UserModel user); void addScope(RoleModel role); + } diff --git a/model/api/src/main/java/org/keycloak/models/ClaimMask.java b/model/api/src/main/java/org/keycloak/models/ClaimMask.java new file mode 100755 index 0000000000..7d4334c9ac --- /dev/null +++ b/model/api/src/main/java/org/keycloak/models/ClaimMask.java @@ -0,0 +1,50 @@ +package org.keycloak.models; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClaimMask { + public static final long NAME = 0x01l; + public static final long USERNAME = 0x02l; + public static final long PROFILE = 0x04l; + public static final long PICTURE = 0x08l; + public static final long WEBSITE = 0x10l; + public static final long EMAIL = 0x20l; + public static final long GENDER = 0x40l; + public static final long LOCALE = 0x80l; + public static final long ADDRESS = 0x100l; + public static final long PHONE = 0x200l; + + public static boolean hasName(long mask) { + return (mask & NAME) > 0; + } + public static boolean hasUsername(long mask) { + return (mask & USERNAME) > 0; + } + public static boolean hasProfile(long mask) { + return (mask & PROFILE) > 0; + } + public static boolean hasPicture(long mask) { + return (mask & PICTURE) > 0; + } + public static boolean hasWebsite(long mask) { + return (mask & WEBSITE) > 0; + } + public static boolean hasEmail(long mask) { + return (mask & EMAIL) > 0; + } + public static boolean hasGender(long mask) { + return (mask & GENDER) > 0; + } + public static boolean hasLocale(long mask) { + return (mask & LOCALE) > 0; + } + public static boolean hasAddress(long mask) { + return (mask & ADDRESS) > 0; + } + public static boolean hasPhone(long mask) { + return (mask & PHONE) > 0; + } + +} diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java new file mode 100755 index 0000000000..ab38dd3c53 --- /dev/null +++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java @@ -0,0 +1,15 @@ +package org.keycloak.models; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public interface ClientModel { + long getAllowedClaimsMask(); + + void setAllowedClaimsMask(long mask); + + UserModel getAgent(); + + String getId(); +} diff --git a/model/api/src/main/java/org/keycloak/models/OAuthClientModel.java b/model/api/src/main/java/org/keycloak/models/OAuthClientModel.java index 622500c588..e5e828416c 100755 --- a/model/api/src/main/java/org/keycloak/models/OAuthClientModel.java +++ b/model/api/src/main/java/org/keycloak/models/OAuthClientModel.java @@ -4,8 +4,6 @@ package org.keycloak.models; * @author Bill Burke * @version $Revision: 1 $ */ -public interface OAuthClientModel { - String getId(); +public interface OAuthClientModel extends ClientModel { - UserModel getOAuthAgent(); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java index 9c25a3813f..3b43464656 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java @@ -6,17 +6,13 @@ import org.keycloak.models.RoleContainerModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; import org.keycloak.models.jpa.entities.*; -import org.keycloak.representations.idm.ApplicationMappingsRepresentation; -import org.keycloak.representations.idm.RoleRepresentation; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -41,7 +37,7 @@ public class ApplicationAdapter implements ApplicationModel { } @Override - public UserModel getApplicationUser() { + public UserModel getAgent() { return new UserAdapter(application.getApplicationUser()); } @@ -70,6 +66,16 @@ public class ApplicationAdapter implements ApplicationModel { application.setEnabled(enabled); } + @Override + public long getAllowedClaimsMask() { + return application.getAllowedClaimsMask(); + } + + @Override + public void setAllowedClaimsMask(long mask) { + application.setAllowedClaimsMask(mask); + } + @Override public boolean isSurrogateAuthRequired() { return application.isSurrogateAuthRequired(); @@ -266,7 +272,7 @@ public class ApplicationAdapter implements ApplicationModel { @Override public void addScope(RoleModel role) { - realm.addScopeMapping(getApplicationUser(), role); + realm.addScopeMapping(getAgent(), role); } public boolean equals(Object o) { diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java index fd2afcc487..6bb62ccacb 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java @@ -25,8 +25,19 @@ public class OAuthClientAdapter implements OAuthClientModel { } @Override - public UserModel getOAuthAgent() { + public UserModel getAgent() { return new UserAdapter(entity.getAgent()); } + @Override + public long getAllowedClaimsMask() { + return entity.getAllowedClaimsMask(); + } + + @Override + public void setAllowedClaimsMask(long mask) { + entity.setAllowedClaimsMask(mask); + } + + } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java index 19a59817db..b85f720f7b 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ApplicationEntity.java @@ -30,6 +30,7 @@ public class ApplicationEntity { private boolean surrogateAuthRequired; private String baseUrl; private String managementUrl; + private long allowedClaimsMask; @OneToOne(fetch = FetchType.EAGER) private UserEntity applicationUser; @@ -119,4 +120,12 @@ public class ApplicationEntity { public void setRealm(RealmEntity realm) { this.realm = realm; } + + public long getAllowedClaimsMask() { + return allowedClaimsMask; + } + + public void setAllowedClaimsMask(long allowedClaimsMask) { + this.allowedClaimsMask = allowedClaimsMask; + } } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java index d266ed7502..9a114a1795 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/OAuthClientEntity.java @@ -28,6 +28,7 @@ public class OAuthClientEntity { private String id; private String name; + private long allowedClaimsMask; @OneToOne(fetch = FetchType.EAGER) private UserEntity agent; @@ -62,4 +63,13 @@ public class OAuthClientEntity { public void setRealm(RealmEntity realm) { this.realm = realm; } + + public long getAllowedClaimsMask() { + return allowedClaimsMask; + } + + public void setAllowedClaimsMask(long allowedClaimsMask) { + this.allowedClaimsMask = allowedClaimsMask; + } + } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java index 80835f2b7e..a0da211452 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java @@ -41,7 +41,7 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo } @Override - public UserAdapter getApplicationUser() { + public UserAdapter getAgent() { // This is not thread-safe. Assumption is that ApplicationAdapter instance is per-client object if (resourceUser == null) { UserEntity userEntity = getMongoStore().loadEntity(UserEntity.class, application.getResourceUserId(), invocationContext); @@ -109,6 +109,17 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo return application.getBaseUrl(); } + @Override + public long getAllowedClaimsMask() { + return application.getAllowedClaimsMask(); + } + + @Override + public void setAllowedClaimsMask(long mask) { + application.setAllowedClaimsMask(mask); + } + + @Override public RoleAdapter getRole(String name) { DBObject query = new QueryBuilder() @@ -185,7 +196,7 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo @Override public void addScope(RoleModel role) { - UserAdapter appUser = getApplicationUser(); + UserAdapter appUser = getAgent(); getMongoStore().pushItemToList(appUser.getUser(), "scopeIds", role.getId(), true, invocationContext); } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java index 2eacc45165..ea48f9154b 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java @@ -31,7 +31,17 @@ public class OAuthClientAdapter extends AbstractAdapter implements OAuthClientMo } @Override - public UserModel getOAuthAgent() { + public long getAllowedClaimsMask() { + return delegate.getAllowedClaimsMask(); + } + + @Override + public void setAllowedClaimsMask(long mask) { + delegate.setAllowedClaimsMask(mask); + } + + @Override + public UserModel getAgent() { // This is not thread-safe. Assumption is that OAuthClientAdapter instance is per-client object if (oauthAgent == null) { UserEntity user = getMongoStore().loadEntity(UserEntity.class, delegate.getOauthAgentId(), invocationContext); diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java old mode 100644 new mode 100755 index 39a62346a1..2a03171993 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/ApplicationEntity.java @@ -25,6 +25,7 @@ public class ApplicationEntity extends AbstractMongoIdentifiableEntity implement private String resourceUserId; private String realmId; + private long allowedClaimsMask; // We are using names of defaultRoles (not ids) private List defaultRoles = new ArrayList(); @@ -83,6 +84,15 @@ public class ApplicationEntity extends AbstractMongoIdentifiableEntity implement this.resourceUserId = resourceUserId; } + @MongoField + public long getAllowedClaimsMask() { + return allowedClaimsMask; + } + + public void setAllowedClaimsMask(long allowedClaimsMask) { + this.allowedClaimsMask = allowedClaimsMask; + } + @MongoField public String getRealmId() { return realmId; diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java old mode 100644 new mode 100755 index f2875b1be0..78c3687f7f --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/OAuthClientEntity.java @@ -16,6 +16,7 @@ public class OAuthClientEntity extends AbstractMongoIdentifiableEntity implement private String oauthAgentId; private String realmId; + private long allowedClaimsMask; @MongoField public String getName() { @@ -44,6 +45,15 @@ public class OAuthClientEntity extends AbstractMongoIdentifiableEntity implement this.realmId = realmId; } + @MongoField + public long getAllowedClaimsMask() { + return allowedClaimsMask; + } + + public void setAllowedClaimsMask(long allowedClaimsMask) { + this.allowedClaimsMask = allowedClaimsMask; + } + @Override public void afterRemove(MongoStoreInvocationContext context) { // Remove user of this oauthClient diff --git a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java index 8aa12f9b19..eb119d547c 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/AdapterTest.java @@ -1,7 +1,6 @@ package org.keycloak.model.test; import org.junit.Assert; -import org.junit.Before; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; @@ -15,7 +14,6 @@ import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.managers.ApplianceBootstrap; import org.keycloak.services.managers.OAuthClientManager; import org.keycloak.services.managers.RealmManager; @@ -141,7 +139,7 @@ public class AdapterTest extends AbstractModelTest { OAuthClientModel oauth = new OAuthClientManager(realmModel).create("oauth-client"); oauth = realmModel.getOAuthClient("oauth-client"); - Assert.assertTrue(realmModel.hasRole(oauth.getOAuthAgent(), realmModel.getRole(Constants.IDENTITY_REQUESTER_ROLE))); + Assert.assertTrue(realmModel.hasRole(oauth.getAgent(), realmModel.getRole(Constants.IDENTITY_REQUESTER_ROLE))); } @@ -186,10 +184,10 @@ public class AdapterTest extends AbstractModelTest { RoleModel appRole = app.addRole("test"); realmModel.grantRole(user, appRole); - realmModel.addScopeMapping(client.getOAuthAgent(), appRole); + realmModel.addScopeMapping(client.getAgent(), appRole); RoleModel realmRole = realmModel.addRole("test"); - realmModel.addScopeMapping(app.getApplicationUser(), realmRole); + realmModel.addScopeMapping(app.getAgent(), realmRole); Assert.assertTrue(realmModel.removeApplication(app.getId())); Assert.assertFalse(realmModel.removeApplication(app.getId())); @@ -214,10 +212,10 @@ public class AdapterTest extends AbstractModelTest { RoleModel appRole = app.addRole("test"); realmModel.grantRole(user, appRole); - realmModel.addScopeMapping(client.getOAuthAgent(), appRole); + realmModel.addScopeMapping(client.getAgent(), appRole); RoleModel realmRole = realmModel.addRole("test"); - realmModel.addScopeMapping(app.getApplicationUser(), realmRole); + realmModel.addScopeMapping(app.getAgent(), realmRole); Assert.assertTrue(identitySession.removeRealm(realmModel.getId())); Assert.assertFalse(identitySession.removeRealm(realmModel.getId())); @@ -237,10 +235,10 @@ public class AdapterTest extends AbstractModelTest { RoleModel appRole = app.addRole("test"); realmModel.grantRole(user, appRole); - realmModel.addScopeMapping(client.getOAuthAgent(), appRole); + realmModel.addScopeMapping(client.getAgent(), appRole); RoleModel realmRole = realmModel.addRole("test"); - realmModel.addScopeMapping(app.getApplicationUser(), realmRole); + realmModel.addScopeMapping(app.getAgent(), realmRole); Assert.assertTrue(realmModel.removeRoleById(realmRole.getId())); Assert.assertFalse(realmModel.removeRoleById(realmRole.getId())); diff --git a/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java index 3cac5782e9..942aab901e 100755 --- a/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/ApplicationModelTest.java @@ -37,11 +37,11 @@ public class ApplicationModelTest extends AbstractModelTest { application.addDefaultRole("role-1"); application.addDefaultRole("role-2"); - application.getApplicationUser().addRedirectUri("redirect-1"); - application.getApplicationUser().addRedirectUri("redirect-2"); + application.getAgent().addRedirectUri("redirect-1"); + application.getAgent().addRedirectUri("redirect-2"); - application.getApplicationUser().addWebOrigin("origin-1"); - application.getApplicationUser().addWebOrigin("origin-2"); + application.getAgent().addWebOrigin("origin-1"); + application.getAgent().addWebOrigin("origin-2"); application.updateApplication(); } @@ -69,8 +69,8 @@ public class ApplicationModelTest extends AbstractModelTest { Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl()); Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles()); - UserModel auser = actual.getApplicationUser(); - UserModel euser = expected.getApplicationUser(); + UserModel auser = actual.getAgent(); + UserModel euser = expected.getAgent(); Assert.assertTrue(euser.getRedirectUris().containsAll(auser.getRedirectUris())); Assert.assertTrue(euser.getWebOrigins().containsAll(auser.getWebOrigins())); diff --git a/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java b/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java old mode 100644 new mode 100755 index ec14411199..c0ec969328 --- a/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java +++ b/model/tests/src/test/java/org/keycloak/model/test/CompositeRolesModelTest.java @@ -60,7 +60,7 @@ public class CompositeRolesModelTest extends AbstractModelTest { ApplicationModel application = realm.getApplicationByName(applicationName); Set roleMappings = realm.getRoleMappings(user); - Set scopeMappings = realm.getScopeMappings(application.getApplicationUser()); + Set scopeMappings = realm.getScopeMappings(application.getAgent()); Set appRoles = application.getRoles(); if (appRoles != null) scopeMappings.addAll(appRoles); diff --git a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java index 55642a2f63..3bbd8e49f9 100755 --- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java @@ -4,6 +4,7 @@ import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; import org.jboss.resteasy.logging.Logger; import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClaimMask; import org.keycloak.models.Constants; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -57,7 +58,7 @@ public class ApplicationManager { applicationModel.setBaseUrl(resourceRep.getBaseUrl()); applicationModel.updateApplication(); - UserModel resourceUser = applicationModel.getApplicationUser(); + UserModel resourceUser = applicationModel.getAgent(); if (resourceRep.getCredentials() != null && resourceRep.getCredentials().size() > 0) { for (CredentialRepresentation cred : resourceRep.getCredentials()) { UserCredentialModel credential = new UserCredentialModel(); @@ -89,6 +90,12 @@ public class ApplicationManager { applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles()); } + if (resourceRep.getClaims() != null) { + ClaimManager.setClaims(applicationModel, resourceRep.getClaims()); + } else { + applicationModel.setAllowedClaimsMask(ClaimMask.USERNAME); + } + return applicationModel; } @@ -129,7 +136,7 @@ public class ApplicationManager { public ApplicationModel createApplication(RealmModel realm, String name) { RoleModel loginRole = realm.getRole(Constants.APPLICATION_ROLE); ApplicationModel app = realm.addApplication(name); - realm.grantRole(app.getApplicationUser(), loginRole); + realm.grantRole(app.getAgent(), loginRole); generateSecret(realm, app); return app; @@ -137,7 +144,7 @@ public class ApplicationManager { public UserCredentialModel generateSecret(RealmModel realm, ApplicationModel app) { UserCredentialModel secret = UserCredentialModel.generateSecret(); - realm.updateCredential(app.getApplicationUser(), secret); + realm.updateCredential(app.getAgent(), secret); return secret; } @@ -155,12 +162,16 @@ public class ApplicationManager { List redirectUris = rep.getRedirectUris(); if (redirectUris != null) { - resource.getApplicationUser().setRedirectUris(new HashSet(redirectUris)); + resource.getAgent().setRedirectUris(new HashSet(redirectUris)); } List webOrigins = rep.getWebOrigins(); if (webOrigins != null) { - resource.getApplicationUser().setWebOrigins(new HashSet(webOrigins)); + resource.getAgent().setWebOrigins(new HashSet(webOrigins)); + } + + if (rep.getClaims() != null) { + ClaimManager.setClaims(resource, rep.getClaims()); } } @@ -173,12 +184,12 @@ public class ApplicationManager { rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired()); rep.setBaseUrl(applicationModel.getBaseUrl()); - Set redirectUris = applicationModel.getApplicationUser().getRedirectUris(); + Set redirectUris = applicationModel.getAgent().getRedirectUris(); if (redirectUris != null) { rep.setRedirectUris(new LinkedList(redirectUris)); } - Set webOrigins = applicationModel.getApplicationUser().getWebOrigins(); + Set webOrigins = applicationModel.getAgent().getWebOrigins(); if (webOrigins != null) { rep.setWebOrigins(new LinkedList(webOrigins)); } @@ -240,7 +251,7 @@ public class ApplicationManager { rep.setResource(applicationModel.getName()); Map creds = new HashMap(); - String cred = realmModel.getSecret(applicationModel.getApplicationUser()).getValue(); + String cred = realmModel.getSecret(applicationModel.getAgent()).getValue(); creds.put(CredentialRepresentation.SECRET, cred); rep.setCredentials(creds); @@ -255,7 +266,7 @@ public class ApplicationManager { buffer.append(" ").append(baseUri.toString()).append("\n"); buffer.append(" ").append(realmModel.isSslNotRequired()).append("\n"); buffer.append(" ").append(applicationModel.getName()).append("\n"); - String cred = realmModel.getSecret(applicationModel.getApplicationUser()).getValue(); + String cred = realmModel.getSecret(applicationModel.getAgent()).getValue(); buffer.append(" ").append(cred).append("\n"); buffer.append("\n"); return buffer.toString(); diff --git a/services/src/main/java/org/keycloak/services/managers/ClaimManager.java b/services/src/main/java/org/keycloak/services/managers/ClaimManager.java new file mode 100755 index 0000000000..af1ab62d41 --- /dev/null +++ b/services/src/main/java/org/keycloak/services/managers/ClaimManager.java @@ -0,0 +1,66 @@ +package org.keycloak.services.managers; + +import org.keycloak.models.ClaimMask; +import org.keycloak.models.ClientModel; +import org.keycloak.representations.idm.ClaimRepresentation; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClaimManager { + public static void setClaims(ClientModel model, ClaimRepresentation rep) { + long mask = model.getAllowedClaimsMask(); + if (rep.getAddress()) { + mask |= ClaimMask.ADDRESS; + } else { + mask &= ~ClaimMask.ADDRESS; + } + if (rep.getEmail()) { + mask |= ClaimMask.EMAIL; + } else { + mask &= ~ClaimMask.EMAIL; + } + if (rep.getGender()) { + mask |= ClaimMask.GENDER; + } else { + mask &= ~ClaimMask.GENDER; + } + if (rep.getLocale()) { + mask |= ClaimMask.LOCALE; + } else { + mask &= ~ClaimMask.LOCALE; + } + if (rep.getName()) { + mask |= ClaimMask.NAME; + } else { + mask &= ~ClaimMask.NAME; + } + if (rep.getPhone()) { + mask |= ClaimMask.PHONE; + } else { + mask &= ~ClaimMask.PHONE; + } + if (rep.getPicture()) { + mask |= ClaimMask.PICTURE; + } else { + mask &= ~ClaimMask.PICTURE; + } + if (rep.getProfile()) { + mask |= ClaimMask.PROFILE; + } else { + mask &= ~ClaimMask.PROFILE; + } + if (rep.getUsername()) { + mask |= ClaimMask.USERNAME; + } else { + mask &= ~ClaimMask.USERNAME; + } + if (rep.getWebsite()) { + mask |= ClaimMask.WEBSITE; + } else { + mask &= ~ClaimMask.WEBSITE; + } + model.setAllowedClaimsMask(mask); + } +} diff --git a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java index 303cd94172..a83cf9e7bd 100755 --- a/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java +++ b/services/src/main/java/org/keycloak/services/managers/ModelToRepresentation.java @@ -1,12 +1,15 @@ package org.keycloak.services.managers; import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClaimMask; +import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; +import org.keycloak.representations.idm.ClaimRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; @@ -110,4 +113,19 @@ public class ModelToRepresentation { rep.setValue(cred.getValue()); return rep; } + + public static ClaimRepresentation toRepresentation(ClientModel model) { + ClaimRepresentation rep = new ClaimRepresentation(); + rep.setAddress(ClaimMask.hasAddress(model.getAllowedClaimsMask())); + rep.setEmail(ClaimMask.hasEmail(model.getAllowedClaimsMask())); + rep.setGender(ClaimMask.hasGender(model.getAllowedClaimsMask())); + rep.setLocale(ClaimMask.hasLocale(model.getAllowedClaimsMask())); + rep.setName(ClaimMask.hasName(model.getAllowedClaimsMask())); + rep.setPhone(ClaimMask.hasPhone(model.getAllowedClaimsMask())); + rep.setPicture(ClaimMask.hasPicture(model.getAllowedClaimsMask())); + rep.setProfile(ClaimMask.hasProfile(model.getAllowedClaimsMask())); + rep.setWebsite(ClaimMask.hasWebsite(model.getAllowedClaimsMask())); + rep.setUsername(ClaimMask.hasUsername(model.getAllowedClaimsMask())); + return rep; + } } diff --git a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java index 5426755552..500bbadec1 100755 --- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java +++ b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java @@ -2,18 +2,16 @@ package org.keycloak.services.managers; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonPropertyOrder; -import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClaimMask; import org.keycloak.models.Constants; import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; -import org.keycloak.representations.adapters.config.BaseAdapterConfig; import org.keycloak.representations.adapters.config.BaseRealmConfig; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.OAuthClientRepresentation; -import org.keycloak.services.resources.flows.Urls; import java.net.URI; import java.util.HashMap; @@ -36,7 +34,7 @@ public class OAuthClientManager { public UserCredentialModel generateSecret(RealmModel realm, OAuthClientModel app) { UserCredentialModel secret = UserCredentialModel.generateSecret(); - realm.updateCredential(app.getOAuthAgent(), secret); + realm.updateCredential(app.getAgent(), secret); return secret; } @@ -44,7 +42,7 @@ public class OAuthClientManager { public OAuthClientModel create(String name) { OAuthClientModel model = realm.addOAuthClient(name); RoleModel role = realm.getRole(Constants.IDENTITY_REQUESTER_ROLE); - realm.grantRole(model.getOAuthAgent(), role); + realm.grantRole(model.getAgent(), role); generateSecret(realm, model); return model; } @@ -52,7 +50,7 @@ public class OAuthClientManager { public OAuthClientModel create(OAuthClientRepresentation rep) { OAuthClientModel model = create(rep.getName()); update(rep, model); - UserModel resourceUser = model.getOAuthAgent(); + UserModel resourceUser = model.getAgent(); if (rep.getCredentials() != null) { for (CredentialRepresentation cred : rep.getCredentials()) { UserCredentialModel credential = new UserCredentialModel(); @@ -61,33 +59,43 @@ public class OAuthClientManager { realm.updateCredential(resourceUser, credential); } } + if (rep.getClaims() != null) { + ClaimManager.setClaims(model, rep.getClaims()); + } else { + model.setAllowedClaimsMask(ClaimMask.USERNAME); + } + return model; } public void update(OAuthClientRepresentation rep, OAuthClientModel model) { - model.getOAuthAgent().setEnabled(rep.isEnabled()); + model.getAgent().setEnabled(rep.isEnabled()); List redirectUris = rep.getRedirectUris(); if (redirectUris != null) { - model.getOAuthAgent().setRedirectUris(new HashSet(redirectUris)); + model.getAgent().setRedirectUris(new HashSet(redirectUris)); } List webOrigins = rep.getWebOrigins(); if (webOrigins != null) { - model.getOAuthAgent().setWebOrigins(new HashSet(webOrigins)); + model.getAgent().setWebOrigins(new HashSet(webOrigins)); + } + + if (rep.getClaims() != null) { + ClaimManager.setClaims(model, rep.getClaims()); } } public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) { OAuthClientRepresentation rep = new OAuthClientRepresentation(); rep.setId(model.getId()); - rep.setName(model.getOAuthAgent().getLoginName()); - rep.setEnabled(model.getOAuthAgent().isEnabled()); - Set redirectUris = model.getOAuthAgent().getRedirectUris(); + rep.setName(model.getAgent().getLoginName()); + rep.setEnabled(model.getAgent().isEnabled()); + Set redirectUris = model.getAgent().getRedirectUris(); if (redirectUris != null) { rep.setRedirectUris(new LinkedList(redirectUris)); } - Set webOrigins = model.getOAuthAgent().getWebOrigins(); + Set webOrigins = model.getAgent().getWebOrigins(); if (webOrigins != null) { rep.setWebOrigins(new LinkedList(webOrigins)); } @@ -127,10 +135,10 @@ public class OAuthClientManager { rep.setSslNotRequired(realmModel.isSslNotRequired()); rep.setAuthServerUrl(baseUri.toString()); - rep.setResource(model.getOAuthAgent().getLoginName()); + rep.setResource(model.getAgent().getLoginName()); Map creds = new HashMap(); - creds.put(CredentialRepresentation.SECRET, realmModel.getSecret(model.getOAuthAgent()).getValue()); + creds.put(CredentialRepresentation.SECRET, realmModel.getSecret(model.getAgent()).getValue()); rep.setCredentials(creds); return rep; diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index ca71051399..0ee5c389aa 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -255,7 +255,7 @@ public class RealmManager { if (rep.getApplications() != null) { Map appMap = createApplications(rep, newRealm); for (ApplicationModel app : appMap.values()) { - userMap.put(app.getApplicationUser().getLoginName(), app.getApplicationUser()); + userMap.put(app.getAgent().getLoginName(), app.getAgent()); } } @@ -308,7 +308,7 @@ public class RealmManager { if (rep.getOauthClients() != null) { Map oauthMap = createOAuthClients(rep, newRealm); for (OAuthClientModel app : oauthMap.values()) { - userMap.put(app.getOAuthAgent().getLoginName(), app.getOAuthAgent()); + userMap.put(app.getAgent().getLoginName(), app.getAgent()); } } @@ -501,7 +501,7 @@ public class RealmManager { OAuthClientManager manager = new OAuthClientManager(realm); for (OAuthClientRepresentation rep : realmRep.getOauthClients()) { OAuthClientModel app = manager.create(rep); - appMap.put(app.getOAuthAgent().getLoginName(), app); + appMap.put(app.getAgent().getLoginName(), app); } return appMap; } diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java index 080d52f8d7..93b7c5daae 100755 --- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java +++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java @@ -6,6 +6,8 @@ import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.models.ApplicationModel; +import org.keycloak.models.ClaimMask; +import org.keycloak.models.ClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; @@ -13,6 +15,7 @@ import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.AccessScope; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; +import org.keycloak.representations.IDToken; import org.keycloak.representations.RefreshToken; import org.keycloak.util.Base64Url; import org.keycloak.util.JsonSerialization; @@ -21,7 +24,6 @@ import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.security.PrivateKey; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -178,7 +180,9 @@ public class TokenManager { } } - AccessToken accessToken = initToken(realm, client, user); + ClientModel claimRequesterModel = getClaimRequester(realm, client); + + AccessToken accessToken = initToken(realm, claimRequesterModel, client, user); accessToken.setRealmAccess(refreshToken.getRealmAccess()); accessToken.setResourceAccess(refreshToken.getResourceAccess()); return accessToken; @@ -188,6 +192,12 @@ public class TokenManager { return createClientAccessToken(scopeParam, realm, client, user, new LinkedList(), new MultivaluedHashMap()); } + protected ClientModel getClaimRequester(RealmModel realm, UserModel client) { + ClientModel model = realm.getApplicationByName(client.getLoginName()); + if (model != null) return model; + return realm.getOAuthClient(client.getLoginName()); + } + public AccessToken createClientAccessToken(String scopeParam, RealmModel realm, UserModel client, UserModel user, List realmRolesRequested, MultivaluedMap resourceRolesRequested) { AccessScope scopeMap = null; @@ -196,6 +206,7 @@ public class TokenManager { Set roleMappings = realm.getRoleMappings(user); Set scopeMappings = realm.getScopeMappings(client); + ClientModel claimRequesterModel = getClaimRequester(realm, client); ApplicationModel clientApp = realm.getApplicationByName(client.getLoginName()); Set clientAppRoles = clientApp == null ? null : clientApp.getRoles(); if (clientAppRoles != null) scopeMappings.addAll(clientAppRoles); @@ -222,7 +233,7 @@ public class TokenManager { } } - AccessToken token = initToken(realm, client, user); + AccessToken token = initToken(realm, claimRequesterModel, client, user); if (realmRolesRequested.size() > 0) { for (RoleModel role : realmRolesRequested) { @@ -240,7 +251,42 @@ public class TokenManager { return token; } - protected AccessToken initToken(RealmModel realm, UserModel client, UserModel user) { + public void initClaims(IDToken token, ClientModel model, UserModel user) { + if (ClaimMask.hasUsername(model.getAllowedClaimsMask())) { + token.setPreferredUsername(user.getLoginName()); + } + if (ClaimMask.hasEmail(model.getAllowedClaimsMask())) { + token.setEmail(user.getEmail()); + token.setEmailVerified(user.isEmailVerified()); + } + if (ClaimMask.hasName(model.getAllowedClaimsMask())) { + token.setFamilyName(user.getLastName()); + token.setGivenName(user.getFirstName()); + StringBuilder fullName = new StringBuilder(); + if (user.getFirstName() != null) fullName.append(user.getFirstName()).append(" "); + if (user.getLastName() != null) fullName.append(user.getLastName()); + token.setName(fullName.toString()); + } + } + + protected IDToken initIDToken(RealmModel realm, ClientModel claimer, UserModel client, UserModel user) { + IDToken token = new IDToken(); + token.id(KeycloakModelUtils.generateId()); + token.subject(user.getId()); + token.audience(realm.getName()); + token.issuedNow(); + token.issuedFor(client.getLoginName()); + token.issuer(realm.getName()); + if (realm.getAccessTokenLifespan() > 0) { + token.expiration((System.currentTimeMillis() / 1000) + realm.getAccessTokenLifespan()); + } + initClaims(token, claimer, user); + return token; + } + + + + protected AccessToken initToken(RealmModel realm, ClientModel claimer, UserModel client, UserModel user) { AccessToken token = new AccessToken(); token.id(KeycloakModelUtils.generateId()); token.subject(user.getId()); @@ -250,12 +296,12 @@ public class TokenManager { token.issuer(realm.getName()); if (realm.getAccessTokenLifespan() > 0) { token.expiration((System.currentTimeMillis() / 1000) + realm.getAccessTokenLifespan()); - logger.info("Access Token expiration: " + token.getExpiration()); } Set allowedOrigins = client.getWebOrigins(); if (allowedOrigins != null) { token.setAllowedOrigins(allowedOrigins); } + initClaims(token, claimer, user); return token; } @@ -324,6 +370,7 @@ public class TokenManager { RealmModel realm; AccessToken accessToken; RefreshToken refreshToken; + IDToken idToken; public AccessTokenResponseBuilder(RealmModel realm) { this.realm = realm; @@ -354,8 +401,53 @@ public class TokenManager { return this; } + public AccessTokenResponseBuilder generateIDToken() { + if (accessToken == null) { + throw new IllegalStateException("accessToken not set"); + } + idToken = new IDToken(); + idToken.id(KeycloakModelUtils.generateId()); + idToken.subject(accessToken.getSubject()); + idToken.audience(realm.getName()); + idToken.issuedNow(); + idToken.issuedFor(accessToken.getIssuedFor()); + idToken.issuer(accessToken.getIssuer()); + if (realm.getAccessTokenLifespan() > 0) { + idToken.expiration((System.currentTimeMillis() / 1000) + realm.getAccessTokenLifespan()); + } + idToken.setPreferredUsername(accessToken.getPreferredUsername()); + idToken.setGivenName(accessToken.getGivenName()); + idToken.setMiddleName(accessToken.getMiddleName()); + idToken.setFamilyName(accessToken.getFamilyName()); + idToken.setName(accessToken.getName()); + idToken.setNickName(accessToken.getNickName()); + idToken.setGender(accessToken.getGender()); + idToken.setPicture(accessToken.getPicture()); + idToken.setProfile(accessToken.getProfile()); + idToken.setWebsite(accessToken.getWebsite()); + idToken.setBirthdate(accessToken.getBirthdate()); + idToken.setEmail(accessToken.getEmail()); + idToken.setEmailVerified(accessToken.getEmailVerified()); + idToken.setLocale(accessToken.getLocale()); + idToken.setFormattedAddress(accessToken.getFormattedAddress()); + idToken.setAddress(accessToken.getAddress()); + idToken.setStreetAddress(accessToken.getStreetAddress()); + idToken.setLocality(accessToken.getLocality()); + idToken.setRegion(accessToken.getRegion()); + idToken.setPostalCode(accessToken.getPostalCode()); + idToken.setCountry(accessToken.getCountry()); + idToken.setPhoneNumber(accessToken.getPhoneNumber()); + idToken.setPhoneNumberVerified(accessToken.getPhoneNumberVerified()); + idToken.setZoneinfo(accessToken.getZoneinfo()); + return this; + } + public AccessTokenResponse build() { AccessTokenResponse res = new AccessTokenResponse(); + if (idToken != null) { + String encodedToken = new JWSBuilder().jsonContent(idToken).rsa256(realm.getPrivateKey()); + res.setIdToken(encodedToken); + } if (accessToken != null) { String encodedToken = new JWSBuilder().jsonContent(accessToken).rsa256(realm.getPrivateKey()); res.setToken(encodedToken); diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java index a3afea9b38..dd94e6f143 100755 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -27,12 +27,9 @@ import org.keycloak.account.Account; import org.keycloak.account.AccountLoader; import org.keycloak.account.AccountPages; import org.keycloak.jaxrs.JaxrsOAuthClient; -import org.keycloak.jose.jws.JWSInput; -import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.models.*; import org.keycloak.models.utils.TimeBasedOTP; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.managers.AccessCodeEntry; import org.keycloak.services.managers.AppAuthManager; import org.keycloak.services.managers.Auth; import org.keycloak.services.managers.ModelToRepresentation; @@ -257,7 +254,7 @@ public class AccountService { logger.debug("realm not enabled"); throw new ForbiddenException(); } - UserModel client = application.getApplicationUser(); + UserModel client = application.getAgent(); if (!client.isEnabled() || !application.isEnabled()) { logger.debug("account management app not enabled"); throw new ForbiddenException(); diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java index 44ac6e2821..ba6ce97a19 100755 --- a/services/src/main/java/org/keycloak/services/resources/TokenService.java +++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java @@ -159,7 +159,9 @@ public class TokenService { } String scope = form.getFirst("scope"); AccessTokenResponse res = tokenManager.responseBuilder(realm) - .generateAccessToken(scope, client, user).build(); + .generateAccessToken(scope, client, user) + .generateIDToken() + .build(); return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); } @@ -188,6 +190,7 @@ public class TokenService { AccessTokenResponse res = tokenManager.responseBuilder(realm) .accessToken(accessToken) + .generateIDToken() .generateRefreshToken().build(); return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); } @@ -410,6 +413,7 @@ public class TokenService { logger.debug("accessRequest SUCCESS"); AccessTokenResponse res = tokenManager.responseBuilder(realm) .accessToken(accessCode.getToken()) + .generateIDToken() .generateRefreshToken().build(); return Cors.add(request, Response.ok(res)).allowedOrigins(client).allowedMethods("POST").build(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java index 7a3fad1ba2..7c1e3f56ff 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java @@ -325,7 +325,7 @@ public class AdminService { return redirectOnLoginError("realm not enabled"); } ApplicationModel adminConsole = adminRealm.getApplicationNameMap().get(Constants.ADMIN_CONSOLE_APPLICATION); - UserModel adminConsoleUser = adminConsole.getApplicationUser(); + UserModel adminConsoleUser = adminConsole.getAgent(); if (!adminConsole.isEnabled() || !adminConsoleUser.isEnabled()) { logger.debug("admin app not enabled"); return redirectOnLoginError("admin app not enabled"); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java index 92c184592a..30270e5db9 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java @@ -6,7 +6,6 @@ import org.keycloak.models.ApplicationModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; -import org.keycloak.representations.adapters.config.BaseAdapterConfig; import org.keycloak.representations.idm.ApplicationRepresentation; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.services.managers.ApplicationManager; @@ -59,6 +58,11 @@ public class ApplicationResource { auth.init(RealmAuth.Resource.APPLICATION); } + @Path("claims") + public ClaimResource getClaimResource() { + return new ClaimResource(application); + } + @PUT @Consumes(MediaType.APPLICATION_JSON) public void update(final ApplicationRepresentation rep) { @@ -133,7 +137,7 @@ public class ApplicationResource { auth.requireView(); logger.debug("getClientSecret"); - UserCredentialModel model = realm.getSecret(application.getApplicationUser()); + UserCredentialModel model = realm.getSecret(application.getAgent()); if (model == null) throw new NotFoundException("Application does not have a secret"); return ModelToRepresentation.toRepresentation(model); } @@ -141,7 +145,7 @@ public class ApplicationResource { @Path("scope-mappings") public ScopeMappedResource getScopeMappedResource() { - return new ScopeMappedResource(realm, auth, application.getApplicationUser(), session); + return new ScopeMappedResource(realm, auth, application.getAgent(), session); } @Path("roles") @@ -156,7 +160,7 @@ public class ApplicationResource { { auth.requireView(); - return application.getApplicationUser().getWebOrigins(); + return application.getAgent().getWebOrigins(); } @Path("allowed-origins") @@ -166,7 +170,7 @@ public class ApplicationResource { { auth.requireManage(); - application.getApplicationUser().setWebOrigins(allowedOrigins); + application.getAgent().setWebOrigins(allowedOrigins); } @Path("allowed-origins") @@ -177,7 +181,7 @@ public class ApplicationResource { auth.requireManage(); for (String origin : allowedOrigins) { - application.getApplicationUser().removeWebOrigin(origin); + application.getAgent().removeWebOrigin(origin); } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClaimResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClaimResource.java new file mode 100755 index 0000000000..579394eefa --- /dev/null +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClaimResource.java @@ -0,0 +1,36 @@ +package org.keycloak.services.resources.admin; + +import org.keycloak.models.ClientModel; +import org.keycloak.representations.idm.ClaimRepresentation; +import org.keycloak.services.managers.ClaimManager; +import org.keycloak.services.managers.ModelToRepresentation; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ClaimResource { + protected ClientModel model; + + public ClaimResource(ClientModel model) { + this.model = model; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public ClaimRepresentation getClaims() { + return ModelToRepresentation.toRepresentation(model); + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + public void updateClaims(ClaimRepresentation rep) { + ClaimManager.setClaims(model, rep); + } +} diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java index 7ae8fe33cb..cbd6018f86 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java @@ -6,13 +6,10 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserCredentialModel; -import org.keycloak.representations.adapters.config.BaseAdapterConfig; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.OAuthClientRepresentation; -import org.keycloak.services.managers.ApplicationManager; import org.keycloak.services.managers.ModelToRepresentation; import org.keycloak.services.managers.OAuthClientManager; -import org.keycloak.services.managers.RealmManager; import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.util.JsonSerialization; @@ -29,7 +26,6 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriInfo; import java.io.IOException; -import java.util.List; /** * @author Bill Burke @@ -60,6 +56,12 @@ public class OAuthClientResource { auth.init(RealmAuth.Resource.CLIENT); } + @Path("claims") + public ClaimResource getClaimResource() { + return new ClaimResource(oauthClient); + } + + @PUT @Consumes(MediaType.APPLICATION_JSON) public void update(final OAuthClientRepresentation rep) { @@ -110,7 +112,7 @@ public class OAuthClientResource { logger.debug("regenerateSecret"); UserCredentialModel cred = UserCredentialModel.generateSecret(); - realm.updateCredential(oauthClient.getOAuthAgent(), cred); + realm.updateCredential(oauthClient.getAgent(), cred); CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred); return rep; } @@ -122,14 +124,14 @@ public class OAuthClientResource { auth.requireView(); logger.debug("getClientSecret"); - UserCredentialModel model = realm.getSecret(oauthClient.getOAuthAgent()); + UserCredentialModel model = realm.getSecret(oauthClient.getAgent()); if (model == null) throw new NotFoundException("Application does not have a secret"); return ModelToRepresentation.toRepresentation(model); } @Path("scope-mappings") public ScopeMappedResource getScopeMappedResource() { - return new ScopeMappedResource(realm, auth, oauthClient.getOAuthAgent(), session); + return new ScopeMappedResource(realm, auth, oauthClient.getAgent(), session); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java index 445622429a..0c0deb99dd 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java @@ -58,7 +58,7 @@ public class OAuthClientsResource { rep.add(OAuthClientManager.toRepresentation(oauth)); } else { OAuthClientRepresentation client = new OAuthClientRepresentation(); - client.setName(oauth.getOAuthAgent().getLoginName()); + client.setName(oauth.getAgent().getLoginName()); rep.add(client); } } diff --git a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java index 8524807eeb..f523fcc72a 100755 --- a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java @@ -24,6 +24,7 @@ package org.keycloak.services.resources.flows; import org.jboss.resteasy.logging.Logger; import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.models.Constants; +import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; @@ -127,6 +128,7 @@ public class OAuthFlows { if (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested().size() > 0)) { + OAuthClientModel oauthClient = realm.getOAuthClient(client.getLoginName()); accessCode.setExpiration(System.currentTimeMillis() / 1000 + realm.getAccessCodeLifespanUserAction()); return Flows.forms(realm, request, uriInfo).setAccessCode(accessCode.getId(), accessCode.getCode()). setAccessRequest(accessCode.getRealmRolesRequested(), accessCode.getResourceRolesRequested()). diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java index 3c96873be4..044d72faea 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java @@ -65,9 +65,9 @@ public class ProfileTest { appRealm.updateCredential(user2, creds); ApplicationModel app = appRealm.getApplicationNameMap().get("test-app"); - appRealm.addScopeMapping(app.getApplicationUser(), accountApp.getRole(AccountRoles.VIEW_PROFILE)); + appRealm.addScopeMapping(app.getAgent(), accountApp.getRole(AccountRoles.VIEW_PROFILE)); - app.getApplicationUser().addWebOrigin("http://localtest.me:8081"); + app.getAgent().addWebOrigin("http://localtest.me:8081"); UserModel thirdParty = appRealm.getUser("third-party"); appRealm.addScopeMapping(thirdParty, accountApp.getRole(AccountRoles.VIEW_PROFILE)); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java index 7d6c128c96..a8540ed93b 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java @@ -86,21 +86,21 @@ public class CompositeRoleTest { realmComposite1Application.addScope(realmComposite1); realmComposite1Application.setBaseUrl("http://localhost:8081/app"); realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout"); - realm.updateCredential(realmComposite1Application.getApplicationUser(), UserCredentialModel.secret("password")); + realm.updateCredential(realmComposite1Application.getAgent(), UserCredentialModel.secret("password")); final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION"); realmRole1Application.setEnabled(true); realmRole1Application.addScope(realmRole1); realmRole1Application.setBaseUrl("http://localhost:8081/app"); realmRole1Application.setManagementUrl("http://localhost:8081/app/logout"); - realm.updateCredential(realmRole1Application.getApplicationUser(), UserCredentialModel.secret("password")); + realm.updateCredential(realmRole1Application.getAgent(), UserCredentialModel.secret("password")); final ApplicationModel appRoleApplication = new ApplicationManager(manager).createApplication(realm, "APP_ROLE_APPLICATION"); appRoleApplication.setEnabled(true); appRoleApplication.setBaseUrl("http://localhost:8081/app"); appRoleApplication.setManagementUrl("http://localhost:8081/app/logout"); - realm.updateCredential(appRoleApplication.getApplicationUser(), UserCredentialModel.secret("password")); + realm.updateCredential(appRoleApplication.getAgent(), UserCredentialModel.secret("password")); final RoleModel appRole1 = appRoleApplication.addRole("APP_ROLE_1"); final RoleModel appRole2 = appRoleApplication.addRole("APP_ROLE_2"); @@ -121,7 +121,7 @@ public class CompositeRoleTest { appCompositeApplication.setEnabled(true); appCompositeApplication.setBaseUrl("http://localhost:8081/app"); appCompositeApplication.setManagementUrl("http://localhost:8081/app/logout"); - realm.updateCredential(appCompositeApplication.getApplicationUser(), UserCredentialModel.secret("password")); + realm.updateCredential(appCompositeApplication.getAgent(), UserCredentialModel.secret("password")); final RoleModel appCompositeRole = appCompositeApplication.addRole("APP_COMPOSITE_ROLE"); appCompositeApplication.addScope(appRole2); appCompositeRole.addCompositeRole(realmRole1); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java index f35888228f..cf7765ee4c 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java @@ -82,7 +82,7 @@ public class AuthorizationCodeTest { public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { for (ApplicationModel app : appRealm.getApplications()) { if (app.getName().equals("test-app")) { - UserModel client = app.getApplicationUser(); + UserModel client = app.getAgent(); client.addRedirectUri(oauth.getRedirectUri()); } } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java index ee60bd5b90..8e973c117b 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java @@ -48,7 +48,7 @@ public class OAuthRedirectUriTest { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { ApplicationModel app = appRealm.getApplicationNameMap().get("test-app"); - app.getApplicationUser().addRedirectUri("http://localhost:8081/app"); + app.getAgent().addRedirectUri("http://localhost:8081/app"); } }); @@ -81,7 +81,7 @@ public class OAuthRedirectUriTest { keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").getApplicationUser().addRedirectUri("http://localhost:8081/app2"); + appRealm.getApplicationNameMap().get("test-app").getAgent().addRedirectUri("http://localhost:8081/app2"); } }); @@ -95,7 +95,7 @@ public class OAuthRedirectUriTest { keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").getApplicationUser().removeRedirectUri("http://localhost:8081/app2"); + appRealm.getApplicationNameMap().get("test-app").getAgent().removeRedirectUri("http://localhost:8081/app2"); } }); } @@ -106,7 +106,7 @@ public class OAuthRedirectUriTest { keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").getApplicationUser().removeRedirectUri("http://localhost:8081/app"); + appRealm.getApplicationNameMap().get("test-app").getAgent().removeRedirectUri("http://localhost:8081/app"); } }); @@ -120,7 +120,7 @@ public class OAuthRedirectUriTest { keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").getApplicationUser().addRedirectUri("http://localhost:8081/app"); + appRealm.getApplicationNameMap().get("test-app").getAgent().addRedirectUri("http://localhost:8081/app"); } }); } @@ -131,7 +131,7 @@ public class OAuthRedirectUriTest { keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").getApplicationUser().removeRedirectUri("http://localhost:8081/app"); + appRealm.getApplicationNameMap().get("test-app").getAgent().removeRedirectUri("http://localhost:8081/app"); } }); @@ -144,7 +144,7 @@ public class OAuthRedirectUriTest { keycloakRule.configure(new KeycloakRule.KeycloakSetup() { @Override public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { - appRealm.getApplicationNameMap().get("test-app").getApplicationUser().addRedirectUri("http://localhost:8081/app"); + appRealm.getApplicationNameMap().get("test-app").getAgent().addRedirectUri("http://localhost:8081/app"); } }); }