[KEYCLOAK-883] - Configuration option to disable token retrieval from applications.

This commit is contained in:
pedroigor 2015-02-27 02:13:27 -03:00
parent cd39d5292a
commit b45d6b896a
28 changed files with 723 additions and 181 deletions

View file

@ -73,13 +73,14 @@
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
</createTable> </createTable>
<createTable tableName="CLIENT_ALLOWED_IDENTITY_PROVIDER"> <createTable tableName="CLIENT_IDENTITY_PROVIDER_MAPPING">
<column name="CLIENT_ID" type="VARCHAR(36)"> <column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
<column name="INTERNAL_ID" type="VARCHAR(36)"> <column name="IDENTITY_PROVIDER_ID" type="VARCHAR(36)">
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
<column name="RETRIEVE_TOKEN" type="BOOLEAN(1)"/>
</createTable> </createTable>
<createTable tableName="CLIENT_PROTOCOL_MAPPER"> <createTable tableName="CLIENT_PROTOCOL_MAPPER">
<column name="CLIENT_ID" type="VARCHAR(36)"> <column name="CLIENT_ID" type="VARCHAR(36)">
@ -104,10 +105,11 @@
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="FEDERATED_IDENTITY" constraintName="FK404288B92EF007A6" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/> <addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="FEDERATED_IDENTITY" constraintName="FK404288B92EF007A6" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="IDENTITY_PROVIDER_ID" baseTableName="IDENTITY_PROVIDER_CONFIG" constraintName="FKDC4897CF864C4E43" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/> <addForeignKeyConstraint baseColumnNames="IDENTITY_PROVIDER_ID" baseTableName="IDENTITY_PROVIDER_CONFIG" constraintName="FKDC4897CF864C4E43" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/>
<addForeignKeyConstraint baseColumnNames="PROTOCOL_MAPPER_ID" baseTableName="PROTOCOL_MAPPER_CONFIG" constraintName="FK_PMConfig" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="PROTOCOL_MAPPER"/> <addForeignKeyConstraint baseColumnNames="PROTOCOL_MAPPER_ID" baseTableName="PROTOCOL_MAPPER_CONFIG" constraintName="FK_PMConfig" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="PROTOCOL_MAPPER"/>
<addForeignKeyConstraint baseColumnNames="INTERNAL_ID" baseTableName="CLIENT_ALLOWED_IDENTITY_PROVIDER" constraintName="FK_7CELWNIBJI49AVXSRTUF6XJ12" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/> <addForeignKeyConstraint baseColumnNames="IDENTITY_PROVIDER_ID" baseTableName="CLIENT_IDENTITY_PROVIDER_MAPPING" constraintName="FK_7CELWNIBJI49AVXSRTUF6XJ12" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/>
<addUniqueConstraint columnNames="INTERNAL_ID,CLIENT_ID" constraintName="UK_7CAELWNIBJI49AVXSRTUF6XJ12" tableName="CLIENT_ALLOWED_IDENTITY_PROVIDER"/> <addForeignKeyConstraint baseColumnNames="CLIENT_ID" baseTableName="CLIENT_IDENTITY_PROVIDER_MAPPING" constraintName="FK_56ELWNIBJI49AVXSRTUF6XJ23" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="MAPPING_ID" baseTableName="CLIENT_PROTOCOL_MAPPER" constraintName="FK_CPCM" referencedColumnNames="ID" referencedTableName="PROTOCOL_MAPPER"/> <addForeignKeyConstraint baseColumnNames="MAPPING_ID" baseTableName="CLIENT_PROTOCOL_MAPPER" constraintName="FK_CPCM" referencedColumnNames="ID" referencedTableName="PROTOCOL_MAPPER"/>
<addUniqueConstraint columnNames="CLIENT_ID,MAPPING_ID" constraintName="UK_CPCM" tableName="CLIENT_PROTOCOL_MAPPER"/> <addUniqueConstraint columnNames="CLIENT_ID,MAPPING_ID" constraintName="UK_CPCM" tableName="CLIENT_PROTOCOL_MAPPER"/>
<addUniqueConstraint columnNames="PROVIDER_NONIMAL_ID" constraintName="UK_2DAELWNIBJI49AVXSRTUF6XJ33" tableName="IDENTITY_PROVIDER"/> <addUniqueConstraint columnNames="PROVIDER_NONIMAL_ID" constraintName="UK_2DAELWNIBJI49AVXSRTUF6XJ33" tableName="IDENTITY_PROVIDER"/>
<addUniqueConstraint columnNames="IDENTITY_PROVIDER_ID,CLIENT_ID" constraintName="UK_7CAELWNIBJI49AVXSRTUF6XJ12" tableName="CLIENT_IDENTITY_PROVIDER_MAPPING"/>
</changeSet> </changeSet>
</databaseChangeLog> </databaseChangeLog>

View file

@ -18,6 +18,7 @@
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class> <class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class> <class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
<class>org.keycloak.models.jpa.entities.IdentityProviderEntity</class> <class>org.keycloak.models.jpa.entities.IdentityProviderEntity</class>
<class>org.keycloak.models.jpa.entities.ClientIdentityProviderMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ClaimTypeEntity</class> <class>org.keycloak.models.jpa.entities.ClaimTypeEntity</class>
<class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class> <class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class>

View file

@ -2,7 +2,6 @@ package org.keycloak.representations.idm;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -29,7 +28,7 @@ public class ApplicationRepresentation {
protected Boolean fullScopeAllowed; protected Boolean fullScopeAllowed;
protected Integer nodeReRegistrationTimeout; protected Integer nodeReRegistrationTimeout;
protected Map<String, Integer> registeredNodes; protected Map<String, Integer> registeredNodes;
protected List<String> allowedIdentityProviders; protected List<ClientIdentityProviderMappingRepresentation> identityProviders;
protected List<ClientProtocolMappingRepresentation> protocolMappers; protected List<ClientProtocolMappingRepresentation> protocolMappers;
public String getId() { public String getId() {
@ -192,12 +191,12 @@ public class ApplicationRepresentation {
this.frontchannelLogout = frontchannelLogout; this.frontchannelLogout = frontchannelLogout;
} }
public List<String> getAllowedIdentityProviders() { public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
return this.allowedIdentityProviders; return this.identityProviders;
} }
public void setAllowedIdentityProviders(List<String> allowedIdentityProviders) { public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
this.allowedIdentityProviders = allowedIdentityProviders; this.identityProviders = identityProviders;
} }
public List<ClientProtocolMappingRepresentation> getProtocolMappers() { public List<ClientProtocolMappingRepresentation> getProtocolMappers() {

View file

@ -0,0 +1,43 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.representations.idm;
/**
* @author pedroigor
*/
public class ClientIdentityProviderMappingRepresentation {
protected String id;
protected boolean retrieveToken;
public String getId() {
return this.id;
}
public void setId(String identityProviderId) {
this.id = identityProviderId;
}
public boolean isRetrieveToken() {
return this.retrieveToken;
}
public void setRetrieveToken(boolean retrieveToken) {
this.retrieveToken = retrieveToken;
}
}

View file

@ -2,7 +2,6 @@ package org.keycloak.representations.idm;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -23,8 +22,8 @@ public class OAuthClientRepresentation {
protected Boolean directGrantsOnly; protected Boolean directGrantsOnly;
protected Boolean fullScopeAllowed; protected Boolean fullScopeAllowed;
protected Boolean frontchannelLogout; protected Boolean frontchannelLogout;
protected List<String> allowedIdentityProviders;
protected List<ClientProtocolMappingRepresentation> protocolMappers; protected List<ClientProtocolMappingRepresentation> protocolMappers;
private List<ClientIdentityProviderMappingRepresentation> identityProviders;
public String getId() { public String getId() {
@ -139,12 +138,12 @@ public class OAuthClientRepresentation {
this.frontchannelLogout = frontchannelLogout; this.frontchannelLogout = frontchannelLogout;
} }
public List<String> getAllowedIdentityProviders() { public List<ClientIdentityProviderMappingRepresentation> getIdentityProviders() {
return this.allowedIdentityProviders; return this.identityProviders;
} }
public void setAllowedIdentityProviders(List<String> allowedIdentityProviders) { public void setIdentityProviders(List<ClientIdentityProviderMappingRepresentation> identityProviders) {
this.allowedIdentityProviders = allowedIdentityProviders; this.identityProviders = identityProviders;
} }
public List<ClientProtocolMappingRepresentation> getProtocolMappers() { public List<ClientProtocolMappingRepresentation> getProtocolMappers() {

View file

@ -962,7 +962,7 @@ Authorization: Bearer {keycloak_access_token}]]></programlisting>
</section> </section>
<section> <section>
<title>Enabling/Disabling Identity Providers for Service Providers</title> <title>Configuring Identity Providers for Applications</title>
<para> <para>
By default, all identity providers enabled for a particular realm are also available to all its applications. 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 However, you can also specify which identity providers should be available when
@ -993,6 +993,10 @@ Authorization: Bearer {keycloak_access_token}]]></programlisting>
</para> </para>
</listitem> </listitem>
</orderedlist> </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>
<section> <section>

View file

@ -43,75 +43,95 @@ module.controller('ApplicationCredentialsCtrl', function($scope, $location, real
}); });
}); });
module.controller('ApplicationIdentityProviderCtrl', function($scope, $location, realm, application, Application, $location, Notifications) { module.controller('ApplicationIdentityProviderCtrl', function($scope, $location, $route, realm, application, Application, $location, Notifications) {
$scope.realm = realm; $scope.realm = realm;
$scope.application = angular.copy(application); $scope.application = angular.copy(application);
var length = 0;
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] = {};
}
$scope.identityProviders = []; $scope.identityProviders = [];
if (!$scope.application.allowedIdentityProviders) {
$scope.application.allowedIdentityProviders = [];
}
for (j = 0; j < realm.identityProviders.length; j++) { for (j = 0; j < realm.identityProviders.length; j++) {
var identityProvider = realm.identityProviders[j]; var identityProvider = realm.identityProviders[j];
var match = false; var match = false;
var applicationProvider;
for (i = 0; i < $scope.application.allowedIdentityProviders.length; i++) { for (i = 0; i < $scope.application.identityProviders.length; i++) {
var appProvider = $scope.application.allowedIdentityProviders[i]; applicationProvider = $scope.application.identityProviders[i];
if (appProvider == identityProvider.id) { if (applicationProvider) {
$scope.identityProviders[i] = identityProvider; if (applicationProvider.retrieveToken) {
match = true; 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();
break;
}
applicationProvider = null;
} }
} }
if (!match) { if (applicationProvider == null) {
var length = $scope.identityProviders.length; var length = $scope.identityProviders.length + $scope.application.identityProviders.length;
length = length + $scope.application.allowedIdentityProviders.length; $scope.identityProviders[length] = {};
$scope.identityProviders[length].identityProvider = identityProvider;
$scope.identityProviders[length] = identityProvider; $scope.identityProviders[length].retrieveToken = false.toString();
} }
} }
$scope.identityProviders = $scope.identityProviders.filter(function(n){ return n != undefined }); $scope.identityProviders = $scope.identityProviders.filter(function(n){ return n != undefined });
var oldCopy = angular.copy($scope.application);
$scope.save = function() { $scope.save = function() {
var selectedProviders = []; var selectedProviders = [];
for (i = 0; i < $scope.application.allowedIdentityProviders.length; i++) { for (i = 0; i < $scope.application.identityProviders.length; i++) {
var appProvider = $scope.application.allowedIdentityProviders[i]; var appProvider = $scope.application.identityProviders[i];
if (appProvider) { if (appProvider.id != null && appProvider.id != false) {
selectedProviders[selectedProviders.length] = appProvider; selectedProviders[selectedProviders.length] = appProvider;
} }
} }
$scope.allowedIdentityProviders = $scope.application.allowedIdentityProviders; $scope.application.identityProviders = selectedProviders;
$scope.application.allowedIdentityProviders = selectedProviders;
Application.update({ Application.update({
realm : realm.realm, realm : realm.realm,
application : application.id application : application.id
}, $scope.application, function() { }, $scope.application, function() {
$scope.changed = false; $scope.changed = false;
$scope.application.allowedIdentityProviders = $scope.allowedIdentityProviders; $route.reload();
$location.url("/realms/" + realm.realm + "/applications/" + application.id + "/identity-provider");
Notifications.success("Your changes have been saved to the application."); Notifications.success("Your changes have been saved to the application.");
}); });
}; };
$scope.reset = function() { $scope.reset = function() {
$scope.application = angular.copy(application); $scope.application = angular.copy(oldCopy);
$scope.changed = false; $scope.changed = false;
}; };
$scope.$watch(function() { $scope.$watch('application', function() {
return $location.path(); if (!angular.equals($scope.application, oldCopy)) {
}, function() { $scope.changed = true;
$scope.path = $location.path().substring(1).split("/"); }
}); }, true);
}); });
module.controller('ApplicationSamlKeyCtrl', function($scope, $location, $http, $upload, realm, application, module.controller('ApplicationSamlKeyCtrl', function($scope, $location, $http, $upload, realm, application,

View file

@ -324,74 +324,94 @@ module.controller('OAuthClientRevocationCtrl', function($scope, realm, oauth, OA
} }
}); });
module.controller('OAuthClientIdentityProviderCtrl', function($scope, realm, oauth, OAuthClient, $location, Notifications) { module.controller('OAuthClientIdentityProviderCtrl', function($scope, $route, realm, oauth, OAuthClient, $location, Notifications) {
$scope.realm = realm; $scope.realm = realm;
$scope.oauth = angular.copy(oauth); $scope.oauth = angular.copy(oauth);
var length = 0;
if ($scope.oauth.identityProviders) {
length = $scope.oauth.identityProviders.length;
} else {
$scope.oauth.identityProviders = new Array(realm.identityProviders.length);
}
for (j = length; j < realm.identityProviders.length; j++) {
$scope.oauth.identityProviders[j] = {};
}
$scope.identityProviders = []; $scope.identityProviders = [];
if (!$scope.oauth.allowedIdentityProviders) {
$scope.oauth.allowedIdentityProviders = [];
}
for (j = 0; j < realm.identityProviders.length; j++) { for (j = 0; j < realm.identityProviders.length; j++) {
var identityProvider = realm.identityProviders[j]; var identityProvider = realm.identityProviders[j];
var match = false; var match = false;
var applicationProvider;
for (i = 0; i < $scope.oauth.allowedIdentityProviders.length; i++) { for (i = 0; i < $scope.oauth.identityProviders.length; i++) {
var appProvider = $scope.oauth.allowedIdentityProviders[i]; applicationProvider = $scope.oauth.identityProviders[i];
if (appProvider == identityProvider.id) { if (applicationProvider) {
$scope.identityProviders[i] = identityProvider; if (applicationProvider.retrieveToken) {
match = true; 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();
break;
}
applicationProvider = null;
} }
} }
if (!match) { if (applicationProvider == null) {
var length = $scope.identityProviders.length; var length = $scope.identityProviders.length + $scope.oauth.identityProviders.length;
length = length + $scope.oauth.allowedIdentityProviders.length; $scope.identityProviders[length] = {};
$scope.identityProviders[length].identityProvider = identityProvider;
$scope.identityProviders[length] = identityProvider; $scope.identityProviders[length].retrieveToken = false.toString();
} }
} }
$scope.identityProviders = $scope.identityProviders.filter(function(n){ return n != undefined }); $scope.identityProviders = $scope.identityProviders.filter(function(n){ return n != undefined });
var oldCopy = angular.copy($scope.oauth);
$scope.save = function() { $scope.save = function() {
var selectedProviders = []; var selectedProviders = [];
for (i = 0; i < $scope.oauth.allowedIdentityProviders.length; i++) { for (i = 0; i < $scope.oauth.identityProviders.length; i++) {
var appProvider = $scope.oauth.allowedIdentityProviders[i]; var appProvider = $scope.oauth.identityProviders[i];
if (appProvider) { if (appProvider.id != null && appProvider.id != false) {
selectedProviders[selectedProviders.length] = appProvider; selectedProviders[selectedProviders.length] = appProvider;
} }
} }
$scope.allowedIdentityProviders = $scope.oauth.allowedIdentityProviders; $scope.oauth.identityProviders = selectedProviders;
$scope.oauth.allowedIdentityProviders = selectedProviders;
OAuthClient.update({ OAuthClient.update({
realm : realm.realm, realm : realm.realm,
oauth : oauth.id oauth : oauth.id
}, $scope.oauth, function() { }, $scope.oauth, function() {
$scope.changed = false; $scope.changed = false;
$scope.oauth.allowedIdentityProviders = $scope.allowedIdentityProviders; $route.reload();
$location.url("/realms/" + realm.realm + "/oauth-clients/" + oauth.id + "/identity-provider");
Notifications.success("Your changes have been saved to the application."); Notifications.success("Your changes have been saved to the application.");
}); });
}; };
$scope.reset = function() { $scope.reset = function() {
$scope.oauth = angular.copy(oauth); $scope.oauth = angular.copy(oldCopy);
$scope.changed = false; $scope.changed = false;
}; };
$scope.$watch(function() { $scope.$watch('oauth', function() {
return $location.path(); if (!angular.equals($scope.oauth, oldCopy)) {
}, function() { $scope.changed = true;
$scope.path = $location.path().substring(1).split("/"); }
}); }, true);
}); });

View file

@ -7,17 +7,24 @@
<li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}">{{application.name}}</a></li> <li><a href="#/realms/{{realm.realm}}/applications/{{application.id}}">{{application.name}}</a></li>
<li class="active">Identity Provider</li> <li class="active">Identity Provider</li>
</ol> </ol>
<h2 data-ng-hide="create"><span>{{application.name}}</span> Identity Provider Settings<span tooltip-placement="right" tooltip="Select which identity providers can be used for this application. By default, all identity providers are enabled. Select one or more to restrict." class="fa fa-info-circle"></span></h2> <h2 data-ng-hide="create"><span>{{application.name}}</span> Identity Provider Settings</h2>
<form class="form-horizontal" name="identityProviderForm" novalidate> <form class="form-horizontal" name="identityProviderForm" novalidate>
<div class="form-group" ng-repeat="identityProvider in identityProviders"> <div class="form-group" ng-repeat="identityProvider in identityProviders">
<legend><span class="text">{{identityProvider.name}}</span></legend> <legend><span class="text">{{identityProvider.identityProvider.name}}</span></legend>
<label class="col-sm-2 control-label" for="{{identityProvider.id}}">Enable</label> <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"> <div class="col-sm-4">
<input ng-model="application.allowedIdentityProviders[$index]" name="identityProvider.id" id="identityProvider.id" value="identityProvider.id" onoffswitchmodel /> <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">
<input ng-model="application.identityProviders[$index].retrieveToken" name="identityProvider.identityProvider.id + 'retrieveToken'" id="identityProvider.identityProvider.id + 'retrieveToken'" value="true" onoffswitchmodel />
</div>
</div> </div>
</div> </div>
<div class="pull-right form-actions"> <div class="pull-right form-actions">
<button kc-save>Save</button> <button kc-reset data-ng-show="changed">Clear changes</button>
<button kc-save data-ng-show="changed">Save</button>
</div> </div>
</form> </form>
</div> </div>

View file

@ -10,14 +10,21 @@
<h2 data-ng-hide="create"><span>{{oauth.name}}</span> Identity Provider Settings</h2> <h2 data-ng-hide="create"><span>{{oauth.name}}</span> Identity Provider Settings</h2>
<form class="form-horizontal" name="identityProviderForm" novalidate> <form class="form-horizontal" name="identityProviderForm" novalidate>
<div class="form-group" ng-repeat="identityProvider in identityProviders"> <div class="form-group" ng-repeat="identityProvider in identityProviders">
<legend><span class="text">{{identityProvider.name}}</span></legend> <legend><span class="text">{{identityProvider.identityProvider.name}}</span></legend>
<label class="col-sm-2 control-label" for="{{identityProvider.id}}">Enable</label> <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"> <div class="col-sm-4">
<input ng-model="oauth.allowedIdentityProviders[$index]" name="identityProvider.id" id="identityProvider.id" value="identityProvider.id" kc-onoffswitch-model /> <input ng-model="oauth.identityProviders[$index].id" name="identityProvider.identityProvider.id" id="identityProvider.identityProvider.id" value="identityProvider.identityProvider.id" onoffswitchmodel />
</div>
<div data-ng-show="oauth.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">
<input ng-model="oauth.identityProviders[$index].retrieveToken" name="identityProvider.identityProvider.id + 'retrieveToken'" id="identityProvider.identityProvider.id + 'retrieveToken'" value="true" onoffswitchmodel />
</div>
</div> </div>
</div> </div>
<div class="pull-right form-actions"> <div class="pull-right form-actions">
<button kc-save>Save</button> <button kc-reset data-ng-show="changed">Clear changes</button>
<button kc-save data-ng-show="changed">Save</button>
</div> </div>
</form> </form>
</div> </div>

View file

@ -0,0 +1,43 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models;
/**
* @author pedroigor
*/
public class ClientIdentityProviderMappingModel {
private String identityProvider;
private boolean retrieveToken;
public String getIdentityProvider() {
return this.identityProvider;
}
public void setIdentityProvider(String identityProviderModel) {
this.identityProvider = identityProviderModel;
}
public boolean isRetrieveToken() {
return this.retrieveToken;
}
public void setRetrieveToken(boolean retrieveToken) {
this.retrieveToken = retrieveToken;
}
}

View file

@ -98,11 +98,10 @@ public interface ClientModel {
void setNotBefore(int notBefore); void setNotBefore(int notBefore);
void updateAllowedIdentityProviders(List<String> identityProviders); void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders);
List<ClientIdentityProviderMappingModel> getIdentityProviders();
List<String> getAllowedIdentityProviders();
boolean hasIdentityProvider(String providerId); boolean hasIdentityProvider(String providerId);
boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId);
Set<ProtocolMapperModel> getProtocolMappers(); Set<ProtocolMapperModel> getProtocolMappers();
void addProtocolMappers(Set<String> mapperIds); void addProtocolMappers(Set<String> mapperIds);

View file

@ -29,7 +29,7 @@ public class ClientEntity extends AbstractIdentifiableEntity {
private List<String> webOrigins = new ArrayList<String>(); private List<String> webOrigins = new ArrayList<String>();
private List<String> redirectUris = new ArrayList<String>(); private List<String> redirectUris = new ArrayList<String>();
private List<String> scopeIds = new ArrayList<String>(); private List<String> scopeIds = new ArrayList<String>();
private List<String> allowedIdentityProviders = new ArrayList<String>(); private List<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
private Set<String> protocolMappers = new HashSet<String>(); private Set<String> protocolMappers = new HashSet<String>();
public String getName() { public String getName() {
@ -144,12 +144,12 @@ public class ClientEntity extends AbstractIdentifiableEntity {
this.frontchannelLogout = frontchannelLogout; this.frontchannelLogout = frontchannelLogout;
} }
public List<String> getAllowedIdentityProviders() { public List<ClientIdentityProviderMappingEntity> getIdentityProviders() {
return this.allowedIdentityProviders; return this.identityProviders;
} }
public void setAllowedIdentityProviders(List<String> allowedIdentityProviders) { public void setIdentityProviders(List<ClientIdentityProviderMappingEntity> identityProviders) {
this.allowedIdentityProviders = allowedIdentityProviders; this.identityProviders = identityProviders;
} }
public Set<String> getProtocolMappers() { public Set<String> getProtocolMappers() {

View file

@ -0,0 +1,44 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.entities;
/**
* @author pedroigor
*/
public class ClientIdentityProviderMappingEntity {
private String id;
private Boolean retrieveToken;
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public Boolean isRetrieveToken() {
return this.retrieveToken;
}
public void setRetrieveToken(Boolean retrieveToken) {
this.retrieveToken = retrieveToken;
}
}

View file

@ -3,6 +3,7 @@ package org.keycloak.models.utils;
import org.keycloak.models.ApplicationModel; import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClaimMask; import org.keycloak.models.ClaimMask;
import org.keycloak.models.ClaimTypeModel; import org.keycloak.models.ClaimTypeModel;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel; import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.FederatedIdentityModel;
@ -19,6 +20,7 @@ import org.keycloak.models.UserSessionModel;
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.ClaimTypeRepresentation; import org.keycloak.representations.idm.ClaimTypeRepresentation;
import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation;
import org.keycloak.representations.idm.ClientProtocolMappingRepresentation; import org.keycloak.representations.idm.ClientProtocolMappingRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation;
@ -262,8 +264,8 @@ public class ModelToRepresentation {
rep.setRegisteredNodes(new HashMap<String, Integer>(applicationModel.getRegisteredNodes())); rep.setRegisteredNodes(new HashMap<String, Integer>(applicationModel.getRegisteredNodes()));
} }
if (!applicationModel.getAllowedIdentityProviders().isEmpty()) { if (!applicationModel.getIdentityProviders().isEmpty()) {
rep.setAllowedIdentityProviders(applicationModel.getAllowedIdentityProviders()); rep.setIdentityProviders(toRepresentation(applicationModel.getIdentityProviders()));
} }
if (!applicationModel.getProtocolMappers().isEmpty()) { if (!applicationModel.getProtocolMappers().isEmpty()) {
@ -279,6 +281,21 @@ 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 OAuthClientRepresentation toRepresentation(OAuthClientModel model) { public static OAuthClientRepresentation toRepresentation(OAuthClientModel model) {
OAuthClientRepresentation rep = new OAuthClientRepresentation(); OAuthClientRepresentation rep = new OAuthClientRepresentation();
rep.setId(model.getId()); rep.setId(model.getId());
@ -301,8 +318,8 @@ public class ModelToRepresentation {
} }
rep.setNotBefore(model.getNotBefore()); rep.setNotBefore(model.getNotBefore());
if (!model.getAllowedIdentityProviders().isEmpty()) { if (!model.getIdentityProviders().isEmpty()) {
rep.setAllowedIdentityProviders(model.getAllowedIdentityProviders()); rep.setIdentityProviders(toRepresentation(model.getIdentityProviders()));
} }
if (!model.getProtocolMappers().isEmpty()) { if (!model.getProtocolMappers().isEmpty()) {

View file

@ -7,6 +7,7 @@ import org.keycloak.models.ApplicationModel;
import org.keycloak.models.BrowserSecurityHeaders; import org.keycloak.models.BrowserSecurityHeaders;
import org.keycloak.models.ClaimMask; import org.keycloak.models.ClaimMask;
import org.keycloak.models.ClaimTypeModel; import org.keycloak.models.ClaimTypeModel;
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.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
@ -23,6 +24,7 @@ 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.ClaimTypeRepresentation; import org.keycloak.representations.idm.ClaimTypeRepresentation;
import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentation;
import org.keycloak.representations.idm.ClientProtocolMappingRepresentation; import org.keycloak.representations.idm.ClientProtocolMappingRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation; import org.keycloak.representations.idm.FederatedIdentityRepresentation;
@ -473,17 +475,7 @@ public class RepresentationToModel {
applicationModel.setProtocolMappers(ids); applicationModel.setProtocolMappers(ids);
} }
List<String> allowedIdentityProviders = resourceRep.getAllowedIdentityProviders(); applicationModel.updateAllowedIdentityProviders(toModel(resourceRep.getIdentityProviders(), realm));
if (allowedIdentityProviders == null || allowedIdentityProviders.isEmpty()) {
allowedIdentityProviders = new ArrayList<String>();
for (IdentityProviderModel identityProvider : realm.getIdentityProviders()) {
allowedIdentityProviders.add(identityProvider.getId());
}
}
applicationModel.updateAllowedIdentityProviders(allowedIdentityProviders);
return applicationModel; return applicationModel;
} }
@ -536,9 +528,7 @@ public class RepresentationToModel {
setClaims(resource, rep.getClaims()); setClaims(resource, rep.getClaims());
} }
if (rep.getAllowedIdentityProviders() != null) { updateClientIdentityProvides(rep.getIdentityProviders(), resource);
resource.updateAllowedIdentityProviders(rep.getAllowedIdentityProviders());
}
} }
public static void setClaims(ClientModel model, ClaimRepresentation rep) { public static void setClaims(ClientModel model, ClaimRepresentation rep) {
@ -613,17 +603,7 @@ public class RepresentationToModel {
public static OAuthClientModel createOAuthClient(OAuthClientRepresentation rep, RealmModel realm) { public static OAuthClientModel createOAuthClient(OAuthClientRepresentation rep, RealmModel realm) {
OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm); OAuthClientModel model = createOAuthClient(rep.getId(), rep.getName(), realm);
List<String> allowedIdentityProviders = rep.getAllowedIdentityProviders(); model.updateAllowedIdentityProviders(toModel(rep.getIdentityProviders(), realm));
if (allowedIdentityProviders == null || allowedIdentityProviders.isEmpty()) {
allowedIdentityProviders = new ArrayList<String>();
for (IdentityProviderModel identityProvider : realm.getIdentityProviders()) {
allowedIdentityProviders.add(identityProvider.getId());
}
}
model.updateAllowedIdentityProviders(allowedIdentityProviders);
updateOAuthClient(rep, model); updateOAuthClient(rep, model);
return model; return model;
@ -667,9 +647,7 @@ public class RepresentationToModel {
} }
} }
if (rep.getAllowedIdentityProviders() != null) { updateClientIdentityProvides(rep.getIdentityProviders(), model);
model.updateAllowedIdentityProviders(rep.getAllowedIdentityProviders());
}
if (rep.getProtocolMappers() != null) { if (rep.getProtocolMappers() != null) {
Set<String> ids = new HashSet<String>(); Set<String> ids = new HashSet<String>();
@ -868,4 +846,48 @@ public class RepresentationToModel {
model.setConfig(rep.getConfig()); model.setConfig(rep.getConfig());
return model; return model;
} }
private static List<ClientIdentityProviderMappingModel> toModel(List<ClientIdentityProviderMappingRepresentation> repIdentityProviders, RealmModel realm) {
List<ClientIdentityProviderMappingModel> allowedIdentityProviders = 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 {
for (ClientIdentityProviderMappingRepresentation rep : repIdentityProviders) {
ClientIdentityProviderMappingModel identityProviderMapping = new ClientIdentityProviderMappingModel();
identityProviderMapping.setIdentityProvider(rep.getId());
identityProviderMapping.setRetrieveToken(rep.isRetrieveToken());
allowedIdentityProviders.add(identityProviderMapping);
}
}
return allowedIdentityProviders;
}
private static void updateClientIdentityProvides(List<ClientIdentityProviderMappingRepresentation> identityProviders, ClientModel resource) {
if (identityProviders != null) {
List<ClientIdentityProviderMappingModel> allowedIdentityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
for (ClientIdentityProviderMappingRepresentation mappingRepresentation : identityProviders) {
ClientIdentityProviderMappingModel identityProviderMapping = new ClientIdentityProviderMappingModel();
identityProviderMapping.setIdentityProvider(mappingRepresentation.getId());
identityProviderMapping.setRetrieveToken(mappingRepresentation.isRetrieveToken());
allowedIdentityProviders.add(identityProviderMapping);
}
resource.updateAllowedIdentityProviders(allowedIdentityProviders);
}
}
} }

View file

@ -1,5 +1,6 @@
package org.keycloak.models.cache; package org.keycloak.models.cache;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -263,15 +264,15 @@ public abstract class ClientAdapter implements ClientModel {
} }
@Override @Override
public void updateAllowedIdentityProviders(List<String> identityProviders) { public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
getDelegateForUpdate(); getDelegateForUpdate();
updatedClient.updateAllowedIdentityProviders(identityProviders); updatedClient.updateAllowedIdentityProviders(identityProviders);
} }
@Override @Override
public List<String> getAllowedIdentityProviders() { public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
if (updatedClient != null) return updatedClient.getAllowedIdentityProviders(); if (updatedClient != null) return updatedClient.getIdentityProviders();
return cachedClient.getAllowedIdentityProviders(); return cachedClient.getIdentityProviders();
} }
@Override @Override
@ -280,6 +281,12 @@ public abstract class ClientAdapter implements ClientModel {
return cachedClient.hasIdentityProvider(providerId); return cachedClient.hasIdentityProvider(providerId);
} }
@Override
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
if (updatedClient != null) return updatedClient.isAllowedRetrieveTokenFromIdentityProvider(providerId);
return cachedClient.isAllowedRetrieveTokenFromIdentityProvider(providerId);
}
@Override @Override
public Set<ProtocolMapperModel> getProtocolMappers() { public Set<ProtocolMapperModel> getProtocolMappers() {
if (updatedClient != null) return updatedClient.getProtocolMappers(); if (updatedClient != null) return updatedClient.getProtocolMappers();

View file

@ -1,5 +1,6 @@
package org.keycloak.models.cache.entities; package org.keycloak.models.cache.entities;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -35,7 +36,7 @@ public class CachedClient {
protected int notBefore; protected int notBefore;
protected Set<String> scope = new HashSet<String>(); protected Set<String> scope = new HashSet<String>();
protected Set<String> webOrigins = new HashSet<String>(); protected Set<String> webOrigins = new HashSet<String>();
private List<String> allowedIdentityProviders = new ArrayList<String>(); private List<ClientIdentityProviderMappingModel> identityProviders = new ArrayList<ClientIdentityProviderMappingModel>();
private Set<ProtocolMapperModel> protocolClaimMappings = new HashSet<ProtocolMapperModel>(); private Set<ProtocolMapperModel> protocolClaimMappings = new HashSet<ProtocolMapperModel>();
public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) { public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
@ -57,7 +58,7 @@ public class CachedClient {
for (RoleModel role : model.getScopeMappings()) { for (RoleModel role : model.getScopeMappings()) {
scope.add(role.getId()); scope.add(role.getId());
} }
this.allowedIdentityProviders = model.getAllowedIdentityProviders(); this.identityProviders = model.getIdentityProviders();
protocolClaimMappings.addAll(model.getProtocolMappers()); protocolClaimMappings.addAll(model.getProtocolMappers());
} }
@ -125,15 +126,31 @@ public class CachedClient {
return frontchannelLogout; return frontchannelLogout;
} }
public List<String> getAllowedIdentityProviders() { public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
return this.allowedIdentityProviders; return this.identityProviders;
} }
public boolean hasIdentityProvider(String providerId) { public boolean hasIdentityProvider(String providerId) {
return this.allowedIdentityProviders.contains(providerId); for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
if (model.getIdentityProvider().equals(providerId)) {
return true;
}
}
return false;
} }
public Set<ProtocolMapperModel> getProtocolClaimMappings() { public Set<ProtocolMapperModel> getProtocolClaimMappings() {
return protocolClaimMappings; return protocolClaimMappings;
} }
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
if (model.getIdentityProvider().equals(providerId)) {
return model.isRetrieveToken();
}
}
return false;
}
} }

View file

@ -1,14 +1,15 @@
package org.keycloak.models.jpa; package org.keycloak.models.jpa;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
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.IdentityProviderEntity;
import org.keycloak.models.jpa.entities.ProtocolMapperEntity; import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
import org.keycloak.models.jpa.entities.RealmEntity;
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;
@ -303,47 +304,96 @@ public abstract class ClientAdapter implements ClientModel {
} }
@Override @Override
public void updateAllowedIdentityProviders(List<String> identityProviders) { public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
Collection<IdentityProviderEntity> entities = entity.getAllowedIdentityProviders(); Collection<ClientIdentityProviderMappingEntity> entities = entity.getIdentityProviders();
Set<String> already = new HashSet<String>(); Set<String> already = new HashSet<String>();
List<IdentityProviderEntity> remove = new ArrayList<IdentityProviderEntity>(); List<ClientIdentityProviderMappingEntity> remove = new ArrayList<ClientIdentityProviderMappingEntity>();
for (IdentityProviderEntity rel : entities) {
if (!contains(rel.getId(), identityProviders.toArray(new String[identityProviders.size()]))) { for (ClientIdentityProviderMappingEntity entity : entities) {
remove.add(rel); IdentityProviderEntity identityProvider = entity.getIdentityProvider();
boolean toRemove = true;
for (ClientIdentityProviderMappingModel model : identityProviders) {
if (model.getIdentityProvider().equals(identityProvider.getId())) {
toRemove = false;
break;
}
}
if (toRemove) {
remove.add(entity);
} else { } else {
already.add(rel.getId()); already.add(entity.getIdentityProvider().getId());
} }
} }
for (IdentityProviderEntity entity : remove) { for (ClientIdentityProviderMappingEntity entity : remove) {
entities.remove(entity); entities.remove(entity);
em.remove(entity);
} }
em.flush(); em.flush();
for (String providerId : identityProviders) { for (ClientIdentityProviderMappingModel model : identityProviders) {
if (!already.contains(providerId)) { ClientIdentityProviderMappingEntity mappingEntity = null;
TypedQuery<IdentityProviderEntity> query = em.createNamedQuery("findIdentityProviderById", IdentityProviderEntity.class).setParameter("id", providerId);
IdentityProviderEntity providerEntity = query.getSingleResult(); if (!already.contains(model.getIdentityProvider())) {
entities.add(providerEntity); mappingEntity = new ClientIdentityProviderMappingEntity();
entities.add(mappingEntity);
} else {
for (ClientIdentityProviderMappingEntity entity : entities) {
if (entity.getIdentityProvider().getId().equals(model.getIdentityProvider())) {
mappingEntity = entity;
break;
} }
} }
}
TypedQuery<IdentityProviderEntity> query = em.createNamedQuery("findIdentityProviderById", IdentityProviderEntity.class).setParameter("id", model.getIdentityProvider());
IdentityProviderEntity identityProviderEntity = query.getSingleResult();
mappingEntity.setIdentityProvider(identityProviderEntity);
mappingEntity.setClient(this.entity);
mappingEntity.setRetrieveToken(model.isRetrieveToken());
em.persist(mappingEntity);
}
em.flush(); em.flush();
} }
@Override @Override
public List<String> getAllowedIdentityProviders() { public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
Collection<IdentityProviderEntity> entities = entity.getAllowedIdentityProviders(); List<ClientIdentityProviderMappingModel> models = new ArrayList<ClientIdentityProviderMappingModel>();
List<String> providers = new ArrayList<String>();
for (IdentityProviderEntity entity : entities) { for (ClientIdentityProviderMappingEntity entity : this.entity.getIdentityProviders()) {
providers.add(entity.getId()); ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
model.setIdentityProvider(entity.getIdentityProvider().getId());
model.setRetrieveToken(entity.isRetrieveToken());
models.add(model);
} }
return providers; return models;
} }
@Override @Override
public boolean hasIdentityProvider(String providerId) { public boolean hasIdentityProvider(String providerId) {
List<String> allowedIdentityProviders = getAllowedIdentityProviders(); for (ClientIdentityProviderMappingModel model : getIdentityProviders()) {
return allowedIdentityProviders.contains(providerId); if (model.getIdentityProvider().equals(providerId)) {
return true;
}
}
return false;
}
@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) {

View file

@ -73,9 +73,8 @@ public abstract class ClientEntity {
@CollectionTable(name="CLIENT_ATTRIBUTES", joinColumns={ @JoinColumn(name="CLIENT_ID") }) @CollectionTable(name="CLIENT_ATTRIBUTES", joinColumns={ @JoinColumn(name="CLIENT_ID") })
protected Map<String, String> attributes = new HashMap<String, String>(); protected Map<String, String> attributes = new HashMap<String, String>();
@OneToMany(fetch = FetchType.LAZY) @OneToMany(fetch = FetchType.LAZY, mappedBy = "client", cascade = CascadeType.REMOVE)
@JoinTable(name="CLIENT_ALLOWED_IDENTITY_PROVIDER", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="INTERNAL_ID")}) Collection<ClientIdentityProviderMappingEntity> identityProviders = new ArrayList<ClientIdentityProviderMappingEntity>();
Collection<IdentityProviderEntity> allowedIdentityProviders = new ArrayList<IdentityProviderEntity>();
@OneToMany(fetch = FetchType.LAZY) @OneToMany(fetch = FetchType.LAZY)
@JoinTable(name="CLIENT_PROTOCOL_MAPPER", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="MAPPING_ID")}) @JoinTable(name="CLIENT_PROTOCOL_MAPPER", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="MAPPING_ID")})
@ -193,12 +192,12 @@ public abstract class ClientEntity {
this.frontchannelLogout = frontchannelLogout; this.frontchannelLogout = frontchannelLogout;
} }
public Collection<IdentityProviderEntity> getAllowedIdentityProviders() { public Collection<ClientIdentityProviderMappingEntity> getIdentityProviders() {
return this.allowedIdentityProviders; return this.identityProviders;
} }
public void setAllowedIdentityProviders(Collection<IdentityProviderEntity> allowedIdentityProviders) { public void setIdentityProviders(Collection<ClientIdentityProviderMappingEntity> identityProviders) {
this.allowedIdentityProviders = allowedIdentityProviders; this.identityProviders = identityProviders;
} }
public Collection<ProtocolMapperEntity> getProtocolMappers() { public Collection<ProtocolMapperEntity> getProtocolMappers() {

View file

@ -0,0 +1,121 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.io.Serializable;
/**
* @author pedroigor
*/
@Table(name="CLIENT_IDENTITY_PROVIDER_MAPPING")
@Entity
@IdClass(ClientIdentityProviderMappingEntity.Key.class)
public class ClientIdentityProviderMappingEntity {
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CLIENT_ID")
private ClientEntity client;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "IDENTITY_PROVIDER_ID")
private IdentityProviderEntity identityProvider;
@Column(name = "RETRIEVE_TOKEN")
private boolean retrieveToken;
public ClientEntity getClient() {
return this.client;
}
public void setClient(ClientEntity client) {
this.client = client;
}
public IdentityProviderEntity getIdentityProvider() {
return this.identityProvider;
}
public void setIdentityProvider(IdentityProviderEntity identityProvider) {
this.identityProvider = identityProvider;
}
public void setRetrieveToken(boolean retrieveToken) {
this.retrieveToken = retrieveToken;
}
public boolean isRetrieveToken() {
return retrieveToken;
}
public static class Key implements Serializable {
private ClientEntity client;
private IdentityProviderEntity identityProvider;
public Key() {
}
public Key(ClientEntity client, IdentityProviderEntity identityProvider) {
this.client = client;
this.identityProvider = identityProvider;
}
public ClientEntity getUser() {
return client;
}
public IdentityProviderEntity getIdentityProvider() {
return identityProvider;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (identityProvider != null ? !identityProvider.getId().equals(key.identityProvider.getId()) : key.identityProvider != null)
return false;
if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
return true;
}
@Override
public int hashCode() {
int result = client != null ? client.getId().hashCode() : 0;
result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
return result;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClientIdentityProviderMappingEntity key = (ClientIdentityProviderMappingEntity) o;
if (identityProvider != null ? !identityProvider.getId().equals(key.identityProvider.getId()) : key.identityProvider != null)
return false;
if (client != null ? !client.getId().equals(key.client != null ? key.client.getId() : null) : key.client != null) return false;
return true;
}
@Override
public int hashCode() {
int result = client != null ? client.getId().hashCode() : 0;
result = 31 * result + (identityProvider != null ? identityProvider.hashCode() : 0);
return result;
}
}

View file

@ -2,6 +2,7 @@ package org.keycloak.models.mongo.keycloak.adapters;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity; import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
@ -9,6 +10,7 @@ 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.entities.ClientEntity; import org.keycloak.models.entities.ClientEntity;
import org.keycloak.models.entities.ClientIdentityProviderMappingEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.mongo.utils.MongoModelUtils; import org.keycloak.models.mongo.utils.MongoModelUtils;
@ -323,24 +325,58 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
} }
@Override @Override
public void updateAllowedIdentityProviders(List<String> identityProviders) { public void updateAllowedIdentityProviders(List<ClientIdentityProviderMappingModel> identityProviders) {
List<String> providerIds = new ArrayList<String>(); List<ClientIdentityProviderMappingEntity> stored = getMongoEntityAsClient().getIdentityProviders();
for (String providerId : identityProviders) {
providerIds.add(providerId); for (ClientIdentityProviderMappingModel model : identityProviders) {
ClientIdentityProviderMappingEntity entity = new ClientIdentityProviderMappingEntity();
entity.setId(model.getIdentityProvider());
entity.setRetrieveToken(model.isRetrieveToken());
} }
getMongoEntityAsClient().setAllowedIdentityProviders(identityProviders); getMongoEntityAsClient().setIdentityProviders(stored);
updateMongoEntity(); updateMongoEntity();
} }
@Override @Override
public List<String> getAllowedIdentityProviders() { public List<ClientIdentityProviderMappingModel> getIdentityProviders() {
return getMongoEntityAsClient().getAllowedIdentityProviders(); List<ClientIdentityProviderMappingModel> models = new ArrayList<ClientIdentityProviderMappingModel>();
for (ClientIdentityProviderMappingEntity entity : getMongoEntityAsClient().getIdentityProviders()) {
ClientIdentityProviderMappingModel model = new ClientIdentityProviderMappingModel();
model.setIdentityProvider(entity.getId());
model.setRetrieveToken(entity.isRetrieveToken());
models.add(model);
}
return models;
} }
@Override @Override
public boolean hasIdentityProvider(String providerId) { public boolean hasIdentityProvider(String providerId) {
List<String> allowedIdentityProviders = getMongoEntityAsClient().getAllowedIdentityProviders(); for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntityAsClient().getIdentityProviders()) {
return allowedIdentityProviders.contains(providerId); String identityProvider = identityProviderMappingModel.getId();
if (identityProvider.equals(providerId)) {
return true;
} }
} }
return false;
}
@Override
public boolean isAllowedRetrieveTokenFromIdentityProvider(String providerId) {
for (ClientIdentityProviderMappingEntity identityProviderMappingModel : getMongoEntityAsClient().getIdentityProviders()) {
if (identityProviderMappingModel.getId().equals(providerId)) {
return identityProviderMappingModel.isRetrieveToken();
}
}
return false;
}
}

View file

@ -186,6 +186,10 @@ public class IdentityBrokerService {
return corsResponse(badRequest("Client [" + audience + "] not authorized."), clientModel); 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);
}
if (OAuthClientModel.class.isInstance(clientModel) && !forceRetrieval) { if (OAuthClientModel.class.isInstance(clientModel) && !forceRetrieval) {
return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo) return corsResponse(Flows.forms(this.session, this.realmModel, clientModel, this.uriInfo)
.setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders())) .setClientSessionCode(authManager.extractAuthorizationHeaderToken(this.request.getHttpHeaders()))

View file

@ -1,6 +1,7 @@
package org.keycloak.services.resources.admin; package org.keycloak.services.resources.admin;
import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
@ -17,6 +18,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -63,11 +65,15 @@ public class IdentityProviderResource {
private void removeClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderModel identityProvider) { private void removeClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderModel identityProvider) {
for (ClientModel clientModel : clients) { for (ClientModel clientModel : clients) {
List<String> allowedIdentityProviders = clientModel.getAllowedIdentityProviders(); List<ClientIdentityProviderMappingModel> identityProviders = clientModel.getIdentityProviders();
allowedIdentityProviders.remove(identityProvider.getId()); for (ClientIdentityProviderMappingModel providerMappingModel : new ArrayList<ClientIdentityProviderMappingModel>(identityProviders)) {
if (providerMappingModel.getIdentityProvider().equals(identityProvider.getId())) {
identityProviders.remove(providerMappingModel);
}
}
clientModel.updateAllowedIdentityProviders(allowedIdentityProviders); clientModel.updateAllowedIdentityProviders(identityProviders);
} }
} }

View file

@ -7,6 +7,7 @@ import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.broker.provider.IdentityProvider; import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory; import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
@ -179,9 +180,12 @@ public class IdentityProvidersResource {
private void updateClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderRepresentation identityProvider) { private void updateClientIdentityProviders(List<? extends ClientModel> clients, IdentityProviderRepresentation identityProvider) {
for (ClientModel clientModel : clients) { for (ClientModel clientModel : clients) {
List<String> allowedIdentityProviders = clientModel.getAllowedIdentityProviders(); List<ClientIdentityProviderMappingModel> allowedIdentityProviders = clientModel.getIdentityProviders();
ClientIdentityProviderMappingModel providerMappingModel = new ClientIdentityProviderMappingModel();
allowedIdentityProviders.add(identityProvider.getId()); providerMappingModel.setIdentityProvider(identityProvider.getId());
allowedIdentityProviders.add(providerMappingModel);
clientModel.updateAllowedIdentityProviders(allowedIdentityProviders); clientModel.updateAllowedIdentityProviders(allowedIdentityProviders);
} }

View file

@ -25,6 +25,8 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.models.ApplicationModel; import org.keycloak.models.ApplicationModel;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel;
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;
@ -156,11 +158,18 @@ public abstract class AbstractIdentityProviderTest {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
RealmModel realm = getRealm(); RealmModel realm = getRealm();
ApplicationModel applicationModel = realm.getApplicationByName("test-app"); ApplicationModel applicationModel = realm.getApplicationByName("test-app");
List<String> allowedIdentityProviders = applicationModel.getAllowedIdentityProviders(); List<ClientIdentityProviderMappingModel> allowedIdentityProviders = applicationModel.getIdentityProviders();
ClientIdentityProviderMappingModel mapping = null;
assertTrue(allowedIdentityProviders.contains(identityProviderModel.getId())); for (ClientIdentityProviderMappingModel model : allowedIdentityProviders) {
if (model.getIdentityProvider().equals(identityProviderModel.getId())) {
mapping = model;
}
}
allowedIdentityProviders.remove(identityProviderModel.getId()); assertNotNull(mapping);
allowedIdentityProviders.remove(mapping);
this.driver.navigate().to("http://localhost:8081/test-app/"); this.driver.navigate().to("http://localhost:8081/test-app/");
@ -173,7 +182,7 @@ public abstract class AbstractIdentityProviderTest {
} }
allowedIdentityProviders.add(identityProviderModel.getId()); allowedIdentityProviders.add(mapping);
applicationModel.updateAllowedIdentityProviders(allowedIdentityProviders); applicationModel.updateAllowedIdentityProviders(allowedIdentityProviders);
@ -317,6 +326,18 @@ public abstract class AbstractIdentityProviderTest {
assertNotNull(identityModel.getToken()); 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);
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());
@ -331,6 +352,14 @@ public abstract class AbstractIdentityProviderTest {
WebTarget tokenEndpoint = client.target(tokenEndpointUrl); WebTarget tokenEndpoint = client.target(tokenEndpointUrl);
Response response = tokenEndpoint.request().get(); Response response = tokenEndpoint.request().get();
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
providerMappingModel.setRetrieveToken(true);
client = ClientBuilder.newBuilder().register(authFilter).build();
tokenEndpoint = client.target(tokenEndpointUrl);
response = tokenEndpoint.request().get();
assertEquals(Status.OK.getStatusCode(), response.getStatus()); assertEquals(Status.OK.getStatusCode(), response.getStatus());
assertNotNull(response.readEntity(String.class)); assertNotNull(response.readEntity(String.class));
@ -375,6 +404,18 @@ public abstract class AbstractIdentityProviderTest {
assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE)); assertTrue(oauth.getCurrentQuery().containsKey(OAuth2Constants.CODE));
ClientModel clientModel = getRealm().findClient("third-party");
ClientIdentityProviderMappingModel providerMappingModel = null;
for (ClientIdentityProviderMappingModel identityProviderMappingModel : clientModel.getIdentityProviders()) {
if (identityProviderMappingModel.getIdentityProvider().equals(getProviderId())) {
providerMappingModel = identityProviderMappingModel;
break;
}
}
providerMappingModel.setRetrieveToken(true);
AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password"); AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "password");
URI tokenEndpointUrl = Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName()); URI tokenEndpointUrl = Urls.identityProviderRetrieveToken(BASE_URI, getProviderId(), getRealm().getName());
String authHeader = "Bearer " + accessToken.getAccessToken(); String authHeader = "Bearer " + accessToken.getAccessToken();

View file

@ -25,6 +25,8 @@ import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.saml.SAMLIdentityProvider; import org.keycloak.broker.saml.SAMLIdentityProvider;
import org.keycloak.broker.saml.SAMLIdentityProviderConfig; import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory; import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.models.ClientIdentityProviderMappingModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
@ -113,6 +115,31 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertFalse(identityProviderModel.isAuthenticateByDefault()); assertFalse(identityProviderModel.isAuthenticateByDefault());
} }
@Test
public void testApplicationIdentityProviders() throws Exception {
RealmModel realm = installTestRealm();
ClientModel client = realm.findClient("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.updateAllowedIdentityProviders(identityProviders);
client = realm.findClientById(client.getId());
identityProviders = client.getIdentityProviders();
assertEquals(0, identityProviders.size());
}
private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) { private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
assertFalse(identityProviders.isEmpty()); assertFalse(identityProviders.isEmpty());

View file

@ -197,8 +197,11 @@
"/test-app/*" "/test-app/*"
], ],
"webOrigins": [], "webOrigins": [],
"allowedIdentityProviders": [ "identityProviders": [
"kc-oidc-idp" {
"id": "kc-oidc-idp",
"retrieveToken": false
}
] ]
} }
], ],