keycloak-aplcache

Merge pull request #955 from pedroigor/master [KEYCLOAK-883]

2/9/2015 9:30:42 PM

Changes

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
index cc4b3e6..b9f09c3 100644
--- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
@@ -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;
     }
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
index 13db021..7a31d03 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js
@@ -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'
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
index ec05bb0..98a6e6b 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
@@ -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.");
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/IdentityProviderResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/IdentityProviderResource.java
new file mode 100755
index 0000000..48a9d5b
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/IdentityProviderResource.java
@@ -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();
+}
\ No newline at end of file
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/IdentityProvidersResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/IdentityProvidersResource.java
new file mode 100755
index 0000000..16ae0e9
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/IdentityProvidersResource.java
@@ -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);
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
index fa7309a..1ed0a80 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/RealmResource.java
@@ -35,6 +35,9 @@ public interface RealmResource {
     @Path("roles")
     public RolesResource roles();
 
+    @Path("identity-provider")
+    IdentityProvidersResource identityProviders();
+
     @DELETE
     public void remove();
 
diff --git a/model/api/src/main/java/org/keycloak/models/AdminRoles.java b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
index a988951..8d46505 100755
--- a/model/api/src/main/java/org/keycloak/models/AdminRoles.java
+++ b/model/api/src/main/java/org/keycloak/models/AdminRoles.java
@@ -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};
 
 }
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 8fe9688..f89acaa 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -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;
+    }
 }
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 0c7835c..8463168 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -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;
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
index 1917844..1e61b3e 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
@@ -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();
-    }
-
-    @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();
+    public IdentityProviderRepresentation getIdentityProvider() {
+        return ModelToRepresentation.toRepresentation(this.identityProviderModel);
     }
 
-    @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;
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
new file mode 100755
index 0000000..42c3497
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
@@ -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;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 51a39f7..3e5c2b0 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -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);
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
index 641315b..20238f1 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAuth.java
@@ -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();
         }
diff --git a/services/src/main/java/org/keycloak/services/resources/AuthenticationBrokerResource.java b/services/src/main/java/org/keycloak/services/resources/AuthenticationBrokerResource.java
index 91b0fb0..5320eee 100644
--- a/services/src/main/java/org/keycloak/services/resources/AuthenticationBrokerResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/AuthenticationBrokerResource.java
@@ -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);
 
+        IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(realm, providerId);
+
         try {
-            IdentityProvider provider = getIdentityProvider(realm, providerId);
+            IdentityProvider identityProvider = getIdentityProvider(realm, providerId);
 
-            if (provider == null) {
-                return Flows.forms(session, realm, null, uriInfo).setError("Social provider not found").createErrorPage();
+            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()) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java
index e0d29e9..5d04fa4 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AbstractClientTest.java
@@ -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();
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
new file mode 100644
index 0000000..2d91d9f
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
@@ -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;
+    }
+}