Merge pull request #1057 from mposolda/master

KEYCLOAK-1108 Remove option for enable/disable login per app. Few other minor fixes
This commit is contained in:
Marek Posolda 2015-03-18 10:36:44 +01:00
commit b8d5109744
18 changed files with 218 additions and 288 deletions

View file

@ -954,6 +954,33 @@ Authorization: Bearer {keycloak_access_token}]]></programlisting>
In this case, given that you are accessing an protected service in Keycloak, you need to send the access token
issued by Keycloak during the user authentication.
</para>
<para>
By default, the Keycloak access token issued for the application can't be automatically used for retrieve thirdparty token. You will
need to enable this in admin console first:
<orderedlist>
<listitem>
<para>
Click 'Applications' on the left side menu.
</para>
</listitem>
<listitem>
<para>
Select an application from the list.
</para>
</listitem>
<listitem>
<para>
Click the 'Identity Provider' tab.
</para>
</listitem>
<listitem>
<para>
From this page you can configure if an application is allowed to retrieve tokens from an specific identity provider. For that,
just click on the <emphasis>Can Retrieve Token</emphasis> button.
</para>
</listitem>
</orderedlist>
</para>
<note>
<para>
If your application is not at the same origin as the authentication server, make sure you have properly configured CORS.
@ -961,44 +988,6 @@ Authorization: Bearer {keycloak_access_token}]]></programlisting>
</note>
</section>
<section>
<title>Configuring Identity Providers for Applications</title>
<para>
By default, all identity providers enabled for a particular realm are also available to all its applications.
However, you can also specify which identity providers should be available when
authenticating users for a particular application.
</para>
<para>
For that, please follow these steps:
</para>
<orderedlist>
<listitem>
<para>
Click 'Applications' on the left side menu.
</para>
</listitem>
<listitem>
<para>
Select an application from the list.
</para>
</listitem>
<listitem>
<para>
Click the 'Identity Provider' tab.
</para>
</listitem>
<listitem>
<para>
Now you should be able to enable or disabled identity providers to the application by clicking on the Enable/Disable button.
</para>
</listitem>
</orderedlist>
<para>
From this page you can also configure if an application is allowed to retrieve tokens from an specific identity provider. For that,
just click on the <emphasis>Can Retrieve Token</emphasis> button.
</para>
</section>
<section>
<title>Automatically Select and Identity Provider</title>
<para>

View file

@ -56,35 +56,34 @@ module.controller('ApplicationIdentityProviderCtrl', function($scope, $location,
if ($scope.application.identityProviders) {
length = $scope.application.identityProviders.length;
} else {
$scope.application.identityProviders = new Array(realm.identityProviders.length);
}
for (j = length; j < realm.identityProviders.length; j++) {
$scope.application.identityProviders[j] = {};
for (i = 0; i < $scope.application.identityProviders.length; i++) {
var applicationProvider = $scope.application.identityProviders[i];
if (applicationProvider.retrieveToken) {
applicationProvider.retrieveToken = applicationProvider.retrieveToken.toString();
}
}
} else {
$scope.application.identityProviders = [];
}
$scope.identityProviders = [];
var providersMissingInApp = [];
for (j = 0; j < realm.identityProviders.length; j++) {
var identityProvider = realm.identityProviders[j];
var match = false;
var applicationProvider;
var applicationProvider = null;
for (i = 0; i < $scope.application.identityProviders.length; i++) {
applicationProvider = $scope.application.identityProviders[i];
if (applicationProvider) {
if (applicationProvider.retrieveToken) {
applicationProvider.retrieveToken = applicationProvider.retrieveToken.toString();
} else {
applicationProvider.retrieveToken = false.toString();
}
if (applicationProvider.id == identityProvider.id) {
$scope.identityProviders[i] = {};
$scope.identityProviders[i].identityProvider = identityProvider;
$scope.identityProviders[i].retrieveToken = applicationProvider.retrieveToken.toString();
$scope.identityProviders[i].retrieveToken = applicationProvider.retrieveToken;
break;
}
@ -93,30 +92,27 @@ module.controller('ApplicationIdentityProviderCtrl', function($scope, $location,
}
if (applicationProvider == null) {
var length = $scope.identityProviders.length + $scope.application.identityProviders.length;
$scope.identityProviders[length] = {};
$scope.identityProviders[length].identityProvider = identityProvider;
$scope.identityProviders[length].retrieveToken = false.toString();
providersMissingInApp.push(identityProvider);
}
}
$scope.identityProviders = $scope.identityProviders.filter(function(n){ return n != undefined });
for (j = 0; j < providersMissingInApp.length; j++) {
var identityProvider = providersMissingInApp[j];
var currentProvider = {};
currentProvider.identityProvider = identityProvider;
currentProvider.retrieveToken = "false";
$scope.identityProviders.push(currentProvider);
var currentAppProvider = {};
currentAppProvider.id = identityProvider.id;
currentAppProvider.retrieveToken = "false";
$scope.application.identityProviders.push(currentAppProvider);
}
var oldCopy = angular.copy($scope.application);
$scope.save = function() {
var selectedProviders = [];
for (i = 0; i < $scope.application.identityProviders.length; i++) {
var appProvider = $scope.application.identityProviders[i];
if (appProvider.id != null && appProvider.id != false) {
selectedProviders[selectedProviders.length] = appProvider;
}
}
$scope.application.identityProviders = selectedProviders;
Application.update({
realm : realm.realm,

View file

@ -11,10 +11,6 @@
<form class="form-horizontal" name="identityProviderForm" novalidate>
<div class="form-group" ng-repeat="identityProvider in identityProviders">
<legend><span class="text">{{identityProvider.identityProvider.name}}</span></legend>
<label class="col-sm-2 control-label" for="{{identityProvider.identityProvider.id}}">Enable&nbsp;<span tooltip-placement="right" tooltip="If disabled, users can not login to the application using this identity provider." class="fa fa-info-circle"></span></label>
<div class="col-sm-4">
<input ng-model="application.identityProviders[$index].id" name="identityProvider.identityProvider.id" id="identityProvider.identityProvider.id" value="identityProvider.identityProvider.id" onoffswitchmodel />
</div>
<div data-ng-show="application.identityProviders[$index].id">
<label class="col-sm-2 control-label" for="{{identityProvider.identityProvider.id}}retrieveToken">Can Retrieve Token&nbsp;<span tooltip-placement="right" tooltip="If disabled, the application can not retrieve tokens from the identity provider." class="fa fa-info-circle"></span></label>
<div class="col-sm-4">

View file

@ -63,14 +63,6 @@
</div>
</div>
</form>
<#elseif realm.social>
<div id="kc-social-providers">
<ul>
<#list social.providers as p>
<li><a href="${p.loginUrl}" class="zocial ${p.id}"> <span class="text">${p.name}</span></a></li>
</#list>
</ul>
</div>
</#if>
<#elseif section = "info" >
<#if realm.password && realm.registrationAllowed>
@ -83,7 +75,7 @@
<div id="kc-social-providers">
<ul>
<#list social.providers as p>
<li><a href="${p.loginUrl}" class="zocial ${p.id}"> <span class="text">${p.name}</span></a></li>
<li><a href="${p.loginUrl}" id="zocial-${p.id}" class="zocial ${p.providerId}"> <span class="text">${p.name}</span></a></li>
</#list>
</ul>
</div>

View file

@ -53,24 +53,6 @@ public class IdentityProviderBean {
for (IdentityProviderModel identityProvider : identityProviders) {
if (identityProvider.isEnabled()) {
String clientId = uriInfo.getQueryParameters().getFirst(OAuth2Constants.CLIENT_ID);
if (clientId != null) {
ClientModel clientModel = realm.findClient(clientId);
if (clientModel != null && !clientModel.hasIdentityProvider(identityProvider.getId())) {
if (ApplicationModel.class.isInstance(clientModel)) {
ApplicationModel applicationModel = (ApplicationModel) clientModel;
if (applicationModel.getName().equals(Constants.ACCOUNT_MANAGEMENT_APP)) {
addIdentityProvider(realm, baseURI, identityProvider);
}
}
continue;
}
}
addIdentityProvider(realm, baseURI, identityProvider);
}
}
@ -83,7 +65,7 @@ public class IdentityProviderBean {
private void addIdentityProvider(RealmModel realm, URI baseURI, IdentityProviderModel identityProvider) {
String loginUrl = Urls.identityProviderAuthnRequest(baseURI, identityProvider.getId(), realm.getName()).toString();
providers.add(new IdentityProvider(identityProvider.getId(), identityProvider.getName(), loginUrl));
providers.add(new IdentityProvider(identityProvider.getId(), identityProvider.getProviderId(), identityProvider.getName(), loginUrl));
}
public List<IdentityProvider> getProviders() {
@ -97,11 +79,13 @@ public class IdentityProviderBean {
public static class IdentityProvider {
private final String id;
private final String providerId; // This refer to providerType (facebook, google, etc.)
private final String name;
private final String loginUrl;
public IdentityProvider(String id, String name, String loginUrl) {
public IdentityProvider(String id, String providerId, String name, String loginUrl) {
this.id = id;
this.providerId = providerId;
if (name == null) {
name = id;
@ -123,5 +107,8 @@ public class IdentityProviderBean {
return loginUrl;
}
public String getProviderId() {
return providerId;
}
}
}

View file

@ -98,9 +98,8 @@ public interface ClientModel {
void setNotBefore(int notBefore);
void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders);
void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders);
List<ClientIdentityProviderMappingModel> getIdentityProviders();
boolean hasIdentityProvider(String providerId);
boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId);
Set<ProtocolMapperModel> getProtocolMappers();

View file

@ -489,7 +489,7 @@ public class RepresentationToModel {
}
}
applicationModel.updateAllowedIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm));
applicationModel.updateIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm));
return applicationModel;
}
@ -538,7 +538,7 @@ public class RepresentationToModel {
}
}
updateClientIdentityProvides(rep.getIdentityProviders(), resource);
updateClientIdentityProviders(rep.getIdentityProviders(), resource);
}
public static void setClaims(ClientModel model, ClaimRepresentation rep) {
@ -613,7 +613,7 @@ public class RepresentationToModel {
public static OAuthClientModel createOAuthClient(OAuthClientRepresentation rep, RealmModel realm) {
OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm);
model.updateAllowedIdentityProviders(toModel(rep.getIdentityProviders(), realm));
model.updateIdentityProviders(toModel(rep.getIdentityProviders(), realm));
updateOAuthClient(rep, model);
return model;
@ -653,7 +653,7 @@ public class RepresentationToModel {
}
}
updateClientIdentityProvides(rep.getIdentityProviders(), model);
updateClientIdentityProviders(rep.getIdentityProviders(), model);
if (rep.getProtocolMappers() != null) {
// first, remove all default/built in mappers
@ -818,35 +818,25 @@ public class RepresentationToModel {
}
private static List<ClientIdentityProviderMappingModel> toModel(List<ClientIdentityProviderMappingRepresentation> repIdentityProviders, RealmModel realm) {
List<ClientIdentityProviderMappingModel> allowedIdentityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
List<ClientIdentityProviderMappingModel> result = new ArrayList<ClientIdentityProviderMappingModel>();
if (repIdentityProviders == null || repIdentityProviders.isEmpty()) {
allowedIdentityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
for (IdentityProviderModel identityProvider : realm.getIdentityProviders()) {
ClientIdentityProviderMappingModel identityProviderMapping = new ClientIdentityProviderMappingModel();
identityProviderMapping.setIdentityProvider(identityProvider.getId());
allowedIdentityProviders.add(identityProviderMapping);
}
} else {
if (repIdentityProviders != null) {
for (ClientIdentityProviderMappingRepresentation rep : repIdentityProviders) {
ClientIdentityProviderMappingModel identityProviderMapping = new ClientIdentityProviderMappingModel();
identityProviderMapping.setIdentityProvider(rep.getId());
identityProviderMapping.setRetrieveToken(rep.isRetrieveToken());
allowedIdentityProviders.add(identityProviderMapping);
result.add(identityProviderMapping);
}
}
return allowedIdentityProviders;
return result;
}
private static void updateClientIdentityProvides(List<ClientIdentityProviderMappingRepresentation> identityProviders, ClientModel resource) {
private static void updateClientIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders, ClientModel resource) {
if (identityProviders != null) {
List<ClientIdentityProviderMappingModel> allowedIdentityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
List<ClientIdentityProviderMappingModel> result = new ArrayList<ClientIdentityProviderMappingModel>();
for (ClientIdentityProviderMappingRepresentation mappingRepresentation : identityProviders) {
ClientIdentityProviderMappingModel identityProviderMapping = new ClientIdentityProviderMappingModel();
@ -854,10 +844,10 @@ public class RepresentationToModel {
identityProviderMapping.setIdentityProvider(mappingRepresentation.getId());
identityProviderMapping.setRetrieveToken(mappingRepresentation.isRetrieveToken());
allowedIdentityProviders.add(identityProviderMapping);
result.add(identityProviderMapping);
}
resource.updateAllowedIdentityProviders(allowedIdentityProviders);
resource.updateIdentityProviders(result);
}
}
}

View file

@ -386,7 +386,7 @@ public abstract class ClientAdapter implements ClientModel {
}
@Override
public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
for (ClientIdentityProviderMappingModel model : identityProviders) {
@ -416,19 +416,6 @@ public abstract class ClientAdapter implements ClientModel {
return models;
}
@Override
public boolean hasIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingEntity identityProviderMappingModel : clientEntity.getIdentityProviders()) {
String identityProvider = identityProviderMappingModel.getId();
if (identityProvider.equals(providerId)) {
return true;
}
}
return false;
}
@Override
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingEntity identityProviderMappingModel : clientEntity.getIdentityProviders()) {

View file

@ -264,9 +264,9 @@ public abstract class ClientAdapter implements ClientModel {
}
@Override
public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
getDelegateForUpdate();
updatedClient.updateAllowedIdentityProviders(identityProviders);
updatedClient.updateIdentityProviders(identityProviders);
}
@Override
@ -275,12 +275,6 @@ public abstract class ClientAdapter implements ClientModel {
return cachedClient.getIdentityProviders();
}
@Override
public boolean hasIdentityProvider(String providerId) {
if (updatedClient != null) return updatedClient.hasIdentityProvider(providerId);
return cachedClient.hasIdentityProvider(providerId);
}
@Override
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
if (updatedClient != null) return updatedClient.isAllowedRetrieveTokenFromIdentityProvider(providerId);

View file

@ -307,7 +307,7 @@ public abstract class ClientAdapter implements ClientModel {
}
@Override
public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
Collection<ClientIdentityProviderMappingEntity> entities = entity.getIdentityProviders();
Set<String> already = new HashSet<String>();
List<ClientIdentityProviderMappingEntity> remove = new ArrayList<ClientIdentityProviderMappingEntity>();
@ -377,17 +377,6 @@ public abstract class ClientAdapter implements ClientModel {
return models;
}
@Override
public boolean hasIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
if (model.getIdentityProvider().equals(providerId)) {
return true;
}
}
return false;
}
@Override
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {

View file

@ -411,7 +411,7 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
@Override
public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
public void updateIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
List<ClientIdentityProviderMappingEntity> stored = new ArrayList<ClientIdentityProviderMappingEntity>();
for (ClientIdentityProviderMappingModel model : identityProviders) {
@ -442,19 +442,6 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
return models;
}
@Override
public boolean hasIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntityAsClient().getIdentityProviders()) {
String identityProvider = identityProviderMappingModel.getId();
if (identityProvider.equals(providerId)) {
return true;
}
}
return false;
}
@Override
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntityAsClient().getIdentityProviders()) {

View file

@ -230,26 +230,12 @@ public class MongoUserProvider implements UserProvider {
return result;
}
private FederatedIdentityEntity findSocialLink(UserModel userModel, String socialProvider, RealmModel realm) {
UserModel user = getUserById(userModel.getId(), realm);
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
List<FederatedIdentityEntity> linkEntities = userEntity.getFederatedIdentities();
if (linkEntities == null) {
return null;
}
for (FederatedIdentityEntity federatedIdentityEntity : linkEntities) {
if (federatedIdentityEntity.getIdentityProvider().equals(socialProvider)) {
return federatedIdentityEntity;
}
}
return null;
}
@Override
public FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm) {
FederatedIdentityEntity federatedIdentityEntity = findSocialLink(user, socialProvider, realm);
user = getUserById(user.getId(), realm);
MongoUserEntity userEntity = ((UserAdapter) user).getUser();
FederatedIdentityEntity federatedIdentityEntity = findFederatedIdentityLink(userEntity, socialProvider);
return federatedIdentityEntity != null ? new FederatedIdentityModel(federatedIdentityEntity.getIdentityProvider(), federatedIdentityEntity.getUserId(),
federatedIdentityEntity.getUserName(), federatedIdentityEntity.getToken()) : null;
}

View file

@ -182,10 +182,6 @@ public class IdentityBrokerService {
return badRequest("Invalid client.");
}
if (!clientModel.hasIdentityProvider(providerId)) {
return corsResponse(badRequest("Client [" + audience + "] not authorized."), clientModel);
}
if (!clientModel.isAllowedRetrieveTokenFromIdentityProvider(providerId)) {
return corsResponse(badRequest("Client [" + audience + "] not authorized to retrieve tokens from identity provider [" + providerId + "]."), clientModel);
}
@ -399,16 +395,16 @@ public class IdentityBrokerService {
if (clientSession != null) {
ClientModel client = clientSession.getClient();
if (client != null) {
LOGGER.debugf("Got authorization code from client [%s].", client.getClientId());
this.event.client(client);
if (client == null) {
throw new IdentityBrokerException("Invalid client");
}
LOGGER.debugf("Got authorization code from client [%s].", client.getClientId());
this.event.client(client);
if (clientSession.getUserSession() != null) {
this.event.session(clientSession.getUserSession());
}
} else {
validateClientPermissions(clientCode, providerId);
}
if (isDebugEnabled()) {
@ -509,19 +505,6 @@ public class IdentityBrokerService {
throw new IdentityBrokerException("Configuration for identity provider [" + providerId + "] not found.");
}
private void validateClientPermissions(ClientSessionCode clientSessionCode, String providerId) {
ClientSessionModel clientSession = clientSessionCode.getClientSession();
ClientModel clientModel = clientSession.getClient();
if (clientModel == null) {
throw new IdentityBrokerException("Invalid client.");
}
if (!clientModel.hasIdentityProvider(providerId)) {
throw new IdentityBrokerException("Client [" + clientModel.getClientId() + "] not authorized to authenticate with identity provider [" + providerId + "].");
}
}
private UserModel createUser(FederatedIdentity updatedIdentity) {
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(updatedIdentity.getIdentityProviderId(), updatedIdentity.getId(),
updatedIdentity.getUsername(), updatedIdentity.getToken());

View file

@ -1,15 +1,17 @@
package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.provider.ProviderFactory;
@ -22,22 +24,21 @@ import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Pedro Igor
*/
public class IdentityProviderResource {
private static Logger logger = Logger.getLogger(IdentityProviderResource.class);
private final RealmAuth auth;
private final RealmModel realm;
private final KeycloakSession session;
@ -62,23 +63,86 @@ public class IdentityProviderResource {
public Response delete() {
this.auth.requireManage();
removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel);
removeClientIdentityProviders(this.realm.getApplications(), this.identityProviderModel);
removeClientIdentityProviders(this.realm.getOAuthClients(), this.identityProviderModel);
this.realm.removeIdentityProviderById(this.identityProviderModel.getId());
return Response.noContent().build();
}
@PUT
@Consumes("application/json")
public Response update(IdentityProviderRepresentation model) {
public Response update(IdentityProviderRepresentation providerRep) {
try {
this.auth.requireManage();
this.realm.updateIdentityProvider(RepresentationToModel.toModel(model));
String internalId = providerRep.getInternalId();
String newProviderId = providerRep.getId();
String oldProviderId = getProviderIdByInternalId(this.realm, internalId);
this.realm.updateIdentityProvider(RepresentationToModel.toModel(providerRep));
if (oldProviderId != null && !oldProviderId.equals(newProviderId)) {
// 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);
updateClientsAfterProviderAliasChange(this.realm.getApplications(), oldProviderId, newProviderId);
updateClientsAfterProviderAliasChange(this.realm.getOAuthClients(), oldProviderId, newProviderId);
updateUsersAfterProviderAliasChange(this.session.users().getUsers(this.realm), oldProviderId, newProviderId);
}
return Response.noContent().build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Identity Provider " + model.getId() + " already exists");
return Flows.errors().exists("Identity Provider " + providerRep.getId() + " already exists");
}
}
// return ID of IdentityProvider from realm based on internalId of this provider
private String getProviderIdByInternalId(RealmModel realm, String providerInternalId) {
List<IdentityProviderModel> providerModels = realm.getIdentityProviders();
for (IdentityProviderModel providerModel : providerModels) {
if (providerModel.getInternalId().equals(providerInternalId)) {
return providerModel.getId();
}
}
return null;
}
private void updateClientsAfterProviderAliasChange(List<? extends 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) {
for (UserModel user : users) {
FederatedIdentityModel federatedIdentity = this.session.users().getFederatedIdentity(user, oldProviderId, this.realm);
if (federatedIdentity != null) {
// Remove old link first
this.session.users().removeFederatedIdentity(this.realm, user, oldProviderId);
// And create new
FederatedIdentityModel newFederatedIdentity = new FederatedIdentityModel(newProviderId, federatedIdentity.getUserId(), federatedIdentity.getUserName(),
federatedIdentity.getToken());
this.session.users().addFederatedIdentity(this.realm, user, newFederatedIdentity);
}
}
}
private IdentityProviderFactory getIdentityProviderFactory() {
List<ProviderFactory> allProviders = new ArrayList<ProviderFactory>();
@ -113,10 +177,10 @@ public class IdentityProviderResource {
for (ClientIdentityProviderMappingModel providerMappingModel : new ArrayList<ClientIdentityProviderMappingModel>(identityProviders)) {
if (providerMappingModel.getIdentityProvider().equals(identityProvider.getId())) {
identityProviders.remove(providerMappingModel);
clientModel.updateIdentityProviders(identityProviders);
break;
}
}
clientModel.updateAllowedIdentityProviders(identityProviders);
}
}

View file

@ -94,9 +94,6 @@ public class IdentityProvidersResource {
try {
this.realm.addIdentityProvider(RepresentationToModel.toModel(representation));
updateClientIdentityProviders(this.realm.getApplications(), representation);
updateClientIdentityProviders(this.realm.getOAuthClients(), representation);
return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build();
} catch (ModelDuplicateException e) {
return Flows.errors().exists("Identity Provider " + representation.getId() + " already exists");
@ -220,17 +217,4 @@ public class IdentityProvidersResource {
return allProviders;
}
private void updateClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderRepresentation identityProvider) {
for (ClientModel clientModel : clients) {
List<ClientIdentityProviderMappingModel> allowedIdentityProviders = clientModel.getIdentityProviders();
ClientIdentityProviderMappingModel providerMappingModel = new ClientIdentityProviderMappingModel();
providerMappingModel.setIdentityProvider(identityProvider.getId());
allowedIdentityProviders.add(providerMappingModel);
clientModel.updateAllowedIdentityProviders(allowedIdentityProviders);
}
}
}

View file

@ -62,6 +62,7 @@ import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@ -226,41 +227,31 @@ public abstract class AbstractIdentityProviderTest {
}
@Test
public void testDisabledForApplication() {
public void testProviderOnLoginPage() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
RealmModel realm = getRealm();
ApplicationModel applicationModel = realm.getApplicationByName("test-app");
List<ClientIdentityProviderMappingModel> allowedIdentityProviders = applicationModel.getIdentityProviders();
ClientIdentityProviderMappingModel mapping = null;
for (ClientIdentityProviderMappingModel model : allowedIdentityProviders) {
if (model.getIdentityProvider().equals(identityProviderModel.getId())) {
mapping = model;
}
}
assertNotNull(mapping);
allowedIdentityProviders.remove(mapping);
// This client doesn't have any specific identity providers settings
ClientModel client2 = realm.findClient("test-app");
assertEquals(0, client2.getIdentityProviders().size());
// Provider button is available on login page
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"));
loginPage.findSocialButton(getProviderId());
try {
this.driver.findElement(By.className(getProviderId()));
fail("Provider [" + getProviderId() + "] not disabled.");
} catch (NoSuchElementException nsee) {
}
allowedIdentityProviders.add(mapping);
applicationModel.updateAllowedIdentityProviders(allowedIdentityProviders);
// Add identityProvider to client model
List<ClientIdentityProviderMappingModel> appIdentityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
ClientIdentityProviderMappingModel mapping = new ClientIdentityProviderMappingModel();
mapping.setIdentityProvider(getProviderId());
mapping.setRetrieveToken(true);
appIdentityProviders.add(mapping);
applicationModel.updateIdentityProviders(appIdentityProviders);
// Provider button still available on login page
this.driver.navigate().to("http://localhost:8081/test-app/");
this.driver.findElement(By.className(getProviderId()));
loginPage.findSocialButton(getProviderId());
}
@Test
@ -398,17 +389,7 @@ public abstract class AbstractIdentityProviderTest {
assertNotNull(identityModel.getToken());
ClientModel clientModel = realm.findClient("test-app");
ClientIdentityProviderMappingModel providerMappingModel = null;
for (ClientIdentityProviderMappingModel identityProviderMappingModel : clientModel.getIdentityProviders()) {
if (identityProviderMappingModel.getIdentityProvider().equals(getProviderId())) {
providerMappingModel = identityProviderMappingModel;
break;
}
}
providerMappingModel.setRetrieveToken(false);
configureRetrieveToken(realm.findClient("test-app"), getProviderId(), false);
UserSessionStatus userSessionStatus = retrieveSessionStatus();
String accessToken = userSessionStatus.getAccessTokenString();
@ -426,7 +407,7 @@ public abstract class AbstractIdentityProviderTest {
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
providerMappingModel.setRetrieveToken(true);
configureRetrieveToken(getRealm().findClient("test-app"), getProviderId(), true);
client = ClientBuilder.newBuilder().register(authFilter).build();
tokenEndpoint = client.target(tokenEndpointUrl);
@ -477,16 +458,9 @@ public abstract class AbstractIdentityProviderTest {
assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE));
ClientModel clientModel = getRealm().findClient("third-party");
ClientIdentityProviderMappingModel providerMappingModel = null;
assertEquals(0, clientModel.getIdentityProviders().size());
for (ClientIdentityProviderMappingModel identityProviderMappingModel : clientModel.getIdentityProviders()) {
if (identityProviderMappingModel.getIdentityProvider().equals(getProviderId())) {
providerMappingModel = identityProviderMappingModel;
break;
}
}
providerMappingModel.setRetrieveToken(true);
configureRetrieveToken(clientModel, getProviderId(), true);
AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password");
URI tokenEndpointUrl = Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName());
@ -505,6 +479,33 @@ public abstract class AbstractIdentityProviderTest {
doAssertTokenRetrieval(driver.getPageSource());
}
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);
private void assertSuccessfulAuthentication(IdentityProviderModel identityProviderModel, String username) {

View file

@ -133,7 +133,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
identityProviders.remove(identityProviderMappingModel);
client.updateAllowedIdentityProviders(identityProviders);
client.updateIdentityProviders(identityProviders);
client = realm.findClientById(client.getId());
identityProviders = client.getIdentityProviders();

View file

@ -110,8 +110,14 @@ public class LoginPage extends AbstractPage {
registerLink.click();
}
public void clickSocial(String id) {
driver.findElement(By.className(id)).click();
public void clickSocial(String providerId) {
WebElement socialButton = findSocialButton(providerId);
socialButton.click();
}
public WebElement findSocialButton(String providerId) {
String id = "zocial-" + providerId;
return this.driver.findElement(By.id(id));
}
public void resetPassword() {