[KEYCLOAK-883] - Refactoring to services endpoints and exposing them through admin client.
This commit is contained in:
parent
98c75f162a
commit
ff1f10d7a7
16 changed files with 463 additions and 167 deletions
|
@ -26,6 +26,7 @@ import java.util.Map;
|
|||
public class IdentityProviderRepresentation {
|
||||
|
||||
protected String id;
|
||||
protected String internalId;
|
||||
protected String providerId;
|
||||
protected String name;
|
||||
protected boolean enabled = true;
|
||||
|
@ -34,6 +35,14 @@ public class IdentityProviderRepresentation {
|
|||
protected String groupName;
|
||||
protected Map<String, String> config = new HashMap<String, String>();
|
||||
|
||||
public String getInternalId() {
|
||||
return this.internalId;
|
||||
}
|
||||
|
||||
public void setInternalId(String internalId) {
|
||||
this.internalId = internalId;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,25 @@ module.config([ '$routeProvider', function($routeProvider) {
|
|||
return {};
|
||||
},
|
||||
providerFactory : function(IdentityProviderFactoryLoader) {
|
||||
return IdentityProviderFactoryLoader();
|
||||
return {};
|
||||
}
|
||||
},
|
||||
controller : 'RealmIdentityProviderCtrl'
|
||||
})
|
||||
.when('/create/identity-provider/:realm/:provider_id', {
|
||||
templateUrl : function(params){ return 'partials/realm-identity-provider-' + params.provider_id + '.html'; },
|
||||
resolve : {
|
||||
realm : function(RealmLoader) {
|
||||
return RealmLoader();
|
||||
},
|
||||
serverInfo : function(ServerInfoLoader) {
|
||||
return ServerInfoLoader();
|
||||
},
|
||||
instance : function(IdentityProviderLoader) {
|
||||
return {};
|
||||
},
|
||||
providerFactory : function(IdentityProviderFactoryLoader) {
|
||||
return new IdentityProviderFactoryLoader();
|
||||
}
|
||||
},
|
||||
controller : 'RealmIdentityProviderCtrl'
|
||||
|
|
|
@ -722,7 +722,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
|
|||
$scope.callbackUrl = $location.absUrl().replace(/\/admin.*/, "/broker/") + realm.realm + "/" ;
|
||||
|
||||
$scope.addProvider = function(provider) {
|
||||
$location.url("/realms/" + realm.realm + "/identity-provider-settings/provider/" + provider.id + "/" + provider.id);
|
||||
$location.url("/create/identity-provider/" + realm.realm + "/" + provider.id);
|
||||
};
|
||||
|
||||
$scope.remove = function() {
|
||||
|
@ -746,7 +746,8 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
|
|||
});
|
||||
} else {
|
||||
IdentityProvider.update({
|
||||
realm: $scope.realm.realm
|
||||
realm: $scope.realm.realm,
|
||||
id: $scope.identityProvider.internalId
|
||||
}, $scope.identityProvider, function () {
|
||||
$location.url("/realms/" + realm.realm + "/identity-provider-settings");
|
||||
Notifications.success("The " + $scope.identityProvider.name + " provider has been update.");
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package org.keycloak.admin.client.resource;
|
||||
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
*/
|
||||
public interface IdentityProviderResource {
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
IdentityProviderRepresentation toRepresentation();
|
||||
|
||||
@PUT
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
void update(IdentityProviderRepresentation identityProviderRepresentation);
|
||||
|
||||
@DELETE
|
||||
void remove();
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.keycloak.admin.client.resource;
|
||||
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
*/
|
||||
public interface IdentityProvidersResource {
|
||||
|
||||
@Path("{id}")
|
||||
IdentityProviderResource get(@PathParam("id") String id);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
List<IdentityProviderRepresentation> findAll();
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
void create(IdentityProviderRepresentation identityProvider);
|
||||
}
|
|
@ -35,6 +35,9 @@ public interface RealmResource {
|
|||
@Path("roles")
|
||||
public RolesResource roles();
|
||||
|
||||
@Path("identity-provider")
|
||||
IdentityProvidersResource identityProviders();
|
||||
|
||||
@DELETE
|
||||
public void remove();
|
||||
|
||||
|
|
|
@ -19,13 +19,15 @@ public class AdminRoles {
|
|||
public static String VIEW_APPLICATIONS = "view-applications";
|
||||
public static String VIEW_CLIENTS = "view-clients";
|
||||
public static String VIEW_EVENTS = "view-events";
|
||||
public static String VIEW_IDENTITY_PROVIDERS = "view-identity-providers";
|
||||
|
||||
public static String MANAGE_REALM = "manage-realm";
|
||||
public static String MANAGE_USERS = "manage-users";
|
||||
public static String MANAGE_APPLICATIONS = "manage-applications";
|
||||
public static String MANAGE_IDENTITY_PROVIDERS = "manage-identity-providers";
|
||||
public static String MANAGE_CLIENTS = "manage-clients";
|
||||
public static String MANAGE_EVENTS = "manage-events";
|
||||
|
||||
public static String[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_APPLICATIONS, VIEW_CLIENTS, VIEW_EVENTS, MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS, MANAGE_EVENTS};
|
||||
public static String[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_APPLICATIONS, VIEW_CLIENTS, VIEW_EVENTS, VIEW_IDENTITY_PROVIDERS, MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS, MANAGE_EVENTS, MANAGE_IDENTITY_PROVIDERS};
|
||||
|
||||
}
|
||||
|
|
|
@ -146,16 +146,7 @@ public class ModelToRepresentation {
|
|||
}
|
||||
|
||||
for (IdentityProviderModel provider : realm.getIdentityProviders()) {
|
||||
IdentityProviderRepresentation providerRep = new IdentityProviderRepresentation();
|
||||
|
||||
providerRep.setProviderId(provider.getProviderId());
|
||||
providerRep.setId(provider.getId());
|
||||
providerRep.setName(provider.getName());
|
||||
providerRep.setEnabled(provider.isEnabled());
|
||||
providerRep.setUpdateProfileFirstLogin(provider.isUpdateProfileFirstLogin());
|
||||
providerRep.setConfig(provider.getConfig());
|
||||
|
||||
rep.addIdentityProvider(providerRep);
|
||||
rep.addIdentityProvider(toRepresentation(provider));
|
||||
}
|
||||
|
||||
return rep;
|
||||
|
@ -306,4 +297,19 @@ public class ModelToRepresentation {
|
|||
rep.setLastSync(model.getLastSync());
|
||||
return rep;
|
||||
}
|
||||
|
||||
public static IdentityProviderRepresentation toRepresentation(IdentityProviderModel identityProviderModel) {
|
||||
IdentityProviderRepresentation providerRep = new IdentityProviderRepresentation();
|
||||
|
||||
providerRep.setInternalId(identityProviderModel.getInternalId());
|
||||
providerRep.setProviderId(identityProviderModel.getProviderId());
|
||||
providerRep.setId(identityProviderModel.getId());
|
||||
providerRep.setName(identityProviderModel.getName());
|
||||
providerRep.setEnabled(identityProviderModel.isEnabled());
|
||||
providerRep.setStoreToken(identityProviderModel.isStoreToken());
|
||||
providerRep.setUpdateProfileFirstLogin(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
providerRep.setConfig(identityProviderModel.getConfig());
|
||||
|
||||
return providerRep;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -744,19 +744,24 @@ public class RepresentationToModel {
|
|||
|
||||
private static void importIdentityProviders(RealmRepresentation rep, RealmModel newRealm) {
|
||||
if (rep.getIdentityProviders() != null) {
|
||||
for (IdentityProviderRepresentation identityProviderRepresentation : rep.getIdentityProviders()) {
|
||||
IdentityProviderModel identityProviderModel = new IdentityProviderModel();
|
||||
|
||||
identityProviderModel.setId(identityProviderRepresentation.getId());
|
||||
identityProviderModel.setProviderId(identityProviderRepresentation.getProviderId());
|
||||
identityProviderModel.setName(identityProviderRepresentation.getName());
|
||||
identityProviderModel.setEnabled(identityProviderRepresentation.isEnabled());
|
||||
identityProviderModel.setUpdateProfileFirstLogin(identityProviderRepresentation.isUpdateProfileFirstLogin());
|
||||
identityProviderModel.setStoreToken(identityProviderRepresentation.isStoreToken());
|
||||
identityProviderModel.setConfig(identityProviderRepresentation.getConfig());
|
||||
|
||||
newRealm.addIdentityProvider(identityProviderModel);
|
||||
for (IdentityProviderRepresentation representation : rep.getIdentityProviders()) {
|
||||
newRealm.addIdentityProvider(toModel(representation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IdentityProviderModel toModel(IdentityProviderRepresentation representation) {
|
||||
IdentityProviderModel identityProviderModel = new IdentityProviderModel();
|
||||
|
||||
identityProviderModel.setInternalId(representation.getInternalId());
|
||||
identityProviderModel.setId(representation.getId());
|
||||
identityProviderModel.setProviderId(representation.getProviderId());
|
||||
identityProviderModel.setName(representation.getName());
|
||||
identityProviderModel.setEnabled(representation.isEnabled());
|
||||
identityProviderModel.setUpdateProfileFirstLogin(representation.isUpdateProfileFirstLogin());
|
||||
identityProviderModel.setStoreToken(representation.isStoreToken());
|
||||
identityProviderModel.setConfig(representation.getConfig());
|
||||
|
||||
return identityProviderModel;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,6 +204,10 @@ public class AuthenticationBrokerResource {
|
|||
if (identityProviderConfig.isStoreToken()) {
|
||||
FederatedIdentityModel identity = this.session.users().getFederatedIdentity(authResult.getUser(), providerId, realm);
|
||||
|
||||
if (identity == null) {
|
||||
return corsResponse(Flows.errors().error("User [" + authResult.getUser().getId() + "] is not associated with identity provider [" + providerId + "].", Response.Status.FORBIDDEN), clientModel);
|
||||
}
|
||||
|
||||
return corsResponse(identityProvider.retrieveToken(identity), clientModel);
|
||||
}
|
||||
|
||||
|
@ -229,17 +233,19 @@ public class AuthenticationBrokerResource {
|
|||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.getRealmByName(realmName);
|
||||
|
||||
try {
|
||||
IdentityProvider provider = getIdentityProvider(realm, providerId);
|
||||
IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(realm, providerId);
|
||||
|
||||
if (provider == null) {
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Social provider not found").createErrorPage();
|
||||
try {
|
||||
IdentityProvider identityProvider = getIdentityProvider(realm, providerId);
|
||||
|
||||
if (identityProvider == null) {
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Social identityProvider not found").createErrorPage();
|
||||
}
|
||||
|
||||
String relayState = provider.getRelayState(createAuthenticationRequest(providerId, null, realm, null));
|
||||
String relayState = identityProvider.getRelayState(createAuthenticationRequest(providerId, null, realm, null));
|
||||
|
||||
if (relayState == null) {
|
||||
return redirectToErrorPage(realm, "No relay state from identity provider.");
|
||||
return redirectToErrorPage(realm, "No relay state from identity identityProvider.");
|
||||
}
|
||||
|
||||
ClientSessionCode clientCode = isValidAuthorizationCode(relayState, realm);
|
||||
|
@ -256,7 +262,7 @@ public class AuthenticationBrokerResource {
|
|||
return response;
|
||||
}
|
||||
|
||||
AuthenticationResponse authenticationResponse = provider.handleResponse(createAuthenticationRequest(providerId, null, realm, clientSession));
|
||||
AuthenticationResponse authenticationResponse = identityProvider.handleResponse(createAuthenticationRequest(providerId, null, realm, clientSession));
|
||||
|
||||
response = authenticationResponse.getResponse();
|
||||
|
||||
|
@ -266,14 +272,16 @@ public class AuthenticationBrokerResource {
|
|||
|
||||
FederatedIdentity identity = authenticationResponse.getUser();
|
||||
|
||||
if (!identityProviderConfig.isStoreToken()) {
|
||||
identity.setToken(null);
|
||||
}
|
||||
|
||||
return performLocalAuthentication(realm, providerId, identity, clientCode);
|
||||
} catch (Exception e) {
|
||||
if (session.getTransaction().isActive()) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
|
||||
IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(realm, providerId);
|
||||
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Authentication failed. Could not authenticate against Identity Provider [" + identityProviderConfig.getName() + "].").createErrorPage();
|
||||
} finally {
|
||||
if (session.getTransaction().isActive()) {
|
||||
|
|
|
@ -1,36 +1,21 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
|
||||
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
|
||||
import org.keycloak.broker.provider.IdentityProvider;
|
||||
import org.keycloak.broker.provider.IdentityProviderFactory;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.social.SocialIdentityProvider;
|
||||
import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* @author Pedro Igor
|
||||
|
@ -39,132 +24,36 @@ public class IdentityProviderResource {
|
|||
|
||||
private final RealmModel realm;
|
||||
private final KeycloakSession session;
|
||||
private final IdentityProviderModel identityProviderModel;
|
||||
|
||||
public IdentityProviderResource(RealmModel realm, KeycloakSession session) {
|
||||
public IdentityProviderResource(RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel) {
|
||||
this.realm = realm;
|
||||
this.session = session;
|
||||
this.identityProviderModel = identityProviderModel;
|
||||
}
|
||||
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public List<IdentityProviderModel> getIdentityProviders() {
|
||||
return realm.getIdentityProviders();
|
||||
public IdentityProviderRepresentation getIdentityProvider() {
|
||||
return ModelToRepresentation.toRepresentation(this.identityProviderModel);
|
||||
}
|
||||
|
||||
@Path("/providers/{provider_id}")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Response getIdentityProviders(@PathParam("provider_id") String providerId) {
|
||||
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
|
||||
|
||||
if (providerFactory != null) {
|
||||
return Response.ok(providerFactory).build();
|
||||
}
|
||||
|
||||
return Response.status(BAD_REQUEST).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response create(@Context UriInfo uriInfo, IdentityProviderModel providerModel) {
|
||||
realm.addIdentityProvider(providerModel);
|
||||
|
||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(providerModel.getProviderId()).build()).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public Response createWithFile(@Context UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
||||
Map<String, List<InputPart>> formDataMap = input.getFormDataMap();
|
||||
|
||||
String id = formDataMap.get("id").get(0).getBodyAsString();
|
||||
String name = formDataMap.get("name").get(0).getBodyAsString();
|
||||
String providerId = formDataMap.get("providerId").get(0).getBodyAsString();
|
||||
String enabled = formDataMap.get("enabled").get(0).getBodyAsString();
|
||||
String updateProfileFirstLogin = formDataMap.get("updateProfileFirstLogin").get(0).getBodyAsString();
|
||||
String storeToken = formDataMap.get("storeToken").get(0).getBodyAsString();
|
||||
InputPart file = formDataMap.get("file").get(0);
|
||||
InputStream inputStream = file.getBody(InputStream.class, null);
|
||||
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
|
||||
Map config = providerFactory.parseConfig(inputStream);
|
||||
IdentityProviderModel providerModel = new IdentityProviderModel();
|
||||
|
||||
providerModel.setId(id);
|
||||
providerModel.setName(name);
|
||||
providerModel.setProviderId(providerId);
|
||||
providerModel.setEnabled(Boolean.valueOf(enabled));
|
||||
providerModel.setUpdateProfileFirstLogin(Boolean.valueOf(updateProfileFirstLogin));
|
||||
providerModel.setStoreToken(Boolean.valueOf(storeToken));
|
||||
providerModel.setConfig(config);
|
||||
|
||||
return create(uriInfo, providerModel);
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Response getIdentityProvider(@PathParam("id") String providerId) {
|
||||
for (IdentityProviderModel identityProviderModel : this.realm.getIdentityProviders()) {
|
||||
if (identityProviderModel.getId().equals(providerId)) {
|
||||
return Response.ok(identityProviderModel).build();
|
||||
}
|
||||
}
|
||||
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
@DELETE
|
||||
@NoCache
|
||||
public Response delete(@PathParam("id") String providerId) {
|
||||
for (ClientModel applicationModel : getClientModels()) {
|
||||
List<String> allowedIdentityProviders = applicationModel.getAllowedIdentityProviders();
|
||||
|
||||
for (String appProvider : new ArrayList<String>(allowedIdentityProviders)) {
|
||||
if (appProvider.equals(providerId)) {
|
||||
allowedIdentityProviders.remove(appProvider);
|
||||
}
|
||||
}
|
||||
|
||||
applicationModel.updateAllowedIdentityProviders(allowedIdentityProviders);
|
||||
}
|
||||
|
||||
this.realm.removeIdentityProviderById(providerId);
|
||||
|
||||
public Response delete() {
|
||||
this.realm.removeIdentityProviderById(this.identityProviderModel.getId());
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
private List<ClientModel> getClientModels() {
|
||||
List<ClientModel> clients = new ArrayList<ClientModel>();
|
||||
|
||||
clients.addAll(this.realm.getOAuthClients());
|
||||
clients.addAll(this.realm.getApplications());
|
||||
|
||||
return clients;
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Consumes("application/json")
|
||||
public Response update(IdentityProviderModel model) {
|
||||
this.realm.updateIdentityProvider(model);
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
private IdentityProviderFactory getProviderFactorytById(String providerId) {
|
||||
List<ProviderFactory> allProviders = new ArrayList<ProviderFactory>();
|
||||
|
||||
allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(IdentityProvider.class));
|
||||
allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(SocialIdentityProvider.class));
|
||||
|
||||
for (ProviderFactory providerFactory : allProviders) {
|
||||
if (providerFactory.getId().equals(providerId)) {
|
||||
return (IdentityProviderFactory) providerFactory;
|
||||
}
|
||||
public Response update(IdentityProviderRepresentation model) {
|
||||
try {
|
||||
this.realm.updateIdentityProvider(RepresentationToModel.toModel(model));
|
||||
return Response.noContent().build();
|
||||
} catch (ModelDuplicateException e) {
|
||||
return Flows.errors().exists("Identity Provider " + model.getId() + " already exists");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
|
||||
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.broker.provider.IdentityProvider;
|
||||
import org.keycloak.broker.provider.IdentityProviderFactory;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
import org.keycloak.social.SocialIdentityProvider;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* @author Pedro Igor
|
||||
*/
|
||||
public class IdentityProvidersResource {
|
||||
|
||||
private final RealmModel realm;
|
||||
private final KeycloakSession session;
|
||||
private RealmAuth auth;
|
||||
|
||||
public IdentityProvidersResource(RealmModel realm, KeycloakSession session, RealmAuth auth) {
|
||||
this.realm = realm;
|
||||
this.session = session;
|
||||
this.auth = auth;
|
||||
this.auth.init(RealmAuth.Resource.IDENTITY_PROVIDER);
|
||||
}
|
||||
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public List<IdentityProviderRepresentation> getIdentityProviders() {
|
||||
this.auth.requireView();
|
||||
|
||||
List<IdentityProviderRepresentation> representations = new ArrayList<IdentityProviderRepresentation>();
|
||||
|
||||
for (IdentityProviderModel identityProviderModel : realm.getIdentityProviders()) {
|
||||
representations.add(ModelToRepresentation.toRepresentation(identityProviderModel));
|
||||
}
|
||||
|
||||
return representations;
|
||||
}
|
||||
|
||||
@Path("/providers/{provider_id}")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Response getIdentityProviders(@PathParam("provider_id") String providerId) {
|
||||
this.auth.requireView();
|
||||
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
|
||||
|
||||
if (providerFactory != null) {
|
||||
return Response.ok(providerFactory).build();
|
||||
}
|
||||
|
||||
return Response.status(BAD_REQUEST).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response create(@Context UriInfo uriInfo, IdentityProviderRepresentation representation) {
|
||||
this.auth.requireManage();
|
||||
|
||||
try {
|
||||
this.realm.addIdentityProvider(RepresentationToModel.toModel(representation));
|
||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(representation.getProviderId()).build()).build();
|
||||
} catch (ModelDuplicateException e) {
|
||||
return Flows.errors().exists("Identity Provider " + representation.getId() + " already exists");
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public Response createWithFile(@Context UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
||||
this.auth.requireManage();
|
||||
Map<String, List<InputPart>> formDataMap = input.getFormDataMap();
|
||||
|
||||
String id = formDataMap.get("id").get(0).getBodyAsString();
|
||||
String name = formDataMap.get("name").get(0).getBodyAsString();
|
||||
String providerId = formDataMap.get("providerId").get(0).getBodyAsString();
|
||||
String enabled = formDataMap.get("enabled").get(0).getBodyAsString();
|
||||
String updateProfileFirstLogin = formDataMap.get("updateProfileFirstLogin").get(0).getBodyAsString();
|
||||
String storeToken = formDataMap.get("storeToken").get(0).getBodyAsString();
|
||||
InputPart file = formDataMap.get("file").get(0);
|
||||
InputStream inputStream = file.getBody(InputStream.class, null);
|
||||
IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
|
||||
Map config = providerFactory.parseConfig(inputStream);
|
||||
IdentityProviderRepresentation representation = new IdentityProviderRepresentation();
|
||||
|
||||
representation.setId(id);
|
||||
representation.setName(name);
|
||||
representation.setProviderId(providerId);
|
||||
representation.setEnabled(Boolean.valueOf(enabled));
|
||||
representation.setUpdateProfileFirstLogin(Boolean.valueOf(updateProfileFirstLogin));
|
||||
representation.setStoreToken(Boolean.valueOf(storeToken));
|
||||
representation.setConfig(config);
|
||||
|
||||
return create(uriInfo, representation);
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
public IdentityProviderResource getIdentityProvider(@PathParam("id") String providerId) {
|
||||
this.auth.requireView();
|
||||
IdentityProviderModel identityProviderModel = null;
|
||||
|
||||
for (IdentityProviderModel storedIdentityProvider : this.realm.getIdentityProviders()) {
|
||||
if (storedIdentityProvider.getId().equals(providerId)
|
||||
|| storedIdentityProvider.getInternalId().equals(providerId)) {
|
||||
identityProviderModel = storedIdentityProvider;
|
||||
}
|
||||
}
|
||||
|
||||
if (identityProviderModel == null) {
|
||||
throw new NotFoundException("Could not find identity provider: " + providerId);
|
||||
}
|
||||
|
||||
IdentityProviderResource identityProviderResource = new IdentityProviderResource(realm, session, identityProviderModel);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(identityProviderResource);
|
||||
|
||||
return identityProviderResource;
|
||||
}
|
||||
|
||||
private IdentityProviderFactory getProviderFactorytById(String providerId) {
|
||||
List<ProviderFactory> allProviders = getProviderFactories();
|
||||
|
||||
for (ProviderFactory providerFactory : allProviders) {
|
||||
if (providerFactory.getId().equals(providerId)) {
|
||||
return (IdentityProviderFactory) providerFactory;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<ProviderFactory> getProviderFactories() {
|
||||
List<ProviderFactory> allProviders = new ArrayList<ProviderFactory>();
|
||||
|
||||
allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(IdentityProvider.class));
|
||||
allProviders.addAll(this.session.getKeycloakSessionFactory().getProviderFactories(SocialIdentityProvider.class));
|
||||
|
||||
return allProviders;
|
||||
}
|
||||
}
|
|
@ -447,7 +447,7 @@ public class RealmAdminResource {
|
|||
}
|
||||
|
||||
@Path("identity-provider")
|
||||
public IdentityProviderResource getIdentityProviderResource() {
|
||||
return new IdentityProviderResource(realm, session);
|
||||
public IdentityProvidersResource getIdentityProviderResource() {
|
||||
return new IdentityProvidersResource(realm, session, this.auth);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class RealmAuth {
|
|||
private Resource resource;
|
||||
|
||||
public enum Resource {
|
||||
APPLICATION, CLIENT, USER, REALM, EVENTS
|
||||
APPLICATION, CLIENT, USER, REALM, EVENTS, IDENTITY_PROVIDER
|
||||
}
|
||||
|
||||
private AdminAuth auth;
|
||||
|
@ -67,6 +67,8 @@ public class RealmAuth {
|
|||
return AdminRoles.VIEW_REALM;
|
||||
case EVENTS:
|
||||
return AdminRoles.VIEW_EVENTS;
|
||||
case IDENTITY_PROVIDER:
|
||||
return AdminRoles.VIEW_IDENTITY_PROVIDERS;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
@ -84,6 +86,8 @@ public class RealmAuth {
|
|||
return AdminRoles.MANAGE_REALM;
|
||||
case EVENTS:
|
||||
return AdminRoles.MANAGE_EVENTS;
|
||||
case IDENTITY_PROVIDER:
|
||||
return AdminRoles.MANAGE_IDENTITY_PROVIDERS;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.keycloak.models.Constants;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
|
@ -100,6 +101,8 @@ public abstract class AbstractClientTest {
|
|||
return ((ApplicationRepresentation) o1).getName();
|
||||
} else if (o1 instanceof OAuthClientRepresentation) {
|
||||
return ((OAuthClientRepresentation) o1).getName();
|
||||
} else if (o1 instanceof IdentityProviderRepresentation) {
|
||||
return ((IdentityProviderRepresentation) o1).getId();
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
package org.keycloak.testsuite.admin;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.IdentityProviderResource;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.testsuite.rule.WebRule;
|
||||
|
||||
import javax.ws.rs.NotFoundException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class IdentityProviderTest extends AbstractClientTest {
|
||||
|
||||
@Rule
|
||||
public WebRule webRule = new WebRule(this);
|
||||
|
||||
@Test
|
||||
public void testFindAll() {
|
||||
realm.identityProviders().create(create("google", "google", "Google"));
|
||||
realm.identityProviders().create(create("facebook", "facebook", "Facebook"));
|
||||
|
||||
assertNames(realm.identityProviders().findAll(), "google", "facebook");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreate() {
|
||||
IdentityProviderRepresentation newIdentityProvider = create("new-identity-provider", "oidc", "New Identity Provider");
|
||||
|
||||
newIdentityProvider.getConfig().put("clientId", "clientId");
|
||||
newIdentityProvider.getConfig().put("clientSecret", "clientSecret");
|
||||
|
||||
realm.identityProviders().create(newIdentityProvider);
|
||||
IdentityProviderResource identityProviderResource = realm.identityProviders().get("new-identity-provider");
|
||||
|
||||
assertNotNull(identityProviderResource);
|
||||
|
||||
IdentityProviderRepresentation representation = identityProviderResource.toRepresentation();
|
||||
|
||||
assertNotNull(representation);
|
||||
|
||||
assertNotNull(representation.getInternalId());
|
||||
assertEquals("New Identity Provider", representation.getName());
|
||||
assertEquals("new-identity-provider", representation.getId());
|
||||
assertEquals("oidc", representation.getProviderId());
|
||||
assertEquals("clientId", representation.getConfig().get("clientId"));
|
||||
assertEquals("clientSecret", representation.getConfig().get("clientSecret"));
|
||||
assertTrue(representation.isEnabled());
|
||||
assertFalse(representation.isStoreToken());
|
||||
assertTrue(representation.isUpdateProfileFirstLogin());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
IdentityProviderRepresentation newIdentityProvider = create("update-identity-provider", "oidc", "Update Identity Provider");
|
||||
|
||||
newIdentityProvider.getConfig().put("clientId", "clientId");
|
||||
newIdentityProvider.getConfig().put("clientSecret", "clientSecret");
|
||||
|
||||
realm.identityProviders().create(newIdentityProvider);
|
||||
IdentityProviderResource identityProviderResource = realm.identityProviders().get("update-identity-provider");
|
||||
|
||||
assertNotNull(identityProviderResource);
|
||||
|
||||
IdentityProviderRepresentation representation = identityProviderResource.toRepresentation();
|
||||
|
||||
assertNotNull(representation);
|
||||
|
||||
assertEquals("update-identity-provider", representation.getId());
|
||||
|
||||
representation.setId("changed-alias");
|
||||
representation.setEnabled(false);
|
||||
representation.setStoreToken(true);
|
||||
representation.getConfig().put("clientId", "changedClientId");
|
||||
|
||||
identityProviderResource.update(representation);
|
||||
|
||||
identityProviderResource = realm.identityProviders().get(representation.getInternalId());
|
||||
|
||||
assertNotNull(identityProviderResource);
|
||||
|
||||
representation = identityProviderResource.toRepresentation();
|
||||
|
||||
assertFalse(representation.isEnabled());
|
||||
assertTrue(representation.isStoreToken());
|
||||
assertEquals("changedClientId", representation.getConfig().get("clientId"));
|
||||
}
|
||||
|
||||
@Test(expected = NotFoundException.class)
|
||||
public void testRemove() {
|
||||
IdentityProviderRepresentation newIdentityProvider = create("remove-identity-provider", "saml", "Remove Identity Provider");
|
||||
|
||||
realm.identityProviders().create(newIdentityProvider);
|
||||
IdentityProviderResource identityProviderResource = realm.identityProviders().get("update-identity-provider");
|
||||
|
||||
assertNotNull(identityProviderResource);
|
||||
|
||||
IdentityProviderRepresentation representation = identityProviderResource.toRepresentation();
|
||||
|
||||
assertNotNull(representation);
|
||||
|
||||
identityProviderResource.remove();
|
||||
|
||||
realm.identityProviders().get("update-identity-provider");
|
||||
}
|
||||
|
||||
private IdentityProviderRepresentation create(String id, String providerId, String name) {
|
||||
IdentityProviderRepresentation identityProviderRepresentation = new IdentityProviderRepresentation();
|
||||
|
||||
identityProviderRepresentation.setId(id);
|
||||
identityProviderRepresentation.setProviderId(providerId);
|
||||
identityProviderRepresentation.setName(name);
|
||||
identityProviderRepresentation.setEnabled(true);
|
||||
|
||||
return identityProviderRepresentation;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue