broker token exchange refactor
This commit is contained in:
parent
f9b099d49d
commit
1f4df58e6c
43 changed files with 305 additions and 586 deletions
|
@ -129,8 +129,9 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
@Override
|
@Override
|
||||||
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
|
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
|
||||||
if (getConfig().getLogoutUrl() == null || getConfig().getLogoutUrl().trim().equals("")) return null;
|
if (getConfig().getLogoutUrl() == null || getConfig().getLogoutUrl().trim().equals("")) return null;
|
||||||
|
String sessionId = userSession.getId();
|
||||||
UriBuilder logoutUri = UriBuilder.fromUri(getConfig().getLogoutUrl())
|
UriBuilder logoutUri = UriBuilder.fromUri(getConfig().getLogoutUrl())
|
||||||
.queryParam("state", userSession.getId());
|
.queryParam("state", sessionId);
|
||||||
String idToken = userSession.getNote(FEDERATED_ID_TOKEN);
|
String idToken = userSession.getNote(FEDERATED_ID_TOKEN);
|
||||||
if (idToken != null) logoutUri.queryParam("id_token_hint", idToken);
|
if (idToken != null) logoutUri.queryParam("id_token_hint", idToken);
|
||||||
String redirect = RealmsResource.brokerUrl(uriInfo)
|
String redirect = RealmsResource.brokerUrl(uriInfo)
|
||||||
|
|
|
@ -7,6 +7,8 @@ import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.broker.provider.IdentityProvider;
|
import org.keycloak.broker.provider.IdentityProvider;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
|
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
|
||||||
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
|
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
|
||||||
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
||||||
|
@ -36,6 +38,7 @@ import org.keycloak.saml.common.util.StaxParserUtil;
|
||||||
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
|
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
|
||||||
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
|
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
|
||||||
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
|
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
|
||||||
|
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
|
||||||
import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
|
import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
|
||||||
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
|
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
|
||||||
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
|
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
|
||||||
|
@ -295,6 +298,19 @@ public class SAMLEndpoint {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (assertion.getAttributeStatements() != null ) {
|
||||||
|
for (AttributeStatementType attrStatement : assertion.getAttributeStatements()) {
|
||||||
|
for (AttributeStatementType.ASTChoiceType choice : attrStatement.getAttributes()) {
|
||||||
|
AttributeType attribute = choice.getAttribute();
|
||||||
|
if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attribute.getFriendlyName())
|
||||||
|
|| X500SAMLProfileConstants.EMAIL.get().equals(attribute.getName())) {
|
||||||
|
if (!attribute.getAttributeValue().isEmpty()) identity.setEmail(attribute.getAttributeValue().get(0).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
|
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
|
||||||
identity.setBrokerUserId(brokerUserId);
|
identity.setBrokerUserId(brokerUserId);
|
||||||
identity.setIdpConfig(config);
|
identity.setIdpConfig(config);
|
||||||
|
|
3
model/api/src/main/java/org/keycloak/migration/MigrationProvider.java
Normal file → Executable file
3
model/api/src/main/java/org/keycloak/migration/MigrationProvider.java
Normal file → Executable file
|
@ -1,9 +1,10 @@
|
||||||
package org.keycloak.migration;
|
package org.keycloak.migration;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Various common utils needed for migration from older version to newer
|
* Various common utils needed for migration from older version to newer
|
||||||
*
|
*
|
||||||
|
|
|
@ -116,10 +116,6 @@ public interface ClientModel extends RoleContainerModel {
|
||||||
|
|
||||||
void setNotBefore(int notBefore);
|
void setNotBefore(int notBefore);
|
||||||
|
|
||||||
void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders);
|
|
||||||
List<ClientIdentityProviderMappingModel> getIdentityProviders();
|
|
||||||
boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId);
|
|
||||||
|
|
||||||
Set<ProtocolMapperModel> getProtocolMappers();
|
Set<ProtocolMapperModel> getProtocolMappers();
|
||||||
ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model);
|
ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model);
|
||||||
void removeProtocolMapper(ProtocolMapperModel mapping);
|
void removeProtocolMapper(ProtocolMapperModel mapping);
|
||||||
|
|
|
@ -8,6 +8,7 @@ public interface Constants {
|
||||||
String ADMIN_CONSOLE_CLIENT_ID = "security-admin-console";
|
String ADMIN_CONSOLE_CLIENT_ID = "security-admin-console";
|
||||||
|
|
||||||
String ACCOUNT_MANAGEMENT_CLIENT_ID = "account";
|
String ACCOUNT_MANAGEMENT_CLIENT_ID = "account";
|
||||||
|
String BROKER_SERVICE_CLIENT_ID = "broker";
|
||||||
|
|
||||||
String INSTALLED_APP_URN = "urn:ietf:wg:oauth:2.0:oob";
|
String INSTALLED_APP_URN = "urn:ietf:wg:oauth:2.0:oob";
|
||||||
String INSTALLED_APP_URL = "http://localhost";
|
String INSTALLED_APP_URL = "http://localhost";
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
|
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -8,8 +10,6 @@ import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.entities;
|
package org.keycloak.models.entities;
|
||||||
|
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.models.utils;
|
package org.keycloak.models.utils;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
|
||||||
import org.keycloak.models.ClientSessionModel;
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
|
@ -14,8 +13,6 @@ import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
|
||||||
import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation;
|
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||||
|
@ -261,10 +258,6 @@ public class ModelToRepresentation {
|
||||||
rep.setRegisteredNodes(new HashMap<>(clientModel.getRegisteredNodes()));
|
rep.setRegisteredNodes(new HashMap<>(clientModel.getRegisteredNodes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clientModel.getIdentityProviders().isEmpty()) {
|
|
||||||
rep.setIdentityProviders(toRepresentation(clientModel.getIdentityProviders()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!clientModel.getProtocolMappers().isEmpty()) {
|
if (!clientModel.getProtocolMappers().isEmpty()) {
|
||||||
List<ProtocolMapperRepresentation> mappings = new LinkedList<>();
|
List<ProtocolMapperRepresentation> mappings = new LinkedList<>();
|
||||||
for (ProtocolMapperModel model : clientModel.getProtocolMappers()) {
|
for (ProtocolMapperModel model : clientModel.getProtocolMappers()) {
|
||||||
|
@ -276,21 +269,6 @@ public class ModelToRepresentation {
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ClientIdentityProviderMappingRepresentation> toRepresentation(List<ClientIdentityProviderMappingModel> identityProviders) {
|
|
||||||
ArrayList<ClientIdentityProviderMappingRepresentation> representations = new ArrayList<ClientIdentityProviderMappingRepresentation>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingModel model : identityProviders) {
|
|
||||||
ClientIdentityProviderMappingRepresentation representation = new ClientIdentityProviderMappingRepresentation();
|
|
||||||
|
|
||||||
representation.setId(model.getIdentityProvider());
|
|
||||||
representation.setRetrieveToken(model.isRetrieveToken());
|
|
||||||
|
|
||||||
representations.add(representation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return representations;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
|
public static UserFederationProviderRepresentation toRepresentation(UserFederationProviderModel model) {
|
||||||
UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
|
UserFederationProviderRepresentation rep = new UserFederationProviderRepresentation();
|
||||||
rep.setId(model.getId());
|
rep.setId(model.getId());
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.keycloak.enums.SslRequired;
|
||||||
import org.keycloak.migration.MigrationProvider;
|
import org.keycloak.migration.MigrationProvider;
|
||||||
import org.keycloak.models.BrowserSecurityHeaders;
|
import org.keycloak.models.BrowserSecurityHeaders;
|
||||||
import org.keycloak.models.ClaimMask;
|
import org.keycloak.models.ClaimMask;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
|
@ -22,7 +21,6 @@ import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||||
import org.keycloak.representations.idm.ClaimRepresentation;
|
import org.keycloak.representations.idm.ClaimRepresentation;
|
||||||
import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation;
|
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||||
|
@ -39,7 +37,6 @@ import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.util.UriUtils;
|
import org.keycloak.util.UriUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -610,8 +607,6 @@ public class RepresentationToModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.updateIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm));
|
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,7 +655,6 @@ public class RepresentationToModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateClientIdentityProviders(rep.getIdentityProviders(), resource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getClaimsMask(ClaimRepresentation rep) {
|
public static long getClaimsMask(ClaimRepresentation rep) {
|
||||||
|
@ -887,37 +881,4 @@ public class RepresentationToModel {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ClientIdentityProviderMappingModel> toModel(List<ClientIdentityProviderMappingRepresentation> repIdentityProviders, RealmModel realm) {
|
|
||||||
List<ClientIdentityProviderMappingModel> result = new ArrayList<ClientIdentityProviderMappingModel>();
|
|
||||||
|
|
||||||
if (repIdentityProviders != null) {
|
|
||||||
for (ClientIdentityProviderMappingRepresentation rep : repIdentityProviders) {
|
|
||||||
ClientIdentityProviderMappingModel identityProviderMapping = new ClientIdentityProviderMappingModel();
|
|
||||||
|
|
||||||
identityProviderMapping.setIdentityProvider(rep.getId());
|
|
||||||
identityProviderMapping.setRetrieveToken(rep.isRetrieveToken());
|
|
||||||
|
|
||||||
result.add(identityProviderMapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void updateClientIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders, ClientModel resource) {
|
|
||||||
if (identityProviders != null) {
|
|
||||||
List<ClientIdentityProviderMappingModel> result = new ArrayList<ClientIdentityProviderMappingModel>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingRepresentation mappingRepresentation : identityProviders) {
|
|
||||||
ClientIdentityProviderMappingModel identityProviderMapping = new ClientIdentityProviderMappingModel();
|
|
||||||
|
|
||||||
identityProviderMapping.setIdentityProvider(mappingRepresentation.getId());
|
|
||||||
identityProviderMapping.setRetrieveToken(mappingRepresentation.isRetrieveToken());
|
|
||||||
|
|
||||||
result.add(identityProviderMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
resource.updateIdentityProviders(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
4
model/api/src/main/java/org/keycloak/models/utils/reflection/MethodPropertyImpl.java
Normal file → Executable file
4
model/api/src/main/java/org/keycloak/models/utils/reflection/MethodPropertyImpl.java
Normal file → Executable file
|
@ -1,13 +1,13 @@
|
||||||
package org.keycloak.models.utils.reflection;
|
package org.keycloak.models.utils.reflection;
|
||||||
|
|
||||||
|
import org.keycloak.util.reflections.Reflections;
|
||||||
|
|
||||||
import java.beans.Introspector;
|
import java.beans.Introspector;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
import org.keycloak.util.reflections.Reflections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bean property based on the value represented by a getter/setter method pair
|
* A bean property based on the value represented by a getter/setter method pair
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.provider;
|
package org.keycloak.provider;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderConfigProperty;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package org.keycloak.provider;
|
package org.keycloak.provider;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderEvent;
|
|
||||||
import org.keycloak.provider.ProviderEventListener;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
|
|
8
model/api/src/test/java/org/keycloak/models/PasswordPolicyTest.java
Normal file → Executable file
8
model/api/src/test/java/org/keycloak/models/PasswordPolicyTest.java
Normal file → Executable file
|
@ -1,12 +1,12 @@
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.util.regex.PatternSyntaxException;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
27
model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
Normal file → Executable file
27
model/file/src/main/java/org/keycloak/models/file/FileUserProvider.java
Normal file → Executable file
|
@ -16,34 +16,33 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.file;
|
package org.keycloak.models.file;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import org.keycloak.connections.file.FileConnectionProvider;
|
||||||
import java.util.Collections;
|
import org.keycloak.connections.file.InMemoryModel;
|
||||||
import java.util.HashSet;
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.CredentialValidationOutput;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
|
||||||
import org.keycloak.models.file.adapter.UserAdapter;
|
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserProvider;
|
import org.keycloak.models.UserProvider;
|
||||||
|
import org.keycloak.models.entities.FederatedIdentityEntity;
|
||||||
|
import org.keycloak.models.entities.UserEntity;
|
||||||
|
import org.keycloak.models.file.adapter.UserAdapter;
|
||||||
|
import org.keycloak.models.utils.CredentialValidation;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import org.keycloak.connections.file.FileConnectionProvider;
|
|
||||||
import org.keycloak.connections.file.InMemoryModel;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.CredentialValidationOutput;
|
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
|
||||||
import org.keycloak.models.entities.FederatedIdentityEntity;
|
|
||||||
import org.keycloak.models.entities.UserEntity;
|
|
||||||
import org.keycloak.models.utils.CredentialValidation;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserProvider for JSON persistence.
|
* UserProvider for JSON persistence.
|
||||||
|
|
|
@ -16,12 +16,18 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.file.adapter;
|
package org.keycloak.models.file.adapter;
|
||||||
|
|
||||||
|
import org.keycloak.connections.file.InMemoryModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.entities.ClientEntity;
|
||||||
|
import org.keycloak.models.entities.ProtocolMapperEntity;
|
||||||
|
import org.keycloak.models.entities.RoleEntity;
|
||||||
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -30,14 +36,6 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.keycloak.connections.file.InMemoryModel;
|
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.models.entities.ClientEntity;
|
|
||||||
import org.keycloak.models.entities.ClientIdentityProviderMappingEntity;
|
|
||||||
import org.keycloak.models.entities.ProtocolMapperEntity;
|
|
||||||
import org.keycloak.models.entities.RoleEntity;
|
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ApplicationModel used for JSON persistence.
|
* ApplicationModel used for JSON persistence.
|
||||||
|
@ -362,48 +360,6 @@ public class ClientAdapter implements ClientModel {
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
|
|
||||||
List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingModel model : identityProviders) {
|
|
||||||
ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
|
|
||||||
|
|
||||||
entity.setId(model.getIdentityProvider());
|
|
||||||
entity.setRetrieveToken(model.isRetrieveToken());
|
|
||||||
stored.add(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.setIdentityProviders(stored);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
|
|
||||||
List<ClientIdentityProviderMappingModel> models = new ArrayList<>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingEntity e : entity.getIdentityProviders()) {
|
|
||||||
ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
|
|
||||||
|
|
||||||
model.setIdentityProvider(e.getId());
|
|
||||||
model.setRetrieveToken(e.isRetrieveToken());
|
|
||||||
|
|
||||||
models.add(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
return models;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
|
|
||||||
for (ClientIdentityProviderMappingEntity identityProviderMappingModel : entity.getIdentityProviders()) {
|
|
||||||
if (identityProviderMappingModel.getId().equals(providerId)) {
|
|
||||||
return identityProviderMappingModel.isRetrieveToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClientId() {
|
public String getClientId() {
|
||||||
return entity.getClientId();
|
return entity.getClientId();
|
||||||
|
|
|
@ -16,18 +16,18 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.file.adapter;
|
package org.keycloak.models.file.adapter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
import java.util.Collections;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleContainerModel;
|
import org.keycloak.models.RoleContainerModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.entities.RoleEntity;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
|
||||||
import org.keycloak.models.entities.RoleEntity;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RoleModel for JSON persistence.
|
* RoleModel for JSON persistence.
|
||||||
|
|
|
@ -16,11 +16,10 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.models.file.adapter;
|
package org.keycloak.models.file.adapter;
|
||||||
|
|
||||||
|
import org.keycloak.connections.file.InMemoryModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
|
||||||
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
|
||||||
|
|
||||||
import org.keycloak.models.GrantedConsentModel;
|
import org.keycloak.models.GrantedConsentModel;
|
||||||
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
import org.keycloak.models.PasswordPolicy;
|
import org.keycloak.models.PasswordPolicy;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
@ -28,7 +27,11 @@ import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserCredentialValueModel;
|
import org.keycloak.models.UserCredentialValueModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.entities.CredentialEntity;
|
import org.keycloak.models.entities.CredentialEntity;
|
||||||
|
import org.keycloak.models.entities.FederatedIdentityEntity;
|
||||||
|
import org.keycloak.models.entities.RoleEntity;
|
||||||
|
import org.keycloak.models.entities.UserEntity;
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
||||||
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -39,12 +42,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.keycloak.connections.file.InMemoryModel;
|
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
|
||||||
import org.keycloak.models.entities.FederatedIdentityEntity;
|
|
||||||
import org.keycloak.models.entities.RoleEntity;
|
|
||||||
import org.keycloak.models.entities.UserEntity;
|
|
||||||
import org.keycloak.util.Time;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserModel for JSON persistence.
|
* UserModel for JSON persistence.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.models.cache;
|
package org.keycloak.models.cache;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleContainerModel;
|
import org.keycloak.models.RoleContainerModel;
|
||||||
|
@ -249,24 +248,6 @@ public class ClientAdapter implements ClientModel {
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
|
|
||||||
getDelegateForUpdate();
|
|
||||||
updated.updateIdentityProviders(identityProviders);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
|
|
||||||
if (updated != null) return updated.getIdentityProviders();
|
|
||||||
return cached.getIdentityProviders();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
|
|
||||||
if (updated != null) return updated.isAllowedRetrieveTokenFromIdentityProvider(providerId);
|
|
||||||
return cached.isAllowedRetrieveTokenFromIdentityProvider(providerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ProtocolMapperModel> getProtocolMappers() {
|
public Set<ProtocolMapperModel> getProtocolMappers() {
|
||||||
if (updated != null) return updated.getProtocolMappers();
|
if (updated != null) return updated.getProtocolMappers();
|
||||||
|
|
|
@ -2,12 +2,12 @@ package org.keycloak.models.cache;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.CredentialValidationOutput;
|
import org.keycloak.models.CredentialValidationOutput;
|
||||||
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakTransaction;
|
import org.keycloak.models.KeycloakTransaction;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
|
|
@ -2,11 +2,11 @@ package org.keycloak.models.cache;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.CredentialValidationOutput;
|
import org.keycloak.models.CredentialValidationOutput;
|
||||||
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserFederationProviderModel;
|
import org.keycloak.models.UserFederationProviderModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
package org.keycloak.models.cache.entities;
|
package org.keycloak.models.cache.entities;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RealmProvider;
|
import org.keycloak.models.RealmProvider;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.cache.RealmCache;
|
import org.keycloak.models.cache.RealmCache;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -37,7 +35,6 @@ public class CachedClient {
|
||||||
private int notBefore;
|
private int notBefore;
|
||||||
private Set<String> scope = new HashSet<String>();
|
private Set<String> scope = new HashSet<String>();
|
||||||
private Set<String> webOrigins = new HashSet<String>();
|
private Set<String> webOrigins = new HashSet<String>();
|
||||||
private List<ClientIdentityProviderMappingModel> identityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
|
|
||||||
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
|
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
|
||||||
private boolean surrogateAuthRequired;
|
private boolean surrogateAuthRequired;
|
||||||
private String managementUrl;
|
private String managementUrl;
|
||||||
|
@ -67,7 +64,6 @@ public class CachedClient {
|
||||||
for (RoleModel role : model.getScopeMappings()) {
|
for (RoleModel role : model.getScopeMappings()) {
|
||||||
scope.add(role.getId());
|
scope.add(role.getId());
|
||||||
}
|
}
|
||||||
this.identityProviders = model.getIdentityProviders();
|
|
||||||
for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
|
for (ProtocolMapperModel mapper : model.getProtocolMappers()) {
|
||||||
this.protocolMappers.add(mapper);
|
this.protocolMappers.add(mapper);
|
||||||
}
|
}
|
||||||
|
@ -145,34 +141,10 @@ public class CachedClient {
|
||||||
return frontchannelLogout;
|
return frontchannelLogout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
|
|
||||||
return this.identityProviders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasIdentityProvider(String providerId) {
|
|
||||||
for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
|
|
||||||
if (model.getIdentityProvider().equals(providerId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<ProtocolMapperModel> getProtocolMappers() {
|
public Set<ProtocolMapperModel> getProtocolMappers() {
|
||||||
return protocolMappers;
|
return protocolMappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
|
|
||||||
for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
|
|
||||||
if (model.getIdentityProvider().equals(providerId)) {
|
|
||||||
return model.isRetrieveToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSurrogateAuthRequired() {
|
public boolean isSurrogateAuthRequired() {
|
||||||
return surrogateAuthRequired;
|
return surrogateAuthRequired;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
package org.keycloak.models.jpa;
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleContainerModel;
|
import org.keycloak.models.RoleContainerModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.jpa.entities.ClientEntity;
|
import org.keycloak.models.jpa.entities.ClientEntity;
|
||||||
import org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity;
|
|
||||||
import org.keycloak.models.jpa.entities.IdentityProviderEntity;
|
|
||||||
import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
|
import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
|
||||||
import org.keycloak.models.jpa.entities.RoleEntity;
|
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||||
import org.keycloak.models.jpa.entities.ScopeMappingEntity;
|
import org.keycloak.models.jpa.entities.ScopeMappingEntity;
|
||||||
|
@ -263,88 +260,6 @@ public class ClientAdapter implements ClientModel {
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
|
|
||||||
Collection<ClientIdentityProviderMappingEntity> entities = entity.getIdentityProviders();
|
|
||||||
Set<String> already = new HashSet<>();
|
|
||||||
List<ClientIdentityProviderMappingEntity> remove = new ArrayList<>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingEntity entity : entities) {
|
|
||||||
IdentityProviderEntity identityProvider = entity.getIdentityProvider();
|
|
||||||
boolean toRemove = true;
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingModel model : identityProviders) {
|
|
||||||
if (model.getIdentityProvider().equals(identityProvider.getAlias())) {
|
|
||||||
toRemove = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toRemove) {
|
|
||||||
remove.add(entity);
|
|
||||||
} else {
|
|
||||||
already.add(entity.getIdentityProvider().getAlias());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ClientIdentityProviderMappingEntity entity : remove) {
|
|
||||||
entities.remove(entity);
|
|
||||||
em.remove(entity);
|
|
||||||
}
|
|
||||||
em.flush();
|
|
||||||
for (ClientIdentityProviderMappingModel model : identityProviders) {
|
|
||||||
ClientIdentityProviderMappingEntity mappingEntity = null;
|
|
||||||
|
|
||||||
if (!already.contains(model.getIdentityProvider())) {
|
|
||||||
mappingEntity = new ClientIdentityProviderMappingEntity();
|
|
||||||
entities.add(mappingEntity);
|
|
||||||
} else {
|
|
||||||
for (ClientIdentityProviderMappingEntity entity : entities) {
|
|
||||||
if (entity.getIdentityProvider().getAlias().equals(model.getIdentityProvider())) {
|
|
||||||
mappingEntity = entity;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TypedQuery<IdentityProviderEntity> query = em.createNamedQuery("findIdentityProviderByAlias", IdentityProviderEntity.class).setParameter("alias", model.getIdentityProvider());
|
|
||||||
IdentityProviderEntity identityProviderEntity = query.getSingleResult();
|
|
||||||
|
|
||||||
mappingEntity.setIdentityProvider(identityProviderEntity);
|
|
||||||
mappingEntity.setClient(this.entity);
|
|
||||||
mappingEntity.setRetrieveToken(model.isRetrieveToken());
|
|
||||||
|
|
||||||
em.persist(mappingEntity);
|
|
||||||
}
|
|
||||||
em.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
|
|
||||||
List<ClientIdentityProviderMappingModel> models = new ArrayList<ClientIdentityProviderMappingModel>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingEntity entity : this.entity.getIdentityProviders()) {
|
|
||||||
ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
|
|
||||||
|
|
||||||
model.setIdentityProvider(entity.getIdentityProvider().getAlias());
|
|
||||||
model.setRetrieveToken(entity.isRetrieveToken());
|
|
||||||
|
|
||||||
models.add(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
return models;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
|
|
||||||
for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
|
|
||||||
if (model.getIdentityProvider().equals(providerId)) {
|
|
||||||
return model.isRetrieveToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean contains(String str, String[] array) {
|
public static boolean contains(String str, String[] array) {
|
||||||
for (String s : array) {
|
for (String s : array) {
|
||||||
if (str.equals(s)) return true;
|
if (str.equals(s)) return true;
|
||||||
|
|
|
@ -25,12 +25,10 @@ import org.keycloak.util.Time;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
10
model/jpa/src/main/java/org/keycloak/models/jpa/entities/GrantedConsentEntity.java
Normal file → Executable file
10
model/jpa/src/main/java/org/keycloak/models/jpa/entities/GrantedConsentEntity.java
Normal file → Executable file
|
@ -1,25 +1,19 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.CollectionTable;
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.ElementCollection;
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
|
3
model/jpa/src/main/java/org/keycloak/models/jpa/entities/GrantedConsentProtocolMapperEntity.java
Normal file → Executable file
3
model/jpa/src/main/java/org/keycloak/models/jpa/entities/GrantedConsentProtocolMapperEntity.java
Normal file → Executable file
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
|
@ -12,6 +10,7 @@ import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
|
3
model/jpa/src/main/java/org/keycloak/models/jpa/entities/GrantedConsentRoleEntity.java
Normal file → Executable file
3
model/jpa/src/main/java/org/keycloak/models/jpa/entities/GrantedConsentRoleEntity.java
Normal file → Executable file
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
|
@ -12,6 +10,7 @@ import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.NamedQueries;
|
import javax.persistence.NamedQueries;
|
||||||
import javax.persistence.NamedQuery;
|
import javax.persistence.NamedQuery;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
|
|
@ -4,12 +4,10 @@ import com.mongodb.DBObject;
|
||||||
import com.mongodb.QueryBuilder;
|
import com.mongodb.QueryBuilder;
|
||||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.entities.ClientIdentityProviderMappingEntity;
|
|
||||||
import org.keycloak.models.entities.ProtocolMapperEntity;
|
import org.keycloak.models.entities.ProtocolMapperEntity;
|
||||||
import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
|
import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
|
||||||
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
|
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
|
||||||
|
@ -396,49 +394,6 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
|
|
||||||
List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingModel model : identityProviders) {
|
|
||||||
ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
|
|
||||||
|
|
||||||
entity.setId(model.getIdentityProvider());
|
|
||||||
entity.setRetrieveToken(model.isRetrieveToken());
|
|
||||||
stored.add(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMongoEntity().setIdentityProviders(stored);
|
|
||||||
updateMongoEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
|
|
||||||
List<ClientIdentityProviderMappingModel> models = new ArrayList<ClientIdentityProviderMappingModel>();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingEntity entity : getMongoEntity().getIdentityProviders()) {
|
|
||||||
ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
|
|
||||||
|
|
||||||
model.setIdentityProvider(entity.getId());
|
|
||||||
model.setRetrieveToken(entity.isRetrieveToken());
|
|
||||||
|
|
||||||
models.add(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
return models;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
|
|
||||||
for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntity().getIdentityProviders()) {
|
|
||||||
if (identityProviderMappingModel.getId().equals(providerId)) {
|
|
||||||
return identityProviderMappingModel.isRetrieveToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSurrogateAuthRequired() {
|
public boolean isSurrogateAuthRequired() {
|
||||||
return getMongoEntity().isSurrogateAuthRequired();
|
return getMongoEntity().isSurrogateAuthRequired();
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.adapters;
|
package org.keycloak.models.mongo.keycloak.adapters;
|
||||||
|
|
||||||
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
|
||||||
|
|
||||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.GrantedConsentModel;
|
import org.keycloak.models.GrantedConsentModel;
|
||||||
|
@ -22,13 +20,14 @@ import org.keycloak.util.Time;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based idm)
|
* Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based idm)
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.keycloak.models.utils.RepresentationToModel;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.services.resources.IdentityBrokerService;
|
||||||
import org.keycloak.timer.TimerProvider;
|
import org.keycloak.timer.TimerProvider;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -84,6 +85,7 @@ public class RealmManager {
|
||||||
setupMasterAdminManagement(realm);
|
setupMasterAdminManagement(realm);
|
||||||
setupRealmAdminManagement(realm);
|
setupRealmAdminManagement(realm);
|
||||||
setupAccountManagement(realm);
|
setupAccountManagement(realm);
|
||||||
|
setupBrokerService(realm);
|
||||||
setupAdminConsole(realm);
|
setupAdminConsole(realm);
|
||||||
|
|
||||||
return realm;
|
return realm;
|
||||||
|
@ -214,6 +216,19 @@ public class RealmManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setupBrokerService(RealmModel realm) {
|
||||||
|
ClientModel client = realm.getClientNameMap().get(Constants.BROKER_SERVICE_CLIENT_ID);
|
||||||
|
if (client == null) {
|
||||||
|
client = new ClientManager(this).createClient(realm, Constants.BROKER_SERVICE_CLIENT_ID);
|
||||||
|
client.setEnabled(true);
|
||||||
|
client.setFullScopeAllowed(false);
|
||||||
|
|
||||||
|
for (String role : IdentityBrokerService.ROLES) {
|
||||||
|
client.addRole(role).setDescription("${role_"+role+"}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public RealmModel importRealm(RealmRepresentation rep) {
|
public RealmModel importRealm(RealmRepresentation rep) {
|
||||||
String id = rep.getId();
|
String id = rep.getId();
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
|
@ -228,6 +243,7 @@ public class RealmManager {
|
||||||
setupMasterAdminManagement(realm);
|
setupMasterAdminManagement(realm);
|
||||||
if (!hasRealmAdminManagementClient(rep)) setupRealmAdminManagement(realm);
|
if (!hasRealmAdminManagementClient(rep)) setupRealmAdminManagement(realm);
|
||||||
if (!hasAccountManagementClient(rep)) setupAccountManagement(realm);
|
if (!hasAccountManagementClient(rep)) setupAccountManagement(realm);
|
||||||
|
if (!hasBrokerClient(rep)) setupBrokerService(realm);
|
||||||
if (!hasAdminConsoleClient(rep)) setupAdminConsole(realm);
|
if (!hasAdminConsoleClient(rep)) setupAdminConsole(realm);
|
||||||
|
|
||||||
RepresentationToModel.importRealm(session, rep, realm);
|
RepresentationToModel.importRealm(session, rep, realm);
|
||||||
|
@ -260,6 +276,15 @@ public class RealmManager {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
private boolean hasBrokerClient(RealmRepresentation rep) {
|
||||||
|
if (rep.getClients() == null) return false;
|
||||||
|
for (ClientRepresentation clientRep : rep.getClients()) {
|
||||||
|
if (clientRep.getClientId().equals(Constants.BROKER_SERVICE_CLIENT_ID)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasAdminConsoleClient(RealmRepresentation rep) {
|
private boolean hasAdminConsoleClient(RealmRepresentation rep) {
|
||||||
if (rep.getClients() == null) return false;
|
if (rep.getClients() == null) return false;
|
||||||
|
|
|
@ -34,17 +34,20 @@ import org.keycloak.events.EventType;
|
||||||
import org.keycloak.login.LoginFormsProvider;
|
import org.keycloak.login.LoginFormsProvider;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientSessionModel;
|
import org.keycloak.models.ClientSessionModel;
|
||||||
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapper;
|
import org.keycloak.protocol.ProtocolMapper;
|
||||||
import org.keycloak.protocol.oidc.TokenManager;
|
import org.keycloak.protocol.oidc.TokenManager;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.services.managers.AppAuthManager;
|
import org.keycloak.services.managers.AppAuthManager;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
|
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
|
||||||
|
@ -92,6 +95,8 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(IdentityBrokerService.class);
|
private static final Logger LOGGER = Logger.getLogger(IdentityBrokerService.class);
|
||||||
public static final String BROKER_PROVIDER_ID = "BROKER_PROVIDER_ID";
|
public static final String BROKER_PROVIDER_ID = "BROKER_PROVIDER_ID";
|
||||||
|
public static final String READ_TOKEN_ROLE = "READ_TOKEN";
|
||||||
|
public static final String[] ROLES = {READ_TOKEN_ROLE};
|
||||||
|
|
||||||
private final RealmModel realmModel;
|
private final RealmModel realmModel;
|
||||||
|
|
||||||
|
@ -185,7 +190,8 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
AuthResult authResult = authManager.authenticateBearerToken(this.session, this.realmModel, this.uriInfo, this.clientConnection, this.request.getHttpHeaders());
|
AuthResult authResult = authManager.authenticateBearerToken(this.session, this.realmModel, this.uriInfo, this.clientConnection, this.request.getHttpHeaders());
|
||||||
|
|
||||||
if (authResult != null) {
|
if (authResult != null) {
|
||||||
String audience = authResult.getToken().getAudience();
|
AccessToken token = authResult.getToken();
|
||||||
|
String audience = token.getAudience();
|
||||||
ClientModel clientModel = this.realmModel.getClientByClientId(audience);
|
ClientModel clientModel = this.realmModel.getClientByClientId(audience);
|
||||||
|
|
||||||
if (clientModel == null) {
|
if (clientModel == null) {
|
||||||
|
@ -194,16 +200,16 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
|
|
||||||
session.getContext().setClient(clientModel);
|
session.getContext().setClient(clientModel);
|
||||||
|
|
||||||
if (!clientModel.isAllowedRetrieveTokenFromIdentityProvider(providerId)) {
|
ClientModel brokerClient = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID);
|
||||||
return corsResponse(badRequest("Client [" + audience + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
|
if (brokerClient == null) {
|
||||||
}
|
return corsResponse(forbidden("Realm has not migrated to support the broker token exchange service"), clientModel);
|
||||||
|
|
||||||
|
}
|
||||||
|
Map<String, AccessToken.Access> resourceAccess = token.getResourceAccess();
|
||||||
|
AccessToken.Access brokerRoles = resourceAccess == null ? null : resourceAccess.get(Constants.BROKER_SERVICE_CLIENT_ID);
|
||||||
|
if (brokerRoles == null || !brokerRoles.isUserInRole(READ_TOKEN_ROLE)) {
|
||||||
|
return corsResponse(forbidden("Client [" + audience + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
|
||||||
|
|
||||||
if (clientModel.isConsentRequired()) {
|
|
||||||
return corsResponse(session.getProvider(LoginFormsProvider.class)
|
|
||||||
.setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders()))
|
|
||||||
.setAccessRequest("Your information from " + providerId + " identity provider.")
|
|
||||||
.setActionUri(this.uriInfo.getRequestUri())
|
|
||||||
.createOAuthGrant(null), clientModel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
|
IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
|
||||||
|
@ -232,18 +238,6 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("{provider_id}/token")
|
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
public Response consentTokenRetrieval(@PathParam("provider_id") String providerId,
|
|
||||||
MultivaluedMap<String, String> formData) {
|
|
||||||
if (formData.containsKey("cancel")) {
|
|
||||||
return redirectToErrorPage(Messages.PERMISSION_NOT_APPROVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getToken(providerId, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Response authenticated(BrokeredIdentityContext context) {
|
public Response authenticated(BrokeredIdentityContext context) {
|
||||||
ClientSessionCode clientCode = null;
|
ClientSessionCode clientCode = null;
|
||||||
IdentityProviderModel identityProviderConfig = context.getIdpConfig();
|
IdentityProviderModel identityProviderConfig = context.getIdpConfig();
|
||||||
|
@ -445,6 +439,11 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
return ErrorResponse.error(message, Status.BAD_REQUEST);
|
return ErrorResponse.error(message, Status.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response forbidden(String message) {
|
||||||
|
fireErrorEvent(message);
|
||||||
|
return ErrorResponse.error(message, Status.FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
public static IdentityProvider getIdentityProvider(KeycloakSession session, RealmModel realm, String alias) {
|
public static IdentityProvider getIdentityProvider(KeycloakSession session, RealmModel realm, String alias) {
|
||||||
IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(alias);
|
IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(alias);
|
||||||
|
|
||||||
|
@ -534,6 +533,13 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
federatedUser.setFirstName(updatedIdentity.getFirstName());
|
federatedUser.setFirstName(updatedIdentity.getFirstName());
|
||||||
federatedUser.setLastName(updatedIdentity.getLastName());
|
federatedUser.setLastName(updatedIdentity.getLastName());
|
||||||
|
|
||||||
|
|
||||||
|
if (updatedIdentity.getIdpConfig().isStoreToken()) {
|
||||||
|
RoleModel readTokenRole = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID).getRole(READ_TOKEN_ROLE);
|
||||||
|
federatedUser.grantRole(readTokenRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.session.users().addFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
|
this.session.users().addFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
|
||||||
|
|
||||||
updatedIdentity.getIdp().importNewUser(session, realmModel, federatedUser, updatedIdentity);
|
updatedIdentity.getIdp().importNewUser(session, realmModel, federatedUser, updatedIdentity);
|
||||||
|
|
|
@ -84,8 +84,6 @@ public class IdentityProviderResource {
|
||||||
public Response delete() {
|
public Response delete() {
|
||||||
this.auth.requireManage();
|
this.auth.requireManage();
|
||||||
|
|
||||||
removeClientIdentityProviders(this.realm.getClients(), this.identityProviderModel);
|
|
||||||
|
|
||||||
this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
|
this.realm.removeIdentityProviderByAlias(this.identityProviderModel.getAlias());
|
||||||
|
|
||||||
return Response.noContent().build();
|
return Response.noContent().build();
|
||||||
|
@ -109,7 +107,6 @@ public class IdentityProviderResource {
|
||||||
// Admin changed the ID (alias) of identity provider. We must update all clients and users
|
// Admin changed the ID (alias) of identity provider. We must update all clients and users
|
||||||
logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId);
|
logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId);
|
||||||
|
|
||||||
updateClientsAfterProviderAliasChange(this.realm.getClients(), oldProviderId, newProviderId);
|
|
||||||
updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
|
updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,25 +128,6 @@ public class IdentityProviderResource {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateClientsAfterProviderAliasChange(List<ClientModel> clients, String oldProviderId, String newProviderId) {
|
|
||||||
for (ClientModel client : clients) {
|
|
||||||
List<ClientIdentityProviderMappingModel> clientIdentityProviders = client.getIdentityProviders();
|
|
||||||
boolean found = true;
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingModel mappingModel : clientIdentityProviders) {
|
|
||||||
if (mappingModel.getIdentityProvider().equals(oldProviderId)) {
|
|
||||||
mappingModel.setIdentityProvider(newProviderId);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
client.updateIdentityProviders(clientIdentityProviders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateUsersAfterProviderAliasChange(List<UserModel> users, String oldProviderId, String newProviderId) {
|
private void updateUsersAfterProviderAliasChange(List<UserModel> users, String oldProviderId, String newProviderId) {
|
||||||
for (UserModel user : users) {
|
for (UserModel user : users) {
|
||||||
FederatedIdentityModel federatedIdentity = this.session.users().getFederatedIdentity(user, oldProviderId, this.realm);
|
FederatedIdentityModel federatedIdentity = this.session.users().getFederatedIdentity(user, oldProviderId, this.realm);
|
||||||
|
@ -285,18 +263,5 @@ public class IdentityProviderResource {
|
||||||
realm.removeIdentityProviderMapper(model);
|
realm.removeIdentityProviderMapper(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeClientIdentityProviders(List<ClientModel> clients, IdentityProviderModel identityProvider) {
|
|
||||||
for (ClientModel clientModel : clients) {
|
|
||||||
List<ClientIdentityProviderMappingModel> identityProviders = clientModel.getIdentityProviders();
|
|
||||||
|
|
||||||
for (ClientIdentityProviderMappingModel providerMappingModel : new ArrayList<>(identityProviders)) {
|
|
||||||
if (providerMappingModel.getIdentityProvider().equals(identityProvider.getAlias())) {
|
|
||||||
identityProviders.remove(providerMappingModel);
|
|
||||||
clientModel.updateIdentityProviders(identityProviders);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
4
testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
Normal file → Executable file
4
testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
Normal file → Executable file
|
@ -42,7 +42,7 @@ public class ClientTest extends AbstractClientTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getClients() {
|
public void getClients() {
|
||||||
assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console");
|
assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -52,7 +52,7 @@ public class ClientTest extends AbstractClientTest {
|
||||||
rep.setEnabled(true);
|
rep.setEnabled(true);
|
||||||
realm.clients().create(rep);
|
realm.clients().create(rep);
|
||||||
|
|
||||||
assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "my-app");
|
assertNames(realm.clients().findAll(), "account", "realm-management", "security-admin-console", "broker", "my-app");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -32,14 +32,17 @@ import org.junit.Test;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserModel.RequiredAction;
|
import org.keycloak.models.UserModel.RequiredAction;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
import org.keycloak.services.Urls;
|
import org.keycloak.services.Urls;
|
||||||
|
import org.keycloak.services.resources.IdentityBrokerService;
|
||||||
import org.keycloak.testsuite.OAuthClient;
|
import org.keycloak.testsuite.OAuthClient;
|
||||||
import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
|
import org.keycloak.testsuite.OAuthClient.AccessTokenResponse;
|
||||||
import org.keycloak.testsuite.broker.util.UserSessionStatusServlet.UserSessionStatus;
|
import org.keycloak.testsuite.broker.util.UserSessionStatusServlet.UserSessionStatus;
|
||||||
|
@ -243,6 +246,7 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
FederatedIdentityModel federatedIdentityModel = federatedIdentities.iterator().next();
|
FederatedIdentityModel federatedIdentityModel = federatedIdentities.iterator().next();
|
||||||
|
|
||||||
assertEquals(getProviderId(), federatedIdentityModel.getIdentityProvider());
|
assertEquals(getProviderId(), federatedIdentityModel.getIdentityProvider());
|
||||||
|
revokeGrant();
|
||||||
|
|
||||||
driver.navigate().to("http://localhost:8081/test-app/logout");
|
driver.navigate().to("http://localhost:8081/test-app/logout");
|
||||||
driver.navigate().to("http://localhost:8081/test-app");
|
driver.navigate().to("http://localhost:8081/test-app");
|
||||||
|
@ -285,27 +289,12 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
RealmModel realm = getRealm();
|
RealmModel realm = getRealm();
|
||||||
ClientModel clientModel = realm.getClientByClientId("test-app");
|
ClientModel clientModel = realm.getClientByClientId("test-app");
|
||||||
|
|
||||||
// This client doesn't have any specific identity providers settings
|
|
||||||
ClientModel client2 = realm.getClientByClientId("test-app");
|
|
||||||
assertEquals(0, client2.getIdentityProviders().size());
|
|
||||||
|
|
||||||
// Provider button is available on login page
|
// Provider button is available on login page
|
||||||
this.driver.navigate().to("http://localhost:8081/test-app/");
|
this.driver.navigate().to("http://localhost:8081/test-app/");
|
||||||
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
||||||
loginPage.findSocialButton(getProviderId());
|
loginPage.findSocialButton(getProviderId());
|
||||||
|
|
||||||
// Add identityProvider to client model
|
}
|
||||||
List<ClientIdentityProviderMappingModel> appIdentityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
|
|
||||||
ClientIdentityProviderMappingModel mapping = new ClientIdentityProviderMappingModel();
|
|
||||||
mapping.setIdentityProvider(getProviderId());
|
|
||||||
mapping.setRetrieveToken(true);
|
|
||||||
appIdentityProviders.add(mapping);
|
|
||||||
clientModel.updateIdentityProviders(appIdentityProviders);
|
|
||||||
|
|
||||||
// Provider button still available on login page
|
|
||||||
this.driver.navigate().to("http://localhost:8081/test-app/");
|
|
||||||
loginPage.findSocialButton(getProviderId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUserAlreadyExistsWhenUpdatingProfile() {
|
public void testUserAlreadyExistsWhenUpdatingProfile() {
|
||||||
|
@ -411,12 +400,16 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
revokeGrant();
|
revokeGrant();
|
||||||
|
|
||||||
// Logout from account management
|
// Logout from account management
|
||||||
|
String pageSource = driver.getPageSource();
|
||||||
accountFederatedIdentityPage.logout();
|
accountFederatedIdentityPage.logout();
|
||||||
assertTrue(driver.getTitle().equals("Log in to realm-with-broker"));
|
assertTrue(driver.getTitle().equals("Log in to realm-with-broker"));
|
||||||
|
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
||||||
|
|
||||||
// Try to login. Previous link is not valid anymore, so now it should try to register new user
|
// Try to login. Previous link is not valid anymore, so now it should try to register new user
|
||||||
this.loginPage.clickSocial(identityProviderModel.getAlias());
|
this.loginPage.clickSocial(identityProviderModel.getAlias());
|
||||||
|
this.loginPage.login("test-user", "password");
|
||||||
doAfterProviderAuthentication();
|
doAfterProviderAuthentication();
|
||||||
|
String current = driver.getCurrentUrl();
|
||||||
this.updateProfilePage.assertCurrent();
|
this.updateProfilePage.assertCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,6 +422,52 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
driver.findElement(By.className("model-oidc-idp"));
|
driver.findElement(By.className("model-oidc-idp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void configureClientRetrieveToken(String clientId) {
|
||||||
|
RealmModel realm = getRealm();
|
||||||
|
RoleModel readTokenRole = realm.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID).getRole(IdentityBrokerService.READ_TOKEN_ROLE);
|
||||||
|
ClientModel client = realm.getClientByClientId(clientId);
|
||||||
|
if (!client.hasScope(readTokenRole)) client.addScopeMapping(readTokenRole);
|
||||||
|
|
||||||
|
brokerServerRule.stopSession(session, true);
|
||||||
|
session = brokerServerRule.startSession();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureUserRetrieveToken(String username) {
|
||||||
|
RealmModel realm = getRealm();
|
||||||
|
UserModel user = session.users().getUserByUsername(username, realm);
|
||||||
|
RoleModel readTokenRole = realm.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID).getRole(IdentityBrokerService.READ_TOKEN_ROLE);
|
||||||
|
if (user != null && !user.hasRole(readTokenRole)) {
|
||||||
|
user.grantRole(readTokenRole);
|
||||||
|
}
|
||||||
|
brokerServerRule.stopSession(session, true);
|
||||||
|
session = brokerServerRule.startSession();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unconfigureClientRetrieveToken(String clientId) {
|
||||||
|
RealmModel realm = getRealm();
|
||||||
|
RoleModel readTokenRole = realm.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID).getRole(IdentityBrokerService.READ_TOKEN_ROLE);
|
||||||
|
ClientModel client = realm.getClientByClientId(clientId);
|
||||||
|
if (client.hasScope(readTokenRole)) client.deleteScopeMapping(readTokenRole);
|
||||||
|
|
||||||
|
brokerServerRule.stopSession(session, true);
|
||||||
|
session = brokerServerRule.startSession();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unconfigureUserRetrieveToken(String username) {
|
||||||
|
RealmModel realm = getRealm();
|
||||||
|
UserModel user = session.users().getUserByUsername(username, realm);
|
||||||
|
RoleModel readTokenRole = realm.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID).getRole(IdentityBrokerService.READ_TOKEN_ROLE);
|
||||||
|
if (user != null && user.hasRole(readTokenRole)) {
|
||||||
|
user.deleteRoleMapping(readTokenRole);
|
||||||
|
}
|
||||||
|
brokerServerRule.stopSession(session, true);
|
||||||
|
session = brokerServerRule.startSession();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTokenStorageAndRetrievalByApplication() {
|
public void testTokenStorageAndRetrievalByApplication() {
|
||||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||||
|
@ -448,8 +487,6 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
|
|
||||||
assertNotNull(identityModel.getToken());
|
assertNotNull(identityModel.getToken());
|
||||||
|
|
||||||
configureRetrieveToken(realm.getClientByClientId("test-app"), getProviderId(), false);
|
|
||||||
|
|
||||||
UserSessionStatus userSessionStatus = retrieveSessionStatus();
|
UserSessionStatus userSessionStatus = retrieveSessionStatus();
|
||||||
String accessToken = userSessionStatus.getAccessTokenString();
|
String accessToken = userSessionStatus.getAccessTokenString();
|
||||||
URI tokenEndpointUrl = Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), realm.getName());
|
URI tokenEndpointUrl = Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), realm.getName());
|
||||||
|
@ -463,112 +500,43 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
Client client = ClientBuilder.newBuilder().register(authFilter).build();
|
Client client = ClientBuilder.newBuilder().register(authFilter).build();
|
||||||
WebTarget tokenEndpoint = client.target(tokenEndpointUrl);
|
WebTarget tokenEndpoint = client.target(tokenEndpointUrl);
|
||||||
Response response = tokenEndpoint.request().get();
|
Response response = tokenEndpoint.request().get();
|
||||||
|
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
||||||
|
assertNotNull(response.readEntity(String.class));
|
||||||
|
revokeGrant();
|
||||||
|
|
||||||
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
|
|
||||||
|
|
||||||
configureRetrieveToken(getRealm().getClientByClientId("test-app"), getProviderId(), true);
|
driver.navigate().to("http://localhost:8081/test-app/logout");
|
||||||
|
String currentUrl = this.driver.getCurrentUrl();
|
||||||
|
System.out.println("after logout currentUrl: " + currentUrl);
|
||||||
|
assertTrue(currentUrl.startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
||||||
|
|
||||||
client = ClientBuilder.newBuilder().register(authFilter).build();
|
unconfigureUserRetrieveToken(getProviderId() + ".test-user");
|
||||||
|
loginIDP("test-user");
|
||||||
|
//authenticateWithIdentityProvider(identityProviderModel, "test-user");
|
||||||
|
assertEquals("http://localhost:8081/test-app", driver.getCurrentUrl());
|
||||||
|
|
||||||
|
userSessionStatus = retrieveSessionStatus();
|
||||||
|
accessToken = userSessionStatus.getAccessTokenString();
|
||||||
|
final String authHeader2 = "Bearer " + accessToken;
|
||||||
|
ClientRequestFilter authFilter2 = new ClientRequestFilter() {
|
||||||
|
@Override
|
||||||
|
public void filter(ClientRequestContext requestContext) throws IOException {
|
||||||
|
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
client = ClientBuilder.newBuilder().register(authFilter2).build();
|
||||||
tokenEndpoint = client.target(tokenEndpointUrl);
|
tokenEndpoint = client.target(tokenEndpointUrl);
|
||||||
response = tokenEndpoint.request().get();
|
response = tokenEndpoint.request().get();
|
||||||
|
|
||||||
assertEquals(Status.OK.getStatusCode(), response.getStatus());
|
assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus());
|
||||||
assertNotNull(response.readEntity(String.class));
|
|
||||||
|
|
||||||
|
revokeGrant();
|
||||||
driver.navigate().to("http://localhost:8081/test-app/logout");
|
driver.navigate().to("http://localhost:8081/test-app/logout");
|
||||||
driver.navigate().to("http://localhost:8081/test-app");
|
driver.navigate().to("http://localhost:8081/test-app");
|
||||||
|
|
||||||
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTokenStorageAndRetrievalByOAuthClient() {
|
|
||||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
|
||||||
|
|
||||||
identityProviderModel.setStoreToken(true);
|
|
||||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
|
||||||
|
|
||||||
driver.navigate().to("http://localhost:8081/test-app");
|
|
||||||
|
|
||||||
// choose the identity provider
|
|
||||||
this.loginPage.clickSocial(getProviderId());
|
|
||||||
|
|
||||||
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
|
|
||||||
|
|
||||||
// log in to identity provider
|
|
||||||
this.loginPage.login("test-user", "password");
|
|
||||||
|
|
||||||
doAfterProviderAuthentication();
|
|
||||||
|
|
||||||
changePasswordPage.realm("realm-with-broker");
|
|
||||||
changePasswordPage.open();
|
|
||||||
changePasswordPage.changePassword("password", "password");
|
|
||||||
|
|
||||||
driver.navigate().to("http://localhost:8081/test-app/logout");
|
|
||||||
|
|
||||||
oauth.realm("realm-with-broker");
|
|
||||||
oauth.redirectUri("http://localhost:8081/third-party");
|
|
||||||
oauth.clientId("third-party");
|
|
||||||
oauth.doLoginGrant("test-user@localhost", "password");
|
|
||||||
|
|
||||||
grantPage.assertCurrent();
|
|
||||||
grantPage.accept();
|
|
||||||
|
|
||||||
assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE));
|
|
||||||
|
|
||||||
ClientModel clientModel = getRealm().getClientByClientId("third-party");
|
|
||||||
assertEquals(0, clientModel.getIdentityProviders().size());
|
|
||||||
|
|
||||||
configureRetrieveToken(clientModel, getProviderId(), true);
|
|
||||||
|
|
||||||
AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password");
|
|
||||||
|
|
||||||
doTokenRequest(accessToken.getAccessToken());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doTokenRequest(String token) {
|
|
||||||
try {
|
|
||||||
HttpClient client = new DefaultHttpClient();
|
|
||||||
HttpGet get = new HttpGet(Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName()));
|
|
||||||
|
|
||||||
get.setHeader("Authorization", "Bearer " + token);
|
|
||||||
|
|
||||||
HttpResponse response = client.execute(get);
|
|
||||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
|
||||||
|
|
||||||
assertNotNull(IOUtils.toString(response.getEntity().getContent()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureRetrieveToken(ClientModel clientModel, String providerId, boolean retrieveToken) {
|
|
||||||
List<ClientIdentityProviderMappingModel> providerMappingModels = clientModel.getIdentityProviders();
|
|
||||||
ClientIdentityProviderMappingModel providerMappingModel = null;
|
|
||||||
|
|
||||||
// Check if provider is already linked with this client
|
|
||||||
for (ClientIdentityProviderMappingModel current : providerMappingModels) {
|
|
||||||
if (current.getIdentityProvider().equals(providerId)) {
|
|
||||||
providerMappingModel = current;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link provider with client if not linked yet
|
|
||||||
if (providerMappingModel == null) {
|
|
||||||
providerMappingModel = new ClientIdentityProviderMappingModel();
|
|
||||||
providerMappingModel.setIdentityProvider(providerId);
|
|
||||||
providerMappingModels.add(providerMappingModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
providerMappingModel.setRetrieveToken(retrieveToken);
|
|
||||||
|
|
||||||
clientModel.updateIdentityProviders(providerMappingModels);
|
|
||||||
|
|
||||||
brokerServerRule.stopSession(session, true);
|
|
||||||
session = brokerServerRule.startSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void doAssertTokenRetrieval(String pageSource);
|
protected abstract void doAssertTokenRetrieval(String pageSource);
|
||||||
|
|
||||||
private UserModel assertSuccessfulAuthentication(IdentityProviderModel identityProviderModel, String username, String expectedEmail) {
|
private UserModel assertSuccessfulAuthentication(IdentityProviderModel identityProviderModel, String username, String expectedEmail) {
|
||||||
|
@ -605,19 +573,8 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void authenticateWithIdentityProvider(IdentityProviderModel identityProviderModel, String username) {
|
private void authenticateWithIdentityProvider(IdentityProviderModel identityProviderModel, String username) {
|
||||||
driver.navigate().to("http://localhost:8081/test-app");
|
loginIDP(username);
|
||||||
|
|
||||||
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
|
||||||
|
|
||||||
// choose the identity provider
|
|
||||||
this.loginPage.clickSocial(getProviderId());
|
|
||||||
|
|
||||||
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
|
|
||||||
System.out.println(this.driver.getCurrentUrl());
|
|
||||||
// log in to identity provider
|
|
||||||
this.loginPage.login(username, "password");
|
|
||||||
|
|
||||||
doAfterProviderAuthentication();
|
|
||||||
|
|
||||||
if (identityProviderModel.isUpdateProfileFirstLogin()) {
|
if (identityProviderModel.isUpdateProfileFirstLogin()) {
|
||||||
String userEmail = "new@email.com";
|
String userEmail = "new@email.com";
|
||||||
|
@ -630,6 +587,22 @@ public abstract class AbstractIdentityProviderTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loginIDP(String username) {
|
||||||
|
driver.navigate().to("http://localhost:8081/test-app");
|
||||||
|
|
||||||
|
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
|
||||||
|
|
||||||
|
// choose the identity provider
|
||||||
|
this.loginPage.clickSocial(getProviderId());
|
||||||
|
|
||||||
|
String currentUrl = this.driver.getCurrentUrl();
|
||||||
|
assertTrue(currentUrl.startsWith("http://localhost:8082/auth/"));
|
||||||
|
System.out.println(this.driver.getCurrentUrl());
|
||||||
|
// log in to identity provider
|
||||||
|
this.loginPage.login(username, "password");
|
||||||
|
doAfterProviderAuthentication();
|
||||||
|
}
|
||||||
|
|
||||||
protected UserModel getFederatedUser() {
|
protected UserModel getFederatedUser() {
|
||||||
UserSessionStatus userSessionStatus = retrieveSessionStatus();
|
UserSessionStatus userSessionStatus = retrieveSessionStatus();
|
||||||
IDToken idToken = userSessionStatus.getIdToken();
|
IDToken idToken = userSessionStatus.getIdToken();
|
||||||
|
|
|
@ -118,32 +118,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
||||||
this.realmManager.removeRealm(realm);
|
this.realmManager.removeRealm(realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testApplicationIdentityProviders() throws Exception {
|
|
||||||
RealmModel realm = installTestRealm();
|
|
||||||
|
|
||||||
ClientModel client = realm.getClientByClientId("test-app-with-allowed-providers");
|
|
||||||
List<ClientIdentityProviderMappingModel> identityProviders = client.getIdentityProviders();
|
|
||||||
|
|
||||||
assertEquals(1, identityProviders.size());
|
|
||||||
|
|
||||||
ClientIdentityProviderMappingModel identityProviderMappingModel = identityProviders.get(0);
|
|
||||||
|
|
||||||
assertEquals("kc-oidc-idp", identityProviderMappingModel.getIdentityProvider());
|
|
||||||
assertEquals(false, identityProviderMappingModel.isRetrieveToken());
|
|
||||||
|
|
||||||
identityProviders.remove(identityProviderMappingModel);
|
|
||||||
|
|
||||||
client.updateIdentityProviders(identityProviders);
|
|
||||||
|
|
||||||
client = realm.getClientById(client.getId());
|
|
||||||
identityProviders = client.getIdentityProviders();
|
|
||||||
|
|
||||||
assertEquals(0, identityProviders.size());
|
|
||||||
this.realmManager.removeRealm(realm);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
|
private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
|
||||||
assertFalse(identityProviders.isEmpty());
|
assertFalse(identityProviders.isEmpty());
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,8 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT
|
||||||
@Override
|
@Override
|
||||||
protected void doAfterProviderAuthentication() {
|
protected void doAfterProviderAuthentication() {
|
||||||
// grant access to broker-app
|
// grant access to broker-app
|
||||||
grantPage.assertCurrent();
|
//grantPage.assertCurrent();
|
||||||
grantPage.accept();
|
//grantPage.accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,4 +120,14 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT
|
||||||
public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided() {
|
public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided() {
|
||||||
super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided();
|
super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername_emailNotProvided();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTokenStorageAndRetrievalByApplication() {
|
||||||
|
super.testTokenStorageAndRetrievalByApplication();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccountManagementLinkIdentity() {
|
||||||
|
super.testAccountManagementLinkIdentity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,8 @@ public class SAMLKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
|
protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
|
||||||
assertEquals("kc-saml-idp-basic.", federatedUser.getUsername());
|
assertEquals("kc-saml-idp-basic.test-user-noemail", federatedUser.getUsername());
|
||||||
assertEquals("", federatedUser.getEmail());
|
//assertEquals("", federatedUser.getEmail());
|
||||||
assertEquals(null, federatedUser.getFirstName());
|
assertEquals(null, federatedUser.getFirstName());
|
||||||
assertEquals(null, federatedUser.getLastName());
|
assertEquals(null, federatedUser.getLastName());
|
||||||
}
|
}
|
||||||
|
@ -94,15 +94,24 @@ public class SAMLKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT
|
||||||
super.testSuccessfulAuthenticationWithoutUpdateProfile();
|
super.testSuccessfulAuthenticationWithoutUpdateProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test
|
|
||||||
public void testTokenStorageAndRetrievalByOAuthClient() {
|
|
||||||
super.testTokenStorageAndRetrievalByOAuthClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulAuthentication() {
|
public void testSuccessfulAuthentication() {
|
||||||
super.testSuccessfulAuthentication();
|
super.testSuccessfulAuthentication();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccountManagementLinkIdentity() {
|
||||||
|
super.testAccountManagementLinkIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTokenStorageAndRetrievalByApplication() {
|
||||||
|
super.testTokenStorageAndRetrievalByApplication();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() {
|
||||||
|
super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,8 @@ public class SAMLKeyCloakServerBrokerWithSignatureTest extends AbstractIdentityP
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
|
protected void doAssertFederatedUserNoEmail(UserModel federatedUser) {
|
||||||
assertEquals("kc-saml-signed-idp.", federatedUser.getUsername());
|
assertEquals("kc-saml-signed-idp.test-user-noemail", federatedUser.getUsername());
|
||||||
assertEquals("", federatedUser.getEmail());
|
//assertEquals("", federatedUser.getEmail());
|
||||||
assertEquals(null, federatedUser.getFirstName());
|
assertEquals(null, federatedUser.getFirstName());
|
||||||
assertEquals(null, federatedUser.getLastName());
|
assertEquals(null, federatedUser.getLastName());
|
||||||
}
|
}
|
||||||
|
@ -93,4 +93,8 @@ public class SAMLKeyCloakServerBrokerWithSignatureTest extends AbstractIdentityP
|
||||||
super.testSuccessfulAuthentication();
|
super.testSuccessfulAuthentication();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTokenStorageAndRetrievalByApplication() {
|
||||||
|
super.testTokenStorageAndRetrievalByApplication();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
8
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/util/UserSessionStatusServlet.java
Normal file → Executable file
8
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/util/UserSessionStatusServlet.java
Normal file → Executable file
|
@ -27,6 +27,7 @@ import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServlet;
|
import javax.servlet.http.HttpServlet;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -39,8 +40,11 @@ public class UserSessionStatusServlet extends HttpServlet {
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
if (req.getRequestURI().toString().endsWith("logout")) {
|
if (req.getRequestURI().toString().endsWith("logout")) {
|
||||||
resp.setStatus(200);
|
String redirect = UriBuilder.fromUri("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/logout")
|
||||||
req.logout();
|
.queryParam("redirect_uri", "http://localhost:8081/test-app").build().toString();
|
||||||
|
resp.sendRedirect(redirect);
|
||||||
|
//resp.setStatus(200);
|
||||||
|
//req.logout();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class ImportTest extends AbstractModelTest {
|
||||||
Assert.assertEquals(0, session.users().getFederatedIdentities(user, realm).size());
|
Assert.assertEquals(0, session.users().getFederatedIdentities(user, realm).size());
|
||||||
|
|
||||||
List<ClientModel> resources = realm.getClients();
|
List<ClientModel> resources = realm.getClients();
|
||||||
Assert.assertEquals(6, resources.size());
|
Assert.assertEquals(7, resources.size());
|
||||||
|
|
||||||
// Test applications imported
|
// Test applications imported
|
||||||
ClientModel application = realm.getClientByClientId("Application");
|
ClientModel application = realm.getClientByClientId("Application");
|
||||||
|
@ -92,7 +92,7 @@ public class ImportTest extends AbstractModelTest {
|
||||||
Assert.assertNotNull(otherApp);
|
Assert.assertNotNull(otherApp);
|
||||||
Assert.assertNull(nonExisting);
|
Assert.assertNull(nonExisting);
|
||||||
Map<String, ClientModel> clients = realm.getClientNameMap();
|
Map<String, ClientModel> clients = realm.getClientNameMap();
|
||||||
Assert.assertEquals(6, clients.size());
|
Assert.assertEquals(7, clients.size());
|
||||||
Assert.assertTrue(clients.values().contains(application));
|
Assert.assertTrue(clients.values().contains(application));
|
||||||
Assert.assertTrue(clients.values().contains(otherApp));
|
Assert.assertTrue(clients.values().contains(otherApp));
|
||||||
Assert.assertTrue(clients.values().contains(accountApp));
|
Assert.assertTrue(clients.values().contains(accountApp));
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
"clients" : [
|
"clients" : [
|
||||||
{
|
{
|
||||||
"clientId": "broker-app",
|
"clientId": "broker-app",
|
||||||
"consentRequired": "true",
|
"consentRequired": "false",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"secret": "secret",
|
"secret": "secret",
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-oidc-idp/endpoint"
|
"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-oidc-idp/endpoint/*"
|
||||||
],
|
],
|
||||||
"protocolMappers": [
|
"protocolMappers": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint"
|
"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint"
|
||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint",
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp/endpoint",
|
||||||
|
"saml_force_name_id_format": "true",
|
||||||
|
"saml_name_id_format": "username",
|
||||||
"saml.assertion.signature": "true",
|
"saml.assertion.signature": "true",
|
||||||
"saml.server.signature": "true",
|
"saml.server.signature": "true",
|
||||||
"saml.signature.algorithm": "RSA_SHA256",
|
"saml.signature.algorithm": "RSA_SHA256",
|
||||||
|
@ -46,6 +50,18 @@
|
||||||
"attribute.name": "mobile",
|
"attribute.name": "mobile",
|
||||||
"attribute.nameformat": "Basic"
|
"attribute.nameformat": "Basic"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-user-property-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"user.attribute": "email",
|
||||||
|
"attribute.name": "urn:oid:1.2.840.113549.1.9.1",
|
||||||
|
"attribute.nameformat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
|
||||||
|
"friendly.name": "email"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -15,7 +15,12 @@
|
||||||
"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint"
|
"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint"
|
||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"saml.authnstatement": "true"
|
"saml.authnstatement": "true",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint",
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint",
|
||||||
|
"saml_force_name_id_format": "true",
|
||||||
|
"saml_name_id_format": "username"
|
||||||
|
|
||||||
},
|
},
|
||||||
"protocolMappers": [
|
"protocolMappers": [
|
||||||
{
|
{
|
||||||
|
@ -40,6 +45,18 @@
|
||||||
"attribute.name": "mobile",
|
"attribute.name": "mobile",
|
||||||
"attribute.nameformat": "Basic"
|
"attribute.nameformat": "Basic"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-user-property-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"user.attribute": "email",
|
||||||
|
"attribute.name": "urn:oid:1.2.840.113549.1.9.1",
|
||||||
|
"attribute.nameformat": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
|
||||||
|
"friendly.name": "email"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -112,6 +112,7 @@
|
||||||
"updateProfileFirstLogin" : "true",
|
"updateProfileFirstLogin" : "true",
|
||||||
"config": {
|
"config": {
|
||||||
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
|
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
|
||||||
|
"singleLogoutServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
|
||||||
"nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
"nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
||||||
"signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
|
"signingCertificate": "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin",
|
||||||
"wantAuthnRequestsSigned": true,
|
"wantAuthnRequestsSigned": true,
|
||||||
|
@ -128,6 +129,7 @@
|
||||||
"updateProfileFirstLogin" : "true",
|
"updateProfileFirstLogin" : "true",
|
||||||
"config": {
|
"config": {
|
||||||
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",
|
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",
|
||||||
|
"singleLogoutServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",
|
||||||
"nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
"nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
||||||
"forceAuthn": true,
|
"forceAuthn": true,
|
||||||
"postBindingResponse": true,
|
"postBindingResponse": true,
|
||||||
|
@ -155,6 +157,7 @@
|
||||||
"providerId" : "keycloak-oidc",
|
"providerId" : "keycloak-oidc",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"updateProfileFirstLogin" : "false",
|
"updateProfileFirstLogin" : "false",
|
||||||
|
"storeToken" : "true",
|
||||||
"config": {
|
"config": {
|
||||||
"clientId": "broker-app",
|
"clientId": "broker-app",
|
||||||
"clientSecret": "secret",
|
"clientSecret": "secret",
|
||||||
|
@ -162,6 +165,7 @@
|
||||||
"authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/login",
|
"authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/login",
|
||||||
"tokenUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/token",
|
"tokenUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/token",
|
||||||
"userInfoUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/userinfo",
|
"userInfoUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/userinfo",
|
||||||
|
"logoutUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/tokens/logout",
|
||||||
"defaultScope": "email profile"
|
"defaultScope": "email profile"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,8 +252,8 @@
|
||||||
"name": "test-app",
|
"name": "test-app",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"publicClient": true,
|
"publicClient": true,
|
||||||
"adminUrl": "http://localhost:8081/auth",
|
"adminUrl": "http://localhost:8081/test-app",
|
||||||
"baseUrl": "http://localhost:8081/auth",
|
"baseUrl": "http://localhost:8081/test-app",
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"/test-app/*"
|
"/test-app/*"
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue