diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml index 7b8c877113..f435ffc945 100755 --- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml +++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml @@ -62,28 +62,40 @@ + + + + + + + + + + + + DTYPE = 'OAuthClientEntity' - + diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml index b4d93a7da9..83eadb5ccf 100755 --- a/connections/jpa/src/main/resources/META-INF/persistence.xml +++ b/connections/jpa/src/main/resources/META-INF/persistence.xml @@ -27,6 +27,7 @@ org.keycloak.models.sessions.jpa.entities.ClientSessionEntity org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity + org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity org.keycloak.models.sessions.jpa.entities.UserSessionNoteEntity org.keycloak.models.sessions.jpa.entities.UserSessionEntity diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java index 8ee4db3c53..811039c1b7 100644 --- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java +++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java @@ -17,6 +17,9 @@ public class Update1_2_0_RC1 extends Update { @Override public void update(KeycloakSession session) { + deleteEntries("clientSessions"); + deleteEntries("sessions"); + convertApplicationsToClients(); convertOAuthClientsToClients(); diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java index 0ef0069b41..d591fbabe1 100755 --- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java +++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java @@ -39,6 +39,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro "org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity", "org.keycloak.models.entities.UserFederationProviderEntity", "org.keycloak.models.entities.ProtocolMapperEntity", + "org.keycloak.models.entities.IdentityProviderMapperEntity", "org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity" }; diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java index de40f101ca..41371965e0 100755 --- a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java @@ -10,6 +10,7 @@ import java.util.Map; public class ClientRepresentation { protected String id; protected String clientId; + protected String name; protected String adminUrl; protected String baseUrl; protected Boolean surrogateAuthRequired; @@ -40,6 +41,14 @@ public class ClientRepresentation { this.id = id; } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public String getClientId() { return clientId; } diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java index 66b106cc04..fbd909db83 100755 --- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java +++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java @@ -120,6 +120,8 @@ public class ImportUtils { adminRole.setDescription("${role_"+AdminRoles.ADMIN+"}"); ClientModel realmAdminApp = KeycloakModelUtils.createClient(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm)); + // No localized name for now + realmAdminApp.setName(realm.getName() + " Realm"); realmAdminApp.setBearerOnly(true); realm.setMasterAdminClient(realmAdminApp); diff --git a/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java b/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java index 3e236dd87f..257fc8434e 100644 --- a/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java +++ b/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java @@ -5,6 +5,6 @@ package org.keycloak.account; */ public enum AccountPages { - ACCOUNT, PASSWORD, TOTP, FEDERATED_IDENTITY, LOG, SESSIONS, ACCESS; + ACCOUNT, PASSWORD, TOTP, FEDERATED_IDENTITY, LOG, SESSIONS, APPLICATIONS; } diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java index ba9534837b..ab1dcad68c 100755 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java @@ -20,7 +20,7 @@ import javax.ws.rs.core.UriInfo; import org.jboss.logging.Logger; import org.keycloak.account.AccountPages; import org.keycloak.account.AccountProvider; -import org.keycloak.account.freemarker.model.AccessBean; +import org.keycloak.account.freemarker.model.ConsentBean; import org.keycloak.account.freemarker.model.AccountBean; import org.keycloak.account.freemarker.model.AccountFederatedIdentityBean; import org.keycloak.account.freemarker.model.FeaturesBean; @@ -185,8 +185,8 @@ public class FreeMarkerAccountProvider implements AccountProvider { case SESSIONS: attributes.put("sessions", new SessionsBean(realm, sessions)); break; - case ACCESS: - attributes.put("access", new AccessBean(realm, user, uriInfo.getBaseUri(), stateChecker)); + case APPLICATIONS: + attributes.put("consent", new ConsentBean(user)); attributes.put("advancedMsg", new AdvancedMessageFormatterMethod(locale, messagesBundle)); break; case PASSWORD: diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java index 847a3e690b..d3116f647d 100644 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java @@ -21,8 +21,8 @@ public class Templates { return "log.ftl"; case SESSIONS: return "sessions.ftl"; - case ACCESS: - return "access.ftl"; + case APPLICATIONS: + return "applications.ftl"; default: throw new IllegalArgumentException(); } diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/ConsentBean.java similarity index 58% rename from forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java rename to forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/ConsentBean.java index 67eb4a68b4..ee4c6e06da 100644 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/AccessBean.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/ConsentBean.java @@ -1,6 +1,5 @@ package org.keycloak.account.freemarker.model; -import java.net.URI; import java.util.LinkedList; import java.util.List; @@ -15,22 +14,25 @@ import org.keycloak.util.MultivaluedHashMap; /** * @author Marek Posolda */ -public class AccessBean { +public class ConsentBean { private List clientGrants = new LinkedList(); - public AccessBean(RealmModel realm, UserModel user, URI baseUri, String stateChecker) { + public ConsentBean(UserModel user) { List grantedConsents = user.getConsents(); for (UserConsentModel consent : grantedConsents) { ClientModel client = consent.getClient(); List realmRolesGranted = new LinkedList(); - MultivaluedHashMap resourceRolesGranted = new MultivaluedHashMap(); + MultivaluedHashMap resourceRolesGranted = new MultivaluedHashMap(); for (RoleModel role : consent.getGrantedRoles()) { if (role.getContainer() instanceof RealmModel) { realmRolesGranted.add(role); } else { - resourceRolesGranted.add(((ClientModel) role.getContainer()).getClientId(), role); + ClientModel currentClient = (ClientModel) role.getContainer(); + ClientRoleEntry clientRole = new ClientRoleEntry(currentClient.getClientId(), currentClient.getName(), + role.getName(), role.getDescription()); + resourceRolesGranted.add(currentClient.getClientId(), clientRole); } } @@ -51,11 +53,11 @@ public class AccessBean { public static class ClientGrantBean { private final List realmRolesGranted; - private final MultivaluedHashMap resourceRolesGranted; + private final MultivaluedHashMap resourceRolesGranted; private final ClientModel client; private final List claimsGranted; - public ClientGrantBean(List realmRolesGranted, MultivaluedHashMap resourceRolesGranted, + public ClientGrantBean(List realmRolesGranted, MultivaluedHashMap resourceRolesGranted, ClientModel client, List claimsGranted) { this.realmRolesGranted = realmRolesGranted; this.resourceRolesGranted = resourceRolesGranted; @@ -67,7 +69,7 @@ public class AccessBean { return realmRolesGranted; } - public MultivaluedHashMap getResourceRolesGranted() { + public MultivaluedHashMap getResourceRolesGranted() { return resourceRolesGranted; } @@ -80,4 +82,36 @@ public class AccessBean { } } + + // Same class used in OAuthGrantBean as well. Maybe should be merged into common-freemarker... + public static class ClientRoleEntry { + + private final String clientId; + private final String clientName; + private final String roleName; + private final String roleDescription; + + public ClientRoleEntry(String clientId, String clientName, String roleName, String roleDescription) { + this.clientId = clientId; + this.clientName = clientName; + this.roleName = roleName; + this.roleDescription = roleDescription; + } + + public String getClientId() { + return clientId; + } + + public String getClientName() { + return clientName; + } + + public String getRoleName() { + return roleName; + } + + public String getRoleDescription() { + return roleDescription; + } + } } diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java index 40ea59f9a8..0de3a9af7a 100755 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java @@ -27,8 +27,8 @@ public class UrlBean { this.stateChecker = stateChecker; } - public String getAccessUrl() { - return Urls.accountAccessPage(baseQueryURI, realm).toString(); + public String getApplicationsUrl() { + return Urls.accountApplicationsPage(baseQueryURI, realm).toString(); } public String getAccountUrl() { diff --git a/forms/common-themes/src/main/resources/theme/base/account/access.ftl b/forms/common-themes/src/main/resources/theme/base/account/applications.ftl similarity index 65% rename from forms/common-themes/src/main/resources/theme/base/account/access.ftl rename to forms/common-themes/src/main/resources/theme/base/account/applications.ftl index dc3cc4141a..9b5cf88592 100755 --- a/forms/common-themes/src/main/resources/theme/base/account/access.ftl +++ b/forms/common-themes/src/main/resources/theme/base/account/applications.ftl @@ -1,9 +1,9 @@ <#import "template.ftl" as layout> -<@layout.mainLayout active='access' bodyClass='access'; section> +<@layout.mainLayout active='applications' bodyClass='applications'; section>
-

${msg("accessHtmlTitle")}

+

${msg("applicationsHtmlTitle")}

@@ -21,9 +21,13 @@ - <#list access.clientGrants as clientGrant> + <#list consent.clientGrants as clientGrant> - <#if clientGrant.client.baseUrl??>${clientGrant.client.clientId}<#else>${clientGrant.client.clientId} + + <#if clientGrant.client.baseUrl??> + <#if clientGrant.client.name??>${advancedMsg(clientGrant.client.name)}<#else>${clientGrant.client.clientId} + <#if clientGrant.client.baseUrl??> + <#list clientGrant.claimsGranted as claim> ${advancedMsg(claim)}<#if claim_has_next>, @@ -36,10 +40,10 @@ <#list clientGrant.resourceRolesGranted?keys as resource> <#if clientGrant.realmRolesGranted?has_content>, - <#list clientGrant.resourceRolesGranted[resource] as role> - <#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)} - ${msg("inResource", resource)} - <#if role_has_next>, + <#list clientGrant.resourceRolesGranted[resource] as clientRole> + <#if clientRole.roleDescription??>${advancedMsg(clientRole.roleDescription)}<#else>${advancedMsg(clientRole.roleName)} + ${msg("inResource")} <#if clientRole.clientName??>${advancedMsg(clientRole.clientName)}<#else>${clientRole.clientId} + <#if clientRole_has_next>, diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties index a846d541bc..add9daa906 100644 --- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties +++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties @@ -16,16 +16,40 @@ authenticatorTitle=Authenticator authenticatorCode=One-time code email=E-Mail firstName=Vorname +givenName=Vorname +fullName=voller Name lastName=Nachname +familyName=Nachname password=Passwort passwordConfirm=Passwortbest\u00E4tigung passwordNew=Neues Passwort username=Benutzernamen +address=Adresse street=Strasse region=Staat, Provinz, Region postal_code=PLZ locality=Stadt oder Ortschaft country=Land +emailVerified=E-Mail verifiziert +gssDelegationCredential=GSS delegierte Berechtigung + +role_admin=Admin +role_realm-admin=Realm Admin +role_create-realm=Realm erstellen +role_view-realm=Realm ansehen +role_view-users=Benutzer ansehen +role_view-applications=Applicationen ansehen +role_view-clients=Clients ansehen +role_view-events=Events ansehen +role_view-identity-providers=Identity Providers ansehen +role_manage-realm=Realm verwalten +role_manage-users=Benutzer verwalten +role_manage-applications=Applikationen verwalten +role_manage-identity-providers=Identity Provider verwalten +role_manage-clients=Clients verwalten +role_manage-events=Events verwalten +role_view-profile=Profile ansehen +role_manage-account=Profile verwalten requiredFields=Erforderliche Felder allFieldsRequired=Alle Felder sind Erforderlich @@ -42,7 +66,7 @@ details=Details started=Startdatum lastAccess=Letzter Zugriff expires=Ablaufdatum -applications= +applications=Applicationen account=Benutzerkonto federatedIdentity=Federated Identity diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties index d0bbb37d18..a2d99fe06e 100755 --- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties +++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties @@ -12,7 +12,7 @@ changePasswordHtmlTitle=Change Password sessionsHtmlTitle=Sessions accountManagementTitle=Keycloak Account Management authenticatorTitle=Authenticator -accessHtmlTitle=Manage Granted Permissions +applicationsHtmlTitle=Manage Granted Permissions authenticatorCode=One-time code email=Email @@ -50,6 +50,9 @@ role_manage-identity-providers=Manage identity providers role_manage-clients=Manage clients role_manage-events=Manage events role_view-profile=View profile +client_account=Account +client_security-admin-console=Security Admin Console +client_realm-management=Realm Management requiredFields=Required fields @@ -74,13 +77,12 @@ federatedIdentity=Federated Identity authenticator=Authenticator sessions=Sessions log=Log -access=Access grantedPersonalInfo=Granted Personal Info grantedPermissions=Granted Permissions action=Action -inResource=in {0} -revoke=Revoke Access +inResource=in +revoke=Revoke Grant configureAuthenticators=Configured Authenticators mobile=Mobile @@ -106,7 +108,7 @@ readOnlyPasswordMessage=You can''t update your password as your account is read successTotpMessage=Mobile authenticator configured. successTotpRemovedMessage=Mobile authenticator removed. -successGrantRevokedMessage=Access revoked successfully. +successGrantRevokedMessage=Grant revoked successfully. accountUpdatedMessage=Your account has been updated. accountPasswordUpdatedMessage=Your password has been updated. diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties index d22b935351..99eff0c090 100755 --- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties +++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties @@ -16,16 +16,40 @@ authenticatorTitle=Authenticator authenticatorCode=Codice One-time email=Email firstName=Nome +givenName=Nome +fullName=Nome Completo lastName=Cognome +familyName=Cognome password=Password passwordConfirm=Conferma Password passwordNew=Nuova Password username=Username +address=Indirizzo street=Via locality=Citta'' o Localita'' region=Stato, Provincia, o Regione postal_code=Cap country=Paese +emailVerified=Email verificata +gssDelegationCredential=credenziali gss delegation + +role_admin=Admin +role_realm-admin=Realm Admin +role_create-realm=Crea realm +role_view-realm=Visualizza realm +role_view-users=Visualizza utenti +role_view-applications=Visualizza applicazioni +role_view-clients=Visualizza client +role_view-events=Visualizza eventi +role_view-identity-providers=Visualizza identity provider +role_manage-realm=Gestisci realm +role_manage-users=Gestisci utenti +role_manage-applications=Gestisci applicazioni +role_manage-identity-providers=Gestisci identity provider +role_manage-clients=Gestisci client +role_manage-events=Gestisci eventi +role_view-profile=Visualizza profilo +role_manage-account=Gestisci account requiredFields=Campi obbligatori allFieldsRequired=Tutti campi obbligatori diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties index 367be5f383..a29d60d799 100644 --- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties +++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties @@ -16,16 +16,40 @@ authenticatorTitle=Autenticator authenticatorCode=C\u00F3digo autenticador email=Email firstName=Primeiro nome +givenName=Primeiro nome +fullName=Nome completo lastName=Sobrenome +familyName=Sobrenome password=Senha passwordConfirm=Confirma\u00E7\u00E3o passwordNew=Nova senha username=Nome de us\u00FAario +address=Endere\u00E7o street=Logradouro locality=Cidade ou Localidade region=Estado postal_code=CEP country=Pa\u00EDs +emailVerified=Email verificado +gssDelegationCredential=gss delega\u00E7\u00E3o credencial + +role_admin=Admin +role_realm-admin=Realm Admin +role_create-realm=Cria realm +role_view-realm=Visualiza realm +role_view-users=Visualiza usu\u00E1rios +role_view-applications=Visualiza aplica\u00E7\u00F5es +role_view-clients=Visualiza clientes +role_view-events=Visualiza eventos +role_view-identity-providers=Visualiza provedores de identidade +role_manage-realm=Gerencia realm +role_manage-users=Gerencia usu\u00E1rios +role_manage-applications=Gerencia aplica\u00E7\u00F5es +role_manage-identity-providers=Gerencia provedores de identidade +role_manage-clients=Gerencia clientes +role_manage-events=Gerencia eventos +role_view-profile=Visualiza perfil +role_manage-account=Gerencia contas requiredFields=Campos obrigat\u00F3rios allFieldsRequired=Todos os campos s\u00E3o obrigat\u00F3rios diff --git a/forms/common-themes/src/main/resources/theme/base/account/template.ftl b/forms/common-themes/src/main/resources/theme/base/account/template.ftl index 1319b6f5d9..dfd2b29528 100644 --- a/forms/common-themes/src/main/resources/theme/base/account/template.ftl +++ b/forms/common-themes/src/main/resources/theme/base/account/template.ftl @@ -56,7 +56,7 @@
  • ${msg("authenticator")}
  • <#if features.identityFederation>
  • ${msg("federatedIdentity")}
  • ${msg("sessions")}
  • -
  • ${msg("access")}
  • +
  • ${msg("applications")}
  • <#if features.log>
  • ${msg("log")}
  • diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html index ebfca94936..69dd012a65 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html @@ -19,9 +19,17 @@
    -
    +
    + +
    +
    + +
    + +
    +
    diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl index 6136e8b033..30d55c3568 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl +++ b/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl @@ -3,7 +3,7 @@ <#if section = "title"> ${msg("oauthGrantTitle")} <#elseif section = "header"> - ${msg("oauthGrantTitleHtml",(realm.name!''), (client.clientId!''))} + ${msg("oauthGrantTitleHtml",(realm.name!''))} <#if client.name??>${advancedMsg(client.name)}<#else>${client.clientId}. <#elseif section = "form">

    ${msg("oauthGrantRequest")}

    @@ -34,10 +34,10 @@ <#if oauth.resourceRolesRequested??> <#list oauth.resourceRolesRequested?keys as resource> - <#list oauth.resourceRolesRequested[resource] as role> + <#list oauth.resourceRolesRequested[resource] as clientRole>
  • - <#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)} - ${msg("inResource", resource)} + <#if clientRole.roleDescription??>${advancedMsg(clientRole.roleDescription)}<#else>${advancedMsg(clientRole.roleName)} + ${msg("inResource")} <#if clientRole.clientName??>${advancedMsg(clientRole.clientName)}<#else>${clientRole.clientId}
  • diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties index ca45f53821..5999681766 100644 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties @@ -16,7 +16,7 @@ loginOauthTitleHtml=Tempor\u00E4rer zugriff auf {0} angefordert loginTotpTitle=Mobile Authentifizierung Einrichten loginProfileTitle=Benutzerkonto Informationen aktualisieren oauthGrantTitle=OAuth gew\u00E4hren -oauthGrantTitleHtml=Tempor\u00E4rer zugriff auf {0} angefordert von {1}. +oauthGrantTitleHtml=Tempor\u00E4rer zugriff auf {0} angefordert von errorTitle=Es tut uns leid... errorTitleHtml=Es tut uns leid... emailVerifyTitle=E-Mail verifizieren @@ -55,7 +55,7 @@ loginTotpStep3=Geben Sie den One-time Code welcher die Applikation generiert hat loginTotpOneTime=One-time Code oauthGrantRequest=Wollen Sie diese Zugriffsreche gew\u00E4hren? -inResource=in {0} +inResource=in emailVerifyInstruction1=Ein E-Mail mit weitern Anweisungen wurde an Sie versendet. emailVerifyInstruction2=Falls Sie kein E-Mail erhalten haben, dann k\u00F6nnen Sie diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties index 006883fa5f..a1f76eee6b 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties @@ -14,7 +14,7 @@ loginTitleHtml=Log in to {0} loginTotpTitle=Mobile Authenticator Setup loginProfileTitle=Update Account Information oauthGrantTitle=OAuth Grant -oauthGrantTitleHtml=Temporary access for {0} requested by {1}. +oauthGrantTitleHtml=Temporary access for {0} requested by errorTitle=We''re sorry... errorTitleHtml=We''re sorry ... emailVerifyTitle=Email verification @@ -45,7 +45,7 @@ region=State, Province, or Region postal_code=Zip or Postal code country=Country emailVerified=Email verified -gssDelegationCredential=gss delegation credential +gssDelegationCredential=GSS Delegation Credential loginTotpStep1=Install FreeOTP or Google Authenticator on your mobile. Both applications are available in Google Play and Apple App Store. loginTotpStep2=Open the application and scan the barcode or enter the key @@ -53,7 +53,7 @@ loginTotpStep3=Enter the one-time code provided by the application and click Sub loginTotpOneTime=One-time code oauthGrantRequest=Do you grant these access privileges? -inResource=in {0} +inResource=in emailVerifyInstruction1=An email with instructions to verify your email address has been sent to you. emailVerifyInstruction2=Haven''t received a verification code in your email? @@ -84,6 +84,9 @@ role_manage-clients=Manage clients role_manage-events=Manage events role_view-profile=View profile role_manage-account=Manage account +client_account=Account +client_security-admin-console=Security Admin Console +client_realm-management=Realm Management invalidUserMessage=Invalid username or password. invalidEmailMessage=Invalid email address. diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties index f7296b95db..b019d6cdd0 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties @@ -14,7 +14,7 @@ loginTitleHtml=Accedi a {0} loginTotpTitle=Configura Autenticazione Mobile loginProfileTitle=Aggiorna Profilo oauthGrantTitle=OAuth Grant -oauthGrantTitleHtml=Accesso temporaneo per {0} richiesto da {1}. +oauthGrantTitleHtml=Accesso temporaneo per {0} richiesto da errorTitle=Siamo spiacenti... errorTitleHtml=Siamo spiacenti ... emailVerifyTitle=Verifica Email @@ -53,7 +53,7 @@ loginTotpStep3=Scrivi il codice one-time fornito dall''applicazione e premi Invi loginTotpOneTime=Codice one-time oauthGrantRequest=Vuoi assegnare questi privilegi di accesso? -inResource=per {0} +inResource=per emailVerifyInstruction1=Ti e'' stata inviata una email con le istruzioni per la verifica della tua email. emailVerifyInstruction2=Non hai ricevuto un codice di verifica nella tua email? diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties index 896f83f5c1..8d50d3e297 100644 --- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties +++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties @@ -14,7 +14,7 @@ loginTitleHtml=Entrar em {0} loginTotpTitle=Configura\u00E7\u00E3o do autenticador mobile loginProfileTitle=Atualiza\u00E7\u00E3o de Informa\u00E7\u00F5es da Conta oauthGrantTitle=Concess\u00E3o OAuth -oauthGrantTitleHtml=Acesso tempor\u00E1rio para {0} solicitado pela {1}. +oauthGrantTitleHtml=Acesso tempor\u00E1rio para {0} solicitado pela errorTitle=N\u00F3s lamentamos... errorTitleHtml=N\u00F3s lamentamos ... emailVerifyTitle=Verifica\u00E7\u00E3o de e-mail @@ -53,7 +53,7 @@ loginTotpStep3=Digite o c\u00F3digo fornecido pelo aplicativo e clique em Enviar loginTotpOneTime=C\u00F3digo autenticador oauthGrantRequest=Voc\u00EA concede esses privil\u00E9gios de acesso? -inResource=em {0} +inResource=em emailVerifyInstruction1=Um e-mail com instru\u00E7\u00F5es para verificar o seu endere\u00E7o de e-mail foi enviado para voc\u00EA. emailVerifyInstruction2=Voc\u00EA n\u00E3o recebeu um c\u00F3digo de verifica\u00E7\u00E3o em seu e-mail? diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java index 53f7937106..d945c38db8 100755 --- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java +++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java @@ -18,6 +18,10 @@ public class ClientBean { return client.getClientId(); } + public String getName() { + return client.getName(); + } + public String getBaseUrl() { return client.getBaseUrl(); } 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 98cd164889..6032587627 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 @@ -21,6 +21,7 @@ */ package org.keycloak.login.freemarker.model; +import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.ProtocolMapperModel; @@ -29,6 +30,7 @@ import org.keycloak.models.RoleModel; import javax.ws.rs.core.MultivaluedMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * @author Viliam Rockai @@ -37,7 +39,7 @@ public class OAuthGrantBean { private final String accessRequestMessage; private List realmRolesRequested; - private MultivaluedMap resourceRolesRequested; + private MultivaluedMap resourceRolesRequested; private String code; private ClientModel client; private List claimsRequested; @@ -47,7 +49,17 @@ public class OAuthGrantBean { this.code = code; this.client = client; this.realmRolesRequested = realmRolesRequested; - this.resourceRolesRequested = resourceRolesRequested; + if (resourceRolesRequested != null) { + this.resourceRolesRequested = new MultivaluedMapImpl(); + for (List clientRoles : resourceRolesRequested.values()) { + for (RoleModel role : clientRoles) { + ClientModel currentClient = (ClientModel) role.getContainer(); + ClientRoleEntry roleEntry = new ClientRoleEntry(currentClient.getClientId(), currentClient.getName(), role.getName(), role.getDescription()); + this.resourceRolesRequested.add(currentClient.getClientId(), roleEntry); + } + } + } + this.accessRequestMessage = accessRequestMessage; List claims = new LinkedList(); @@ -63,7 +75,7 @@ public class OAuthGrantBean { return code; } - public MultivaluedMap getResourceRolesRequested() { + public MultivaluedMap getResourceRolesRequested() { return resourceRolesRequested; } @@ -82,4 +94,36 @@ public class OAuthGrantBean { public String getAccessRequestMessage() { return this.accessRequestMessage; } + + // Same class used in ConsentBean in account as well. Maybe should be merged into common-freemarker... + public static class ClientRoleEntry { + + private final String clientId; + private final String clientName; + private final String roleName; + private final String roleDescription; + + public ClientRoleEntry(String clientId, String clientName, String roleName, String roleDescription) { + this.clientId = clientId; + this.clientName = clientName; + this.roleName = roleName; + this.roleDescription = roleDescription; + } + + public String getClientId() { + return clientId; + } + + public String getClientName() { + return clientName; + } + + public String getRoleName() { + return roleName; + } + + public String getRoleDescription() { + return roleDescription; + } + } } diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java index 2382f55f79..5fae169b3f 100755 --- a/model/api/src/main/java/org/keycloak/models/ClientModel.java +++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java @@ -24,6 +24,10 @@ public interface ClientModel extends RoleContainerModel { void setClientId(String clientId); + String getName(); + + void setName(String name); + boolean isEnabled(); void setEnabled(boolean enabled); diff --git a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java index 059afc941b..7c197a34a1 100755 --- a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java +++ b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java @@ -28,6 +28,9 @@ public interface ClientSessionModel { public Set getRoles(); public void setRoles(Set roles); + public Set getProtocolMappers(); + public void setProtocolMappers(Set protocolMappers); + /** * Authentication request type, i.e. OAUTH, SAML 2.0, SAML 1.1, etc. * diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java index 17c88ea76e..9c2960424b 100755 --- a/model/api/src/main/java/org/keycloak/models/RealmModel.java +++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java @@ -145,6 +145,7 @@ public interface RealmModel extends RoleContainerModel { void updateDefaultRoles(String[] defaultRoles); + // Key is clientId Map getClientNameMap(); List getClients(); diff --git a/model/api/src/main/java/org/keycloak/models/UserConsentModel.java b/model/api/src/main/java/org/keycloak/models/UserConsentModel.java index 11f1034500..a8e4cc3b61 100644 --- a/model/api/src/main/java/org/keycloak/models/UserConsentModel.java +++ b/model/api/src/main/java/org/keycloak/models/UserConsentModel.java @@ -8,31 +8,20 @@ import java.util.Set; */ public class UserConsentModel { - private final RealmModel realm; private final ClientModel client; private Set protocolMappers = new HashSet(); private Set roles = new HashSet(); - public UserConsentModel(RealmModel realm, String clientId) { - this.realm = realm; - this.client = realm.getClientById(clientId); - - if (client == null) { - throw new ModelException("Client with id [" + clientId + "] is not available"); - } + public UserConsentModel(ClientModel client) { + this.client = client; } public ClientModel getClient() { return client; } - public void addGrantedRole(String roleId) { - RoleModel role = realm.getRoleById(roleId); - - // Chance that role was already deleted by other transaction and is not available anymore - if (role != null) { - roles.add(role); - } + public void addGrantedRole(RoleModel role) { + roles.add(role); } public Set getGrantedRoles() { @@ -46,13 +35,8 @@ public class UserConsentModel { return false; } - public void addGrantedProtocolMapper(String protocolMapperId) { - ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protocolMapperId); - - // Chance that protocolMapper was already deleted by other transaction and is not available anymore - if (protocolMapper != null) { - protocolMappers.add(protocolMapper); - } + public void addGrantedProtocolMapper(ProtocolMapperModel protocolMapper) { + protocolMappers.add(protocolMapper); } public Set getGrantedProtocolMappers() { diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java index 699c6d6244..513c4ef831 100644 --- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java +++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java @@ -11,6 +11,7 @@ import java.util.Map; public class ClientEntity extends AbstractIdentifiableEntity { private String clientId; + private String name; private String realmId; private boolean enabled; private String secret; @@ -49,6 +50,14 @@ public class ClientEntity extends AbstractIdentifiableEntity { this.clientId = clientId; } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public boolean isEnabled() { return enabled; } diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 63be7f03ab..e10cbed99a 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -226,6 +226,7 @@ public class ModelToRepresentation { ClientRepresentation rep = new ClientRepresentation(); rep.setId(clientModel.getId()); rep.setClientId(clientModel.getClientId()); + rep.setName(clientModel.getName()); rep.setEnabled(clientModel.isEnabled()); rep.setAdminUrl(clientModel.getManagementUrl()); rep.setPublicClient(clientModel.isPublicClient()); diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index 282d37608d..d5983cdac0 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -523,6 +523,7 @@ public class RepresentationToModel { logger.debug("Create client: {0}" + resourceRep.getClientId()); ClientModel client = resourceRep.getId()!=null ? realm.addClient(resourceRep.getId(), resourceRep.getClientId()) : realm.addClient(resourceRep.getClientId()); + if (resourceRep.getName() != null) client.setName(resourceRep.getName()); if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled()); client.setManagementUrl(resourceRep.getAdminUrl()); if (resourceRep.isSurrogateAuthRequired() != null) @@ -614,6 +615,7 @@ public class RepresentationToModel { public static void updateClient(ClientRepresentation rep, ClientModel resource) { if (rep.getClientId() != null) resource.setClientId(rep.getClientId()); + if (rep.getName() != null) resource.setName(rep.getName()); if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled()); if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly()); if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired()); @@ -792,23 +794,25 @@ public class RepresentationToModel { throw new RuntimeException("Unable to find client consent mappings for client: " + entry.getKey()); } - UserConsentModel consentModel = new UserConsentModel(newRealm, client.getId()); + UserConsentModel consentModel = new UserConsentModel(client); UserConsentRepresentation consentRep = entry.getValue(); if (consentRep.getGrantedRoles() != null) { for (String roleId : consentRep.getGrantedRoles()) { - if (newRealm.getRoleById(roleId) == null) { + RoleModel role = newRealm.getRoleById(roleId); + if (role == null) { throw new RuntimeException("Unable to find realm role referenced in consent mappings of user " + user.getUsername() + ". Role ID: " + roleId); } - consentModel.addGrantedRole(roleId); + consentModel.addGrantedRole(role); } } if (consentRep.getGrantedProtocolMappers() != null) { for (String mapperId : consentRep.getGrantedProtocolMappers()) { - if (client.getProtocolMapperById(mapperId) == null) { + ProtocolMapperModel protocolMapper = client.getProtocolMapperById(mapperId); + if (protocolMapper == null) { throw new RuntimeException("Unable to find protocol mapper referenced in consent mappings of user " + user.getUsername() + ". Protocol mapper ID: " + mapperId); } - consentModel.addGrantedProtocolMapper(mapperId);; + consentModel.addGrantedProtocolMapper(protocolMapper); } } user.addConsent(consentModel); diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java index 7068a26cfa..e7847e2931 100755 --- a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java +++ b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java @@ -68,6 +68,16 @@ public class ClientAdapter implements ClientModel { return entity.getId(); } + @Override + public String getName() { + return entity.getName(); + } + + @Override + public void setName(String name) { + entity.setName(name); + } + @Override public Set getWebOrigins() { Set result = new HashSet(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java index 4dc4a031b5..48089bd5ca 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java @@ -293,7 +293,7 @@ public class ClientAdapter implements ClientModel { @Override public String getClientId() { if (updated != null) return updated.getClientId(); - return cached.getName(); + return cached.getClientId(); } @Override @@ -303,6 +303,18 @@ public class ClientAdapter implements ClientModel { cacheSession.registerRealmInvalidation(cachedRealm.getId()); } + @Override + public String getName() { + if (updated != null) return updated.getName(); + return cached.getName(); + } + + @Override + public void setName(String name) { + getDelegateForUpdate(); + updated.setName(name); + } + @Override public boolean isSurrogateAuthRequired() { if (updated != null) return updated.isSurrogateAuthRequired(); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java index 58d3cb0cd9..8b8c045e07 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java @@ -21,6 +21,7 @@ import java.util.TreeMap; */ public class CachedClient { private String id; + private String clientId; private String name; private String realm; private Set redirectUris = new HashSet(); @@ -49,7 +50,8 @@ public class CachedClient { public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) { id = model.getId(); secret = model.getSecret(); - name = model.getClientId(); + clientId = model.getClientId(); + name = model.getName(); this.realm = realm.getId(); enabled = model.isEnabled(); protocol = model.getProtocol(); @@ -85,6 +87,10 @@ public class CachedClient { return id; } + public String getClientId() { + return clientId; + } + public String getName() { return name; } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java index b290e48377..7e4906a7f9 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java @@ -54,6 +54,16 @@ public class ClientAdapter implements ClientModel { return realm; } + @Override + public String getName() { + return entity.getName(); + } + + @Override + public void setName(String name) { + entity.setName(name); + } + @Override public boolean isEnabled() { return entity.isEnabled(); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java index 8cc29f7ff5..5f92104b26 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java @@ -561,19 +561,27 @@ public class UserAdapter implements UserModel { return null; } - UserConsentModel model = new UserConsentModel(realm, entity.getClientId()); + ClientModel client = realm.getClientById(entity.getClientId()); + if (client == null) { + throw new ModelException("Client with id " + entity.getClientId() + " is not available"); + } + UserConsentModel model = new UserConsentModel(client); Collection grantedRoleEntities = entity.getGrantedRoles(); if (grantedRoleEntities != null) { for (UserConsentRoleEntity grantedRole : grantedRoleEntities) { - model.addGrantedRole(grantedRole.getRoleId()); + RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId()); + if (grantedRoleModel != null) { + model.addGrantedRole(grantedRoleModel); + } } } Collection grantedProtocolMapperEntities = entity.getGrantedProtocolMappers(); if (grantedProtocolMapperEntities != null) { for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) { - model.addGrantedProtocolMapper(grantedProtMapper.getProtocolMapperId()); + ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId()); + model.addGrantedProtocolMapper(protocolMapper ); } } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java index 26322d4baa..ff6f14ce0d 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java @@ -32,6 +32,8 @@ public class ClientEntity { @Id @Column(name="ID", length = 36) private String id; + @Column(name = "NAME") + private String name; @Column(name = "CLIENT_ID") private String clientId; @Column(name="ENABLED") @@ -125,6 +127,14 @@ public class ClientEntity { this.id = id; } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public boolean isEnabled() { return enabled; } diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java index 9eae9f025a..b0784f5e32 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java @@ -27,20 +27,20 @@ import java.util.Set; */ public class ClientAdapter extends AbstractMongoAdapter implements ClientModel { - protected final MongoClientEntity applicationEntity; + protected final MongoClientEntity clientEntity; private final RealmModel realm; protected KeycloakSession session; - public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity applicationEntity, MongoStoreInvocationContext invContext) { + public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity clientEntity, MongoStoreInvocationContext invContext) { super(invContext); this.session = session; this.realm = realm; - this.applicationEntity = applicationEntity; + this.clientEntity = clientEntity; } @Override public MongoClientEntity getMongoEntity() { - return applicationEntity; + return clientEntity; } @Override @@ -59,6 +59,17 @@ public class ClientAdapter extends AbstractMongoAdapter imple return getMongoEntity().getClientId(); } + @Override + public String getName() { + return getMongoEntity().getName(); + } + + @Override + public void setName(String name) { + getMongoEntity().setName(name); + updateMongoEntity(); + } + @Override public void setClientId(String clientId) { getMongoEntity().setClientId(clientId); @@ -84,12 +95,12 @@ public class ClientAdapter extends AbstractMongoAdapter imple @Override public void addWebOrigin(String webOrigin) { - getMongoStore().pushItemToList(applicationEntity, "webOrigins", webOrigin, true, invocationContext); + getMongoStore().pushItemToList(clientEntity, "webOrigins", webOrigin, true, invocationContext); } @Override public void removeWebOrigin(String webOrigin) { - getMongoStore().pullItemFromList(applicationEntity, "webOrigins", webOrigin, invocationContext); + getMongoStore().pullItemFromList(clientEntity, "webOrigins", webOrigin, invocationContext); } @Override @@ -111,12 +122,12 @@ public class ClientAdapter extends AbstractMongoAdapter imple @Override public void addRedirectUri(String redirectUri) { - getMongoStore().pushItemToList(applicationEntity, "redirectUris", redirectUri, true, invocationContext); + getMongoStore().pushItemToList(clientEntity, "redirectUris", redirectUri, true, invocationContext); } @Override public void removeRedirectUri(String redirectUri) { - getMongoStore().pullItemFromList(applicationEntity, "redirectUris", redirectUri, invocationContext); + getMongoStore().pullItemFromList(clientEntity, "redirectUris", redirectUri, invocationContext); } @Override diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java index b0547930c3..1a4a9b5196 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java @@ -462,12 +462,22 @@ public class UserAdapter extends AbstractMongoAdapter implement } private UserConsentModel toConsentModel(UserConsentEntity entity) { - UserConsentModel model = new UserConsentModel(realm, entity.getClientId()); - for (String roleId : entity.getGrantedRoles()) { - model.addGrantedRole(roleId); + ClientModel client = realm.getClientById(entity.getClientId()); + if (client == null) { + throw new ModelException("Client with id " + entity.getClientId() + " is not available"); } + UserConsentModel model = new UserConsentModel(client); + + for (String roleId : entity.getGrantedRoles()) { + RoleModel roleModel = realm.getRoleById(roleId); + if (roleModel != null) { + model.addGrantedRole(roleModel); + } + } + for (String protMapperId : entity.getGrantedProtocolMappers()) { - model.addGrantedProtocolMapper(protMapperId); + ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protMapperId); + model.addGrantedProtocolMapper(protocolMapper); } return model; } diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java index e380441885..cc2c8ccb75 100644 --- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java +++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java @@ -118,6 +118,17 @@ public class ClientSessionAdapter implements ClientSessionModel { update(); } + @Override + public Set getProtocolMappers() { + return entity.getProtocolMappers(); + } + + @Override + public void setProtocolMappers(Set protocolMappers) { + entity.setProtocolMappers(protocolMappers); + update(); + } + @Override public String getAuthMethod() { return entity.getAuthMethod(); diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java index 9c085fcaa3..38d2ea56ac 100755 --- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java +++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java @@ -25,6 +25,7 @@ public class ClientSessionEntity extends SessionEntity { private ClientSessionModel.Action action; private Set roles; + private Set protocolMappers; private Map notes; public String getClient() { @@ -91,6 +92,14 @@ public class ClientSessionEntity extends SessionEntity { this.roles = roles; } + public Set getProtocolMappers() { + return protocolMappers; + } + + public void setProtocolMappers(Set protocolMappers) { + this.protocolMappers = protocolMappers; + } + public Map getNotes() { return notes; } diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java index ebb47b698a..74e795f830 100755 --- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java +++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java @@ -7,6 +7,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionModel; import org.keycloak.models.sessions.jpa.entities.ClientSessionEntity; import org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity; +import org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity; import org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity; import org.keycloak.models.sessions.jpa.entities.UserSessionEntity; @@ -177,4 +178,36 @@ public class ClientSessionAdapter implements ClientSessionModel { } return roles; } + + @Override + public Set getProtocolMappers() { + Set protMappers = new HashSet(); + if (entity.getProtocolMappers() != null) { + for (ClientSessionProtocolMapperEntity e : entity.getProtocolMappers()) { + protMappers.add(e.getProtocolMapperId()); + } + } + return protMappers; + } + + @Override + public void setProtocolMappers(Set protocolMappers) { + if (protocolMappers != null) { + for (String pm : protocolMappers) { + ClientSessionProtocolMapperEntity protMapperEntity = new ClientSessionProtocolMapperEntity(); + protMapperEntity.setClientSession(entity); + protMapperEntity.setProtocolMapperId(pm); + em.persist(protMapperEntity); + + entity.getProtocolMappers().add(protMapperEntity); + } + } else { + if (entity.getProtocolMappers() != null) { + for (ClientSessionProtocolMapperEntity pm : entity.getProtocolMappers()) { + em.remove(pm); + } + entity.getProtocolMappers().clear(); + } + } + } } diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java index 0731de33a8..23086d9470 100755 --- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java +++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java @@ -214,6 +214,10 @@ public class JpaUserSessionProvider implements UserSessionProvider { .setParameter("realmId", realm.getId()) .setParameter("userId", user.getId()) .executeUpdate(); + em.createNamedQuery("removeClientSessionProtMapperByUser") + .setParameter("realmId", realm.getId()) + .setParameter("userId", user.getId()) + .executeUpdate(); em.createNamedQuery("removeClientSessionByUser") .setParameter("realmId", realm.getId()) .setParameter("userId", user.getId()) @@ -238,6 +242,10 @@ public class JpaUserSessionProvider implements UserSessionProvider { .setParameter("realmId", realm.getId()) .setParameter("maxTime", dettachedClientSessionExpired) .executeUpdate(); + em.createNamedQuery("removeDetachedClientSessionProtMapperByExpired") + .setParameter("realmId", realm.getId()) + .setParameter("maxTime", dettachedClientSessionExpired) + .executeUpdate(); em.createNamedQuery("removeDetachedClientSessionNoteByExpired") .setParameter("realmId", realm.getId()) .setParameter("maxTime", dettachedClientSessionExpired) @@ -251,6 +259,11 @@ public class JpaUserSessionProvider implements UserSessionProvider { .setParameter("maxTime", maxTime) .setParameter("idleTime", idleTime) .executeUpdate(); + em.createNamedQuery("removeClientSessionProtMapperByExpired") + .setParameter("realmId", realm.getId()) + .setParameter("maxTime", maxTime) + .setParameter("idleTime", idleTime) + .executeUpdate(); em.createNamedQuery("removeClientSessionNoteByExpired") .setParameter("realmId", realm.getId()) .setParameter("maxTime", maxTime) @@ -277,6 +290,7 @@ public class JpaUserSessionProvider implements UserSessionProvider { public void removeUserSessions(RealmModel realm) { em.createNamedQuery("removeClientSessionNoteByRealm").setParameter("realmId", realm.getId()).executeUpdate(); em.createNamedQuery("removeClientSessionRoleByRealm").setParameter("realmId", realm.getId()).executeUpdate(); + em.createNamedQuery("removeClientSessionProtMapperByRealm").setParameter("realmId", realm.getId()).executeUpdate(); em.createNamedQuery("removeClientSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate(); em.createNamedQuery("removeUserSessionNoteByRealm").setParameter("realmId", realm.getId()).executeUpdate(); em.createNamedQuery("removeUserSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate(); @@ -292,6 +306,7 @@ public class JpaUserSessionProvider implements UserSessionProvider { public void onClientRemoved(RealmModel realm, ClientModel client) { em.createNamedQuery("removeClientSessionNoteByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate(); em.createNamedQuery("removeClientSessionRoleByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate(); + em.createNamedQuery("removeClientSessionProtMapperByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate(); em.createNamedQuery("removeClientSessionByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate(); } diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java index c4bbe06cdf..6f0c535539 100755 --- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java +++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java @@ -60,6 +60,9 @@ public class ClientSessionEntity { @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession") protected Collection roles = new ArrayList(); + @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession") + protected Collection protocolMappers = new ArrayList(); + @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession") protected Collection notes = new ArrayList(); @@ -127,6 +130,14 @@ public class ClientSessionEntity { this.roles = roles; } + public Collection getProtocolMappers() { + return protocolMappers; + } + + public void setProtocolMappers(Collection protocolMappers) { + this.protocolMappers = protocolMappers; + } + public Collection getNotes() { return notes; } diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionProtocolMapperEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionProtocolMapperEntity.java new file mode 100644 index 0000000000..628e0f36f3 --- /dev/null +++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionProtocolMapperEntity.java @@ -0,0 +1,98 @@ +package org.keycloak.models.sessions.jpa.entities; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; + +/** + * @author Marek Posolda + */ +@NamedQueries({ + @NamedQuery(name = "removeClientSessionProtMapperByUser", query="delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"), + @NamedQuery(name = "removeClientSessionProtMapperByClient", query="delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"), + @NamedQuery(name = "removeClientSessionProtMapperByRealm", query="delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"), + @NamedQuery(name = "removeClientSessionProtMapperByExpired", query = "delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"), + @NamedQuery(name = "removeDetachedClientSessionProtMapperByExpired", query = "delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )") +}) +@Table(name="CLIENT_SESSION_PROT_MAPPER") +@Entity +@IdClass(ClientSessionProtocolMapperEntity.Key.class) +public class ClientSessionProtocolMapperEntity { + + @Id + @ManyToOne(fetch= FetchType.LAZY) + @JoinColumn(name="CLIENT_SESSION") + protected ClientSessionEntity clientSession; + + @Id + @Column(name="PROTOCOL_MAPPER_ID") + protected String protocolMapperId; + + public ClientSessionEntity getClientSession() { + return clientSession; + } + + public void setClientSession(ClientSessionEntity clientSession) { + this.clientSession = clientSession; + } + + public String getProtocolMapperId() { + return protocolMapperId; + } + + public void setProtocolMapperId(String protocolMapperId) { + this.protocolMapperId = protocolMapperId; + } + + public static class Key implements Serializable { + + protected ClientSessionEntity clientSession; + + protected String protocolMapperId; + + public Key() { + } + + public Key(ClientSessionEntity clientSession, String protocolMapperId) { + this.clientSession = clientSession; + this.protocolMapperId = protocolMapperId; + } + + public ClientSessionEntity getClientSession() { + return clientSession; + } + + public String getProtocolMapperId() { + return protocolMapperId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Key key = (Key) o; + + if (!protocolMapperId.equals(key.protocolMapperId)) return false; + if (!clientSession.getId().equals(key.clientSession.getId())) return false; + + return true; + } + + @Override + public int hashCode() { + int result = clientSession.getId().hashCode(); + result = 31 * result + protocolMapperId.hashCode(); + return result; + } + } +} diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java index 62a3246bcd..daa6e3f572 100755 --- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java +++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java @@ -105,6 +105,16 @@ public class ClientSessionAdapter implements ClientSessionModel { return entity.getRoles(); } + @Override + public Set getProtocolMappers() { + return entity.getProtocolMappers(); + } + + @Override + public void setProtocolMappers(Set protocolMappers) { + entity.setProtocolMappers(protocolMappers); + } + @Override public String getNote(String name) { return entity.getNotes().get(name); diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java index dd945de793..ca304966ec 100755 --- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java +++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java @@ -23,6 +23,7 @@ public class ClientSessionEntity { private int timestamp; private ClientSessionModel.Action action; private Set roles; + private Set protocolMappers; private Map notes = new HashMap(); public String getId() { @@ -89,6 +90,14 @@ public class ClientSessionEntity { this.roles = roles; } + public Set getProtocolMappers() { + return protocolMappers; + } + + public void setProtocolMappers(Set protocolMappers) { + this.protocolMappers = protocolMappers; + } + public Map getNotes() { return notes; } diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java index 12efd4a368..649ffcf400 100755 --- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java +++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java @@ -120,6 +120,23 @@ public class ClientSessionAdapter extends AbstractMongoAdapter(entity.getRoles()) : null; } + @Override + public Set getProtocolMappers() { + return entity.getProtocolMappers() != null ? new HashSet(entity.getProtocolMappers()) : null; + } + + @Override + public void setProtocolMappers(Set protocolMappers) { + if (protocolMappers == null) { + entity.setProtocolMappers(null); + } else { + List list = new LinkedList(); + list.addAll(protocolMappers); + entity.setProtocolMappers(list); + } + updateMongoEntity(); + } + @Override public String getNote(String name) { return entity.getNotes().get(name); diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java index 91ec6820cb..b5abede7d9 100755 --- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java +++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java @@ -27,6 +27,7 @@ public class MongoClientSessionEntity extends AbstractIdentifiableEntity impleme private int timestamp; private ClientSessionModel.Action action; private List roles; + private List protocolMappers; private Map notes = new HashMap(); public String getId() { @@ -93,6 +94,14 @@ public class MongoClientSessionEntity extends AbstractIdentifiableEntity impleme this.roles = roles; } + public List getProtocolMappers() { + return protocolMappers; + } + + public void setProtocolMappers(List protocolMappers) { + this.protocolMappers = protocolMappers; + } + public Map getNotes() { return notes; } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java index 747c43cea8..315e685a3f 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java @@ -282,9 +282,8 @@ public class SamlProtocol implements LoginProtocol { List> loginResponseMappers = new LinkedList<>(); ProtocolMapperProcessor roleListMapper = null; - Set mappings = client.getProtocolMappers(); + Set mappings = accessCode.getRequestedProtocolMappers(); for (ProtocolMapperModel mapping : mappings) { - if (!mapping.getProtocol().equals(SamlProtocol.LOGIN_PROTOCOL)) continue; ProtocolMapper mapper = (ProtocolMapper)session.getKeycloakSessionFactory().getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); if (mapper == null) continue; diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java index 677b2bf64b..f4d5bd4afc 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java @@ -11,12 +11,14 @@ import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.protocol.saml.SamlProtocol; import org.keycloak.dom.saml.v2.assertion.AttributeStatementType; import org.keycloak.dom.saml.v2.assertion.AttributeType; +import org.keycloak.services.managers.ClientSessionCode; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; /** * @author Bill Burke @@ -96,8 +98,8 @@ public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRo List> roleNameMappers = new LinkedList<>(); KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); AttributeType singleAttributeType = null; - for (ProtocolMapperModel mapping : clientSession.getClient().getProtocolMappers()) { - if (!mapping.getProtocol().equals(SamlProtocol.LOGIN_PROTOCOL)) continue; + Set requestedProtocolMappers = new ClientSessionCode(clientSession.getRealm(), clientSession).getRequestedProtocolMappers(); + for (ProtocolMapperModel mapping : requestedProtocolMappers) { ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); if (mapper == null) continue; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java index 8d9ab8c7ea..f77fbddcf1 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java @@ -27,6 +27,7 @@ import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.IDToken; import org.keycloak.representations.RefreshToken; import org.keycloak.services.managers.AuthenticationManager; +import org.keycloak.services.managers.ClientSessionCode; import org.keycloak.util.Time; import javax.ws.rs.core.HttpHeaders; @@ -208,6 +209,14 @@ public class TokenManager { requestedRoles.add(r.getId()); } clientSession.setRoles(requestedRoles); + + Set requestedProtocolMappers = new HashSet(); + for (ProtocolMapperModel protocolMapper : clientSession.getClient().getProtocolMappers()) { + if (protocolMapper.getProtocol().equals(clientSession.getAuthMethod())) { + requestedProtocolMappers.add(protocolMapper.getId()); + } + } + clientSession.setProtocolMappers(requestedProtocolMappers); } public static void dettachClientSession(UserSessionProvider sessions, RealmModel realm, ClientSessionModel clientSession) { @@ -218,6 +227,7 @@ public class TokenManager { clientSession.setUserSession(null); clientSession.setRoles(null); + clientSession.setProtocolMappers(null); if (userSession.getClientSessions().isEmpty()) { sessions.removeUserSession(realm, userSession); @@ -274,23 +284,20 @@ public class TokenManager { public AccessToken transformAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) { - Set mappings = client.getProtocolMappers(); + Set mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers(); KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); for (ProtocolMapperModel mapping : mappings) { - if (!mapping.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) continue; ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); if (mapper == null || !(mapper instanceof OIDCAccessTokenMapper)) continue; token = ((OIDCAccessTokenMapper)mapper).transformAccessToken(token, mapping, session, userSession, clientSession); - - } return token; } public void transformIDToken(KeycloakSession session, IDToken token, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionModel clientSession) { - Set mappings = client.getProtocolMappers(); + Set mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers(); KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); for (ProtocolMapperModel mapping : mappings) { if (!mapping.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) continue; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java index f337163c0d..7900d901e0 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java @@ -27,6 +27,7 @@ import org.keycloak.events.Details; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventType; import org.keycloak.models.ClientModel; +import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; @@ -122,10 +123,11 @@ public class UserInfoEndpoint { } UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState()); + ClientSessionModel clientSession = session.sessions().getClientSession(token.getClientSession()); ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor()); UserModel userModel = userSession.getUser(); AccessToken userInfo = new AccessToken(); - tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, null); + tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, clientSession); event .detail(Details.USERNAME, userModel.getUsername()) diff --git a/services/src/main/java/org/keycloak/services/Urls.java b/services/src/main/java/org/keycloak/services/Urls.java index 0d3cc324b9..93b479b902 100755 --- a/services/src/main/java/org/keycloak/services/Urls.java +++ b/services/src/main/java/org/keycloak/services/Urls.java @@ -39,8 +39,8 @@ import java.net.URI; */ public class Urls { - public static URI accountAccessPage(URI baseUri, String realmId) { - return accountBase(baseUri).path(AccountService.class, "accessPage").build(realmId); + public static URI accountApplicationsPage(URI baseUri, String realmId) { + return accountBase(baseUri).path(AccountService.class, "applicationsPage").build(realmId); } public static UriBuilder accountBase(URI baseUri) { diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java index 7647b36345..8e363bb95f 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -439,8 +439,8 @@ public class AuthenticationManager { } List protocolMappers = new LinkedList(); - for (ProtocolMapperModel protocolMapper : client.getProtocolMappers()) { - if (protocolMapper.isConsentRequired() && protocolMapper.getProtocol().equals(clientSession.getAuthMethod()) && protocolMapper.getConsentText() != null) { + for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) { + if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) { if (grantedConsent == null || !grantedConsent.isProtocolMapperGranted(protocolMapper)) { protocolMappers.add(protocolMapper); } diff --git a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java index 9e52c9749b..99fc5f2678 100755 --- a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java +++ b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java @@ -2,6 +2,7 @@ package org.keycloak.services.managers; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel.RequiredAction; @@ -112,12 +113,25 @@ public class ClientSessionCode { for (String roleId : clientSession.getRoles()) { RoleModel role = realm.getRoleById(roleId); if (role != null) { - requestedRoles.add(realm.getRoleById(roleId)); + requestedRoles.add(role); } } return requestedRoles; } + public Set getRequestedProtocolMappers() { + Set requestedProtocolMappers = new HashSet(); + if (clientSession.getProtocolMappers() != null) { + for (String protocolMapperId : clientSession.getProtocolMappers()) { + ProtocolMapperModel protocolMapper = clientSession.getClient().getProtocolMapperById(protocolMapperId); + if (protocolMapper != null) { + requestedProtocolMappers.add(protocolMapper); + } + } + } + return requestedProtocolMappers; + } + public void setAction(ClientSessionModel.Action action) { clientSession.setAction(action); clientSession.setNote(ACTION_KEY, UUID.randomUUID().toString()); 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 8493397653..3d56a2a643 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -94,6 +94,7 @@ public class RealmManager { protected void setupAdminConsole(RealmModel realm) { ClientModel adminConsole = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID); if (adminConsole == null) adminConsole = new ClientManager(this).createClient(realm, Constants.ADMIN_CONSOLE_CLIENT_ID); + adminConsole.setName("${client_" + Constants.ADMIN_CONSOLE_CLIENT_ID + "}"); String baseUrl = contextPath + "/admin/" + realm.getName() + "/console"; adminConsole.setBaseUrl(baseUrl + "/index.html"); adminConsole.setEnabled(true); @@ -184,6 +185,7 @@ public class RealmManager { ClientModel realmAdminClient = realm.getClientByClientId(realmAdminClientId); if (realmAdminClient == null) { realmAdminClient = clientManager.createClient(realm, realmAdminClientId); + realmAdminClient.setName("${client_" + realmAdminClientId + "}"); } RoleModel adminRole = realmAdminClient.addRole(AdminRoles.REALM_ADMIN); adminRole.setDescription("${role_" + AdminRoles.REALM_ADMIN + "}"); @@ -202,6 +204,7 @@ public class RealmManager { ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); if (client == null) { client = new ClientManager(this).createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); + client.setName("${client_" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID + "}"); client.setEnabled(true); client.setFullScopeAllowed(false); String base = contextPath + "/realms/" + realm.getName() + "/account"; 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 3a775e1361..9b1edaedf6 100755 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -349,10 +349,10 @@ public class AccountService { return forwardToPage("sessions", AccountPages.SESSIONS); } - @Path("access") + @Path("applications") @GET - public Response accessPage() { - return forwardToPage("access", AccountPages.ACCESS); + public Response applicationsPage() { + return forwardToPage("applications", AccountPages.APPLICATIONS); } /** @@ -494,7 +494,7 @@ public class AccountService { @POST public Response processRevokeGrant(final MultivaluedMap formData) { if (auth == null) { - return login("access"); + return login("applications"); } require(AccountRoles.MANAGE_ACCOUNT); @@ -502,11 +502,11 @@ public class AccountService { String clientId = formData.getFirst("clientId"); if (clientId == null) { - return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.ACCESS); + return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS); } ClientModel client = realm.getClientById(clientId); if (client == null) { - return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.ACCESS); + return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS); } // Revoke grant in UserModel @@ -527,7 +527,7 @@ public class AccountService { event.event(EventType.REVOKE_GRANT).client(auth.getClient()).user(auth.getUser()).detail(Details.REVOKED_CLIENT, client.getClientId()).success(); setReferrerOnPage(); - return account.setSuccess(Messages.SUCCESS_GRANT_REVOKED).createResponse(AccountPages.ACCESS); + return account.setSuccess(Messages.SUCCESS_GRANT_REVOKED).createResponse(AccountPages.APPLICATIONS); } /** diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java index d4aa8d77d3..aeb3e2ad1d 100755 --- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java @@ -34,6 +34,7 @@ import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.login.LoginFormsProvider; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; +import org.keycloak.models.RoleModel; import org.keycloak.models.UserConsentModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ModelException; @@ -611,16 +612,15 @@ public class LoginActionsService { UserConsentModel grantedConsent = user.getConsentByClient(client.getId()); if (grantedConsent == null) { - grantedConsent = new UserConsentModel(realm, client.getId()); + grantedConsent = new UserConsentModel(client); user.addConsent(grantedConsent); } - for (String roleId : clientSession.getRoles()) { - grantedConsent.addGrantedRole(roleId); + for (RoleModel role : accessCode.getRequestedRoles()) { + grantedConsent.addGrantedRole(role); } - // TODO: It's not 100% sure that approved protocolMappers are same like the protocolMappers retrieved here from the client. Maybe clientSession.setProtocolMappers/getProtocolMappers should be added... - for (ProtocolMapperModel protocolMapper : client.getProtocolMappers()) { - if (protocolMapper.isConsentRequired() && protocolMapper.getProtocol().equals(clientSession.getAuthMethod()) && protocolMapper.getConsentText() != null) { - grantedConsent.addGrantedProtocolMapper(protocolMapper.getId()); + for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) { + if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) { + grantedConsent.addGrantedProtocolMapper(protocolMapper); } } user.updateConsent(grantedConsent); 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 73f7655877..526813bc6b 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 @@ -21,7 +21,7 @@ import org.keycloak.services.managers.RealmManager; import org.keycloak.services.resources.RealmsResource; import org.keycloak.testsuite.Constants; import org.keycloak.testsuite.OAuthClient; -import org.keycloak.testsuite.pages.AccountAccessPage; +import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.AccountUpdateProfilePage; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.OAuthGrantPage; @@ -89,7 +89,7 @@ public class ProfileTest { protected AccountUpdateProfilePage profilePage; @WebResource - protected AccountAccessPage accountAccessPage; + protected AccountApplicationsPage accountApplicationsPage; @WebResource protected LoginPage loginPage; @@ -191,8 +191,8 @@ public class ProfileTest { assertEquals("test-user@localhost", profile.getString("username")); - accountAccessPage.open(); - accountAccessPage.revokeGrant("third-party"); + accountApplicationsPage.open(); + accountApplicationsPage.revokeGrant("third-party"); } @Test diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java index 03124461e3..afee212b59 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java @@ -167,6 +167,7 @@ public class AdminAPITest { protected void checkAppUpdate(ClientRepresentation appRep, ClientRepresentation storedApp) { if (appRep.getClientId() != null) Assert.assertEquals(appRep.getClientId(), storedApp.getClientId()); + if (appRep.getName() != null) Assert.assertEquals(appRep.getName(), storedApp.getName()); if (appRep.isEnabled() != null) Assert.assertEquals(appRep.isEnabled(), storedApp.isEnabled()); if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly()); if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java index e1f4c832a5..686355c915 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java @@ -8,7 +8,7 @@ import org.keycloak.representations.AccessTokenResponse; import org.keycloak.services.Urls; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.Constants; -import org.keycloak.testsuite.pages.AccountAccessPage; +import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.OAuthGrantPage; import org.keycloak.testsuite.rule.AbstractKeycloakRule; import org.keycloak.testsuite.rule.WebResource; @@ -53,17 +53,17 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT private OAuthGrantPage grantPage; @WebResource - protected AccountAccessPage accountAccessPage; + protected AccountApplicationsPage accountApplicationsPage; @Override protected void revokeGrant() { String currentUrl = driver.getCurrentUrl(); - String accountAccessPath = Urls.accountAccessPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).port(PORT).build(), "realm-with-oidc-identity-provider").toString(); - accountAccessPage.setPath(accountAccessPath); - accountAccessPage.open(); + String accountAccessPath = Urls.accountApplicationsPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).port(PORT).build(), "realm-with-oidc-identity-provider").toString(); + accountApplicationsPage.setPath(accountAccessPath); + accountApplicationsPage.open(); try { - accountAccessPage.revokeGrant("broker-app"); + accountApplicationsPage.revokeGrant("broker-app"); } catch (NoSuchElementException e) { System.err.println("Couldn't revoke broker-app application, maybe because it wasn't granted or user not logged"); } diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java index e56d462506..efbefa6196 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java @@ -31,6 +31,7 @@ public class ClientModelTest extends AbstractModelTest { realm = realmManager.createRealm("original"); client = realm.addClient("application"); + client.setName("Application"); client.setBaseUrl("http://base"); client.setManagementUrl("http://management"); client.setClientId("app-name"); @@ -85,6 +86,7 @@ public class ClientModelTest extends AbstractModelTest { public static void assertEquals(ClientModel expected, ClientModel actual) { Assert.assertEquals(expected.getClientId(), actual.getClientId()); + Assert.assertEquals(expected.getName(), actual.getName()); Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl()); Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl()); Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java index bea52c4e09..317c101496 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java @@ -99,6 +99,7 @@ public class ImportTest extends AbstractModelTest { Assert.assertTrue(clients.values().contains(accountApp)); realm.getClients().containsAll(clients.values()); + Assert.assertEquals("Applicationn", application.getName()); Assert.assertEquals(50, application.getNodeReRegistrationTimeout()); Map appRegisteredNodes = application.getRegisteredNodes(); Assert.assertEquals(2, appRegisteredNodes.size()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java index 97cb24b408..92ef5dd26c 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java @@ -46,15 +46,15 @@ public class UserConsentModelTest extends AbstractModelTest { UserModel john = session.users().addUser(realm, "john"); UserModel mary = session.users().addUser(realm, "mary"); - UserConsentModel johnFooGrant = new UserConsentModel(realm, fooClient.getId()); - johnFooGrant.addGrantedRole(realmRole.getId()); - johnFooGrant.addGrantedRole(barClientRole.getId()); - johnFooGrant.addGrantedProtocolMapper(fooMapper.getId()); + UserConsentModel johnFooGrant = new UserConsentModel(fooClient); + johnFooGrant.addGrantedRole(realmRole); + johnFooGrant.addGrantedRole(barClientRole); + johnFooGrant.addGrantedProtocolMapper(fooMapper); john.addConsent(johnFooGrant); - UserConsentModel johnBarGrant = new UserConsentModel(realm, barClient.getId()); - johnBarGrant.addGrantedProtocolMapper(barMapper.getId()); - johnBarGrant.addGrantedRole(realmRole.getId()); + UserConsentModel johnBarGrant = new UserConsentModel(barClient); + johnBarGrant.addGrantedProtocolMapper(barMapper); + johnBarGrant.addGrantedRole(realmRole); // Update should fail as grant doesn't yet exists try { @@ -65,9 +65,9 @@ public class UserConsentModelTest extends AbstractModelTest { john.addConsent(johnBarGrant); - UserConsentModel maryFooGrant = new UserConsentModel(realm, fooClient.getId()); - maryFooGrant.addGrantedRole(realmRole.getId()); - maryFooGrant.addGrantedProtocolMapper(fooMapper.getId()); + UserConsentModel maryFooGrant = new UserConsentModel(fooClient); + maryFooGrant.addGrantedRole(realmRole); + maryFooGrant.addGrantedProtocolMapper(fooMapper); mary.addConsent(maryFooGrant); commit(); @@ -143,7 +143,7 @@ public class UserConsentModelTest extends AbstractModelTest { johnConsent.getGrantedRoles().remove(realmRole); RoleModel newRealmRole = realm.addRole("new-realm-role"); - johnConsent.addGrantedRole(newRealmRole.getId()); + johnConsent.addGrantedRole(newRealmRole); john.updateConsent(johnConsent); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java index b706203202..c5b236ac59 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java @@ -101,6 +101,9 @@ public class UserSessionProviderTest { assertEquals(2, session1.getRoles().size()); assertTrue(session1.getRoles().contains("one")); assertTrue(session1.getRoles().contains("two")); + assertEquals(2, session1.getProtocolMappers().size()); + assertTrue(session1.getProtocolMappers().contains("mapper-one")); + assertTrue(session1.getProtocolMappers().contains("mapper-two")); } @Test @@ -470,12 +473,13 @@ public class UserSessionProviderTest { assertNotNull(session.sessions().getUserLoginFailure(realm, "user2")); } - private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set roles) { + private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set roles, Set protocolMappers) { ClientSessionModel clientSession = session.sessions().createClientSession(realm, client); if (userSession != null) clientSession.setUserSession(userSession); clientSession.setRedirectUri(redirect); if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state); if (roles != null) clientSession.setRoles(roles); + if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers); return clientSession; } @@ -487,14 +491,18 @@ public class UserSessionProviderTest { roles.add("one"); roles.add("two"); - createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state", roles); - createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet()); + Set protocolMappers = new HashSet(); + protocolMappers.add("mapper-one"); + protocolMappers.add("mapper-two"); + + createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state", roles, protocolMappers); + createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet(), new HashSet()); sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null); - createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state", new HashSet()); + createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state", new HashSet(), new HashSet()); sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null); - createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state", new HashSet()); + createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state", new HashSet(), new HashSet()); resetSession(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountAccessPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountApplicationsPage.java similarity index 91% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountAccessPage.java rename to testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountApplicationsPage.java index 99b591abc0..fd13b9c2b0 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountAccessPage.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountApplicationsPage.java @@ -15,13 +15,13 @@ import org.openqa.selenium.WebElement; /** * @author Marek Posolda */ -public class AccountAccessPage extends AbstractAccountPage { +public class AccountApplicationsPage extends AbstractAccountPage { - private String path = Urls.accountAccessPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).build(), "test").toString(); + private String path = Urls.accountApplicationsPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).build(), "test").toString(); @Override public boolean isCurrent() { - return driver.getTitle().contains("Account Management") && driver.getCurrentUrl().endsWith("/account/access"); + return driver.getTitle().contains("Account Management") && driver.getCurrentUrl().endsWith("/account/applications"); } @Override diff --git a/testsuite/integration/src/test/resources/model/testrealm.json b/testsuite/integration/src/test/resources/model/testrealm.json index 1c0b7e64a2..e6d4d1887e 100755 --- a/testsuite/integration/src/test/resources/model/testrealm.json +++ b/testsuite/integration/src/test/resources/model/testrealm.json @@ -107,9 +107,10 @@ ] } ], - "applications": [ + "clients": [ { - "name": "Application", + "clientId": "Application", + "name": "Applicationn", "enabled": true, "nodeReRegistrationTimeout": 50, "registeredNodes": { @@ -118,7 +119,8 @@ } }, { - "name": "OtherApp", + "clientId": "OtherApp", + "name": "Other Application", "enabled": true, "protocolMappers" : [ {