Merge pull request #2324 from ssilvert/client-tests
KEYCLOAK-2535: ClientResource endpoint tests
This commit is contained in:
commit
56c3d53a24
17 changed files with 710 additions and 258 deletions
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration of KeyStore.
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class KeyStoreConfig {
|
||||||
|
|
||||||
|
protected Boolean realmCertificate;
|
||||||
|
protected String storePassword;
|
||||||
|
protected String keyPassword;
|
||||||
|
protected String keyAlias;
|
||||||
|
protected String realmAlias;
|
||||||
|
protected String format;
|
||||||
|
|
||||||
|
public Boolean isRealmCertificate() {
|
||||||
|
return realmCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealmCertificate(Boolean realmCertificate) {
|
||||||
|
this.realmCertificate = realmCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStorePassword() {
|
||||||
|
return storePassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStorePassword(String storePassword) {
|
||||||
|
this.storePassword = storePassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyPassword() {
|
||||||
|
return keyPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyPassword(String keyPassword) {
|
||||||
|
this.keyPassword = keyPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyAlias() {
|
||||||
|
return keyAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyAlias(String keyAlias) {
|
||||||
|
this.keyAlias = keyAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRealmAlias() {
|
||||||
|
return realmAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealmAlias(String realmAlias) {
|
||||||
|
this.realmAlias = realmAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormat(String format) {
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,11 @@
|
||||||
<artifactId>resteasy-client</artifactId>
|
<artifactId>resteasy-client</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
|
<artifactId>resteasy-multipart-provider</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>resteasy-jackson2-provider</artifactId>
|
<artifactId>resteasy-jackson2-provider</artifactId>
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.admin.client.resource;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
|
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
|
||||||
|
import org.keycloak.representations.KeyStoreConfig;
|
||||||
|
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public interface ClientAttributeCertificateResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get key info
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@NoCache
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public CertificateRepresentation getKeyInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new certificate with new key pair
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
@Path("generate")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public CertificateRepresentation generate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload certificate and eventually private key
|
||||||
|
*
|
||||||
|
* @param uriInfo
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("upload")
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public CertificateRepresentation uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload only certificate, not private key
|
||||||
|
*
|
||||||
|
* @param uriInfo
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Path("upload-certificate")
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public CertificateRepresentation uploadJksCertificate(@Context final UriInfo uriInfo, MultipartFormDataInput input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a keystore file for the client, containing private key and public certificate
|
||||||
|
*
|
||||||
|
* @param config Keystore configuration as JSON
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
@Path("/download")
|
||||||
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public byte[] getKeystore(final KeyStoreConfig config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new keypair and certificate, and get the private key file
|
||||||
|
*
|
||||||
|
* Generates a keypair and certificate and serves the private key in a specified keystore format.
|
||||||
|
* Only generated public certificate is saved in Keycloak DB - the private key is not.
|
||||||
|
*
|
||||||
|
* @param config Keystore configuration as JSON
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@NoCache
|
||||||
|
@Path("/generate-and-download")
|
||||||
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public byte[] generateAndGetKeystore(final KeyStoreConfig config);
|
||||||
|
}
|
|
@ -34,7 +34,6 @@ import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author rodrigo.sasaki@icarros.com.br
|
* @author rodrigo.sasaki@icarros.com.br
|
||||||
|
@ -55,21 +54,6 @@ public interface ClientResource {
|
||||||
@DELETE
|
@DELETE
|
||||||
public void remove();
|
public void remove();
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("allowed-origins")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public Set<String> getAllowedOrigins();
|
|
||||||
|
|
||||||
@PUT
|
|
||||||
@Path("allowed-origins")
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public void updateAllowedOrigins(Set<String> allowedOrigins);
|
|
||||||
|
|
||||||
@DELETE
|
|
||||||
@Path("allowed-origins")
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public void removeAllowedOrigins(Set<String> originsToRemove);
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("client-secret")
|
@Path("client-secret")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ -80,19 +64,31 @@ public interface ClientResource {
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public CredentialRepresentation getSecret();
|
public CredentialRepresentation getSecret();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new registration access token for the client
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Path("registration-access-token")
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public ClientRepresentation regenerateRegistrationAccessToken();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get representation of certificate resource
|
||||||
|
*
|
||||||
|
* @param attributePrefix
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Path("certificates/{attr}")
|
||||||
|
public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
@Path("installation/providers/{providerId}")
|
@Path("installation/providers/{providerId}")
|
||||||
public String getInstallationProvider(@PathParam("providerId") String providerId);
|
public String getInstallationProvider(@PathParam("providerId") String providerId);
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("logout-all")
|
|
||||||
public void logoutAllUsers();
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("logout-user/{username}")
|
|
||||||
public void logoutUser(@PathParam("username") String username);
|
|
||||||
|
|
||||||
@Path("session-count")
|
@Path("session-count")
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
import org.keycloak.representations.KeyStoreConfig;
|
||||||
import org.keycloak.representations.idm.CertificateRepresentation;
|
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||||
import org.keycloak.services.ErrorResponseException;
|
import org.keycloak.services.ErrorResponseException;
|
||||||
import org.keycloak.common.util.PemUtils;
|
import org.keycloak.common.util.PemUtils;
|
||||||
|
@ -225,64 +226,6 @@ public class ClientAttributeCertificateResource {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class KeyStoreConfig {
|
|
||||||
protected Boolean realmCertificate;
|
|
||||||
protected String storePassword;
|
|
||||||
protected String keyPassword;
|
|
||||||
protected String keyAlias;
|
|
||||||
protected String realmAlias;
|
|
||||||
protected String format;
|
|
||||||
|
|
||||||
public Boolean isRealmCertificate() {
|
|
||||||
return realmCertificate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRealmCertificate(Boolean realmCertificate) {
|
|
||||||
this.realmCertificate = realmCertificate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStorePassword() {
|
|
||||||
return storePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStorePassword(String storePassword) {
|
|
||||||
this.storePassword = storePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKeyPassword() {
|
|
||||||
return keyPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKeyPassword(String keyPassword) {
|
|
||||||
this.keyPassword = keyPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKeyAlias() {
|
|
||||||
return keyAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKeyAlias(String keyAlias) {
|
|
||||||
this.keyAlias = keyAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRealmAlias() {
|
|
||||||
return realmAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRealmAlias(String realmAlias) {
|
|
||||||
this.realmAlias = realmAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFormat() {
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFormat(String format) {
|
|
||||||
this.format = format;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a keystore file for the client, containing private key and public certificate
|
* Get a keystore file for the client, containing private key and public certificate
|
||||||
*
|
*
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.ResourceAdminManager;
|
import org.keycloak.services.managers.ResourceAdminManager;
|
||||||
import org.keycloak.services.resources.KeycloakApplication;
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
import org.keycloak.services.ErrorResponse;
|
import org.keycloak.services.ErrorResponse;
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
@ -62,12 +61,11 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,54 +170,6 @@ public class ClientResource {
|
||||||
return provider.generateInstallation(session, realm, client, keycloak.getBaseUri(uriInfo));
|
return provider.generateInstallation(session, realm, client, keycloak.getBaseUri(uriInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get keycloak.json file
|
|
||||||
*
|
|
||||||
* this method is deprecated, see getInstallationProvider
|
|
||||||
*
|
|
||||||
* Returns a keycloak.json file to be used to configure the adapter of the specified client.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@GET
|
|
||||||
@NoCache
|
|
||||||
@Path("installation/json")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public String getInstallation() throws IOException {
|
|
||||||
auth.requireView();
|
|
||||||
|
|
||||||
ClientManager clientManager = new ClientManager(new RealmManager(session));
|
|
||||||
Object rep = clientManager.toInstallationRepresentation(realm, client, getKeycloakApplication().getBaseUri(uriInfo));
|
|
||||||
|
|
||||||
// TODO Temporary solution to pretty-print
|
|
||||||
return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get adapter configuration XML for JBoss / Wildfly Keycloak subsystem
|
|
||||||
*
|
|
||||||
* this method is deprecated, see getInstallationProvider
|
|
||||||
*
|
|
||||||
* Returns XML that can be included in the JBoss / Wildfly Keycloak subsystem to configure the adapter of that client.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@GET
|
|
||||||
@NoCache
|
|
||||||
@Path("installation/jboss")
|
|
||||||
@Produces(MediaType.TEXT_PLAIN)
|
|
||||||
public String getJBossInstallation() throws IOException {
|
|
||||||
auth.requireView();
|
|
||||||
|
|
||||||
ClientManager clientManager = new ClientManager(new RealmManager(session));
|
|
||||||
return clientManager.toJBossSubsystemConfig(realm, client, getKeycloakApplication().getBaseUri(uriInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the client
|
* Delete the client
|
||||||
*
|
*
|
||||||
|
@ -306,64 +256,6 @@ public class ClientResource {
|
||||||
return new RoleContainerResource(uriInfo, realm, auth, client, adminEvent);
|
return new RoleContainerResource(uriInfo, realm, auth, client, adminEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get allowed origins
|
|
||||||
*
|
|
||||||
* This is used for CORS requests. Access tokens will have
|
|
||||||
* their allowedOrigins claim set to this value for tokens created for this client.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Path("allowed-origins")
|
|
||||||
@GET
|
|
||||||
@NoCache
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public Set<String> getAllowedOrigins()
|
|
||||||
{
|
|
||||||
auth.requireView();
|
|
||||||
return client.getWebOrigins();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update allowed origins
|
|
||||||
*
|
|
||||||
* This is used for CORS requests. Access tokens will have
|
|
||||||
* their allowedOrigins claim set to this value for tokens created for this client.
|
|
||||||
*
|
|
||||||
* @param allowedOrigins
|
|
||||||
*/
|
|
||||||
@Path("allowed-origins")
|
|
||||||
@PUT
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public void updateAllowedOrigins(Set<String> allowedOrigins)
|
|
||||||
{
|
|
||||||
auth.requireManage();
|
|
||||||
|
|
||||||
client.setWebOrigins(allowedOrigins);
|
|
||||||
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(client).success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the specified origins from current allowed origins
|
|
||||||
*
|
|
||||||
* This is used for CORS requests. Access tokens will have
|
|
||||||
* their allowedOrigins claim set to this value for tokens created for this client.
|
|
||||||
*
|
|
||||||
* @param allowedOrigins List of origins to delete
|
|
||||||
*/
|
|
||||||
@Path("allowed-origins")
|
|
||||||
@DELETE
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public void deleteAllowedOrigins(Set<String> allowedOrigins)
|
|
||||||
{
|
|
||||||
auth.requireManage();
|
|
||||||
|
|
||||||
for (String origin : allowedOrigins) {
|
|
||||||
client.removeWebOrigin(origin);
|
|
||||||
}
|
|
||||||
adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo).success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a user dedicated to the service account
|
* Get a user dedicated to the service account
|
||||||
*
|
*
|
||||||
|
@ -507,41 +399,6 @@ public class ClientResource {
|
||||||
return sessions;
|
return sessions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logout all sessions
|
|
||||||
*
|
|
||||||
* If the client has an admin URL, invalidate all sessions associated with that client directly.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Path("logout-all")
|
|
||||||
@POST
|
|
||||||
public GlobalRequestResult logoutAll() {
|
|
||||||
auth.requireManage();
|
|
||||||
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
|
|
||||||
return new ResourceAdminManager(session).logoutClient(uriInfo.getRequestUri(), realm, client);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logout the user by username
|
|
||||||
*
|
|
||||||
* If the client has an admin URL, invalidate the sessions for a particular user directly.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Path("logout-user/{username}")
|
|
||||||
@POST
|
|
||||||
public void logout(final @PathParam("username") String username) {
|
|
||||||
auth.requireManage();
|
|
||||||
UserModel user = session.users().getUserByUsername(username, realm);
|
|
||||||
if (user == null) {
|
|
||||||
throw new NotFoundException("User not found");
|
|
||||||
}
|
|
||||||
adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
|
|
||||||
new ResourceAdminManager(session).logoutUserFromClient(uriInfo.getRequestUri(), realm, client, user);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a cluster node with the client
|
* Register a cluster node with the client
|
||||||
*
|
*
|
||||||
|
|
|
@ -51,8 +51,14 @@ import org.keycloak.provider.Spi;
|
||||||
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
|
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
|
||||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||||
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
|
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
|
||||||
import org.keycloak.representations.info.*;
|
|
||||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||||
|
import org.keycloak.representations.info.ClientInstallationRepresentation;
|
||||||
|
import org.keycloak.representations.info.MemoryInfoRepresentation;
|
||||||
|
import org.keycloak.representations.info.ProviderRepresentation;
|
||||||
|
import org.keycloak.representations.info.ServerInfoRepresentation;
|
||||||
|
import org.keycloak.representations.info.SpiInfoRepresentation;
|
||||||
|
import org.keycloak.representations.info.SystemInfoRepresentation;
|
||||||
|
import org.keycloak.representations.info.ThemeInfoRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
|
|
@ -23,22 +23,29 @@ import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.testsuite.adapter.page.SessionPortal;
|
import org.keycloak.testsuite.adapter.page.SessionPortal;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
|
import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
|
||||||
|
|
||||||
import org.keycloak.testsuite.auth.page.account.Sessions;
|
import org.keycloak.testsuite.auth.page.account.Sessions;
|
||||||
import org.keycloak.testsuite.auth.page.login.Login;
|
import org.keycloak.testsuite.auth.page.login.Login;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.admin.ApiUtil.findClientResourceByClientId;
|
import static org.keycloak.testsuite.admin.ApiUtil.findClientResourceByClientId;
|
||||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
|
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
|
||||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
||||||
|
|
||||||
import org.keycloak.testsuite.util.SecondBrowser;
|
import org.keycloak.testsuite.util.SecondBrowser;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
|
@ -156,9 +163,11 @@ public abstract class AbstractSessionServletAdapterTest extends AbstractServlets
|
||||||
public void testAdminApplicationLogout() {
|
public void testAdminApplicationLogout() {
|
||||||
// login as bburke
|
// login as bburke
|
||||||
loginAndCheckSession(driver, testRealmLoginPage);
|
loginAndCheckSession(driver, testRealmLoginPage);
|
||||||
|
|
||||||
// logout mposolda with admin client
|
// logout mposolda with admin client
|
||||||
findClientResourceByClientId(testRealmResource(), "session-portal")
|
UserRepresentation mposolda = testRealmResource().users().search("mposolda", null, null, null, null, null).get(0);
|
||||||
.logoutUser("mposolda");
|
testRealmResource().users().get(mposolda.getId()).logout();
|
||||||
|
|
||||||
// bburke should be still logged with original httpSession in our browser window
|
// bburke should be still logged with original httpSession in our browser window
|
||||||
sessionPortalPage.navigateTo();
|
sessionPortalPage.navigateTo();
|
||||||
assertEquals(driver.getCurrentUrl(), sessionPortalPage.toString());
|
assertEquals(driver.getCurrentUrl(), sessionPortalPage.toString());
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.admin.client;
|
package org.keycloak.testsuite.admin.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.testsuite.AbstractAuthTest;
|
import org.keycloak.testsuite.AbstractAuthTest;
|
||||||
import org.keycloak.testsuite.admin.ApiUtil;
|
import org.keycloak.testsuite.admin.ApiUtil;
|
||||||
|
|
||||||
|
@ -34,29 +36,35 @@ public abstract class AbstractClientTest extends AbstractAuthTest {
|
||||||
return testRealmResource().toRepresentation();
|
return testRealmResource().toRepresentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createOidcClient(String name) {
|
// returns UserRepresentation retrieved from server, with all fields, including id
|
||||||
|
protected UserRepresentation getFullUserRep(String userName) {
|
||||||
|
List<UserRepresentation> results = testRealmResource().users().search(userName, null, null, null, null, null);
|
||||||
|
if (results.size() != 1) throw new RuntimeException("Did not find single user with username " + userName);
|
||||||
|
return results.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String createOidcClient(String name) {
|
||||||
ClientRepresentation clientRep = new ClientRepresentation();
|
ClientRepresentation clientRep = new ClientRepresentation();
|
||||||
clientRep.setClientId(name);
|
clientRep.setClientId(name);
|
||||||
clientRep.setName(name);
|
clientRep.setName(name);
|
||||||
clientRep.setRootUrl("foo");
|
clientRep.setRootUrl("foo");
|
||||||
clientRep.setProtocol("openid-connect");
|
clientRep.setProtocol("openid-connect");
|
||||||
createClient(clientRep);
|
return createClient(clientRep);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createSamlClient(String name) {
|
protected String createSamlClient(String name) {
|
||||||
ClientRepresentation clientRep = new ClientRepresentation();
|
ClientRepresentation clientRep = new ClientRepresentation();
|
||||||
clientRep.setClientId(name);
|
clientRep.setClientId(name);
|
||||||
clientRep.setName(name);
|
clientRep.setName(name);
|
||||||
clientRep.setProtocol("saml");
|
clientRep.setProtocol("saml");
|
||||||
clientRep.setAdminUrl("samlEndpoint");
|
clientRep.setAdminUrl("samlEndpoint");
|
||||||
createClient(clientRep);
|
return createClient(clientRep);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createClient(ClientRepresentation clientRep) {
|
protected String createClient(ClientRepresentation clientRep) {
|
||||||
Response resp = testRealmResource().clients().create(clientRep);
|
Response resp = testRealmResource().clients().create(clientRep);
|
||||||
// for some reason, findAll() will later fail unless readEntity is called here
|
resp.close();
|
||||||
resp.readEntity(String.class);
|
return ApiUtil.getCreatedId(resp);
|
||||||
//testRealmResource().clients().findAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientRepresentation findClientRepresentation(String name) {
|
protected ClientRepresentation findClientRepresentation(String name) {
|
||||||
|
@ -69,4 +77,8 @@ public abstract class AbstractClientTest extends AbstractAuthTest {
|
||||||
return ApiUtil.findClientResourceByName(testRealmResource(), name);
|
return ApiUtil.findClientResourceByName(testRealmResource(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ClientResource findClientResourceById(String id) {
|
||||||
|
return ApiUtil.findClientResourceByClientId(testRealmResource(), id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,266 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.testsuite.admin.client;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.ws.rs.NotFoundException;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
|
import org.keycloak.admin.client.resource.ProtocolMappersResource;
|
||||||
|
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||||
|
import org.keycloak.testsuite.admin.ApiUtil;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class ClientProtocolMapperTest extends AbstractClientTest {
|
||||||
|
|
||||||
|
private ClientResource oidcClientRsc;
|
||||||
|
private ProtocolMappersResource oidcMappersRsc;
|
||||||
|
private ClientResource samlClientRsc;
|
||||||
|
private ProtocolMappersResource samlMappersRsc;
|
||||||
|
|
||||||
|
private Map<String, List<ProtocolMapperRepresentation>> builtinMappers = null;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
createOidcClient("oidcMapperClient");
|
||||||
|
oidcClientRsc = findClientResource("oidcMapperClient");
|
||||||
|
oidcMappersRsc = oidcClientRsc.getProtocolMappers();
|
||||||
|
|
||||||
|
createSamlClient("samlMapperClient");
|
||||||
|
samlClientRsc = findClientResource("samlMapperClient");
|
||||||
|
samlMappersRsc = samlClientRsc.getProtocolMappers();
|
||||||
|
|
||||||
|
builtinMappers = adminClient.serverInfo().getInfo().getBuiltinProtocolMappers();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
oidcClientRsc.remove();
|
||||||
|
samlClientRsc.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProtocolMapperRepresentation makeMapper(String protocol, String name, String mapperType, Map<String, String> config) {
|
||||||
|
ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
|
||||||
|
rep.setProtocol(protocol);
|
||||||
|
rep.setName(name);
|
||||||
|
rep.setProtocolMapper(mapperType);
|
||||||
|
rep.setConfig(config);
|
||||||
|
rep.setConsentRequired(true);
|
||||||
|
rep.setConsentText("Test Consent Text");
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProtocolMapperRepresentation makeSamlMapper(String name) {
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
config.put("role", "account.view-profile");
|
||||||
|
config.put("new.role.name", "new-role-name");
|
||||||
|
return makeMapper("saml", name, "saml-role-name-mapper", config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProtocolMapperRepresentation makeOidcMapper(String name) {
|
||||||
|
Map<String, String> config = new HashMap<>();
|
||||||
|
config.put("role", "myrole");
|
||||||
|
return makeMapper("openid-connect", name, "oidc-hardcoded-role-mapper", config);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertEqualMappers(ProtocolMapperRepresentation original, ProtocolMapperRepresentation created) {
|
||||||
|
assertNotNull(created);
|
||||||
|
assertEquals(original.getName(), created.getName());
|
||||||
|
assertEquals(original.getConfig(), created.getConfig());
|
||||||
|
assertEquals(original.getConsentText(), created.getConsentText());
|
||||||
|
assertEquals(original.isConsentRequired(), created.isConsentRequired());
|
||||||
|
assertEquals(original.getProtocol(), created.getProtocol());
|
||||||
|
assertEquals(original.getProtocolMapper(), created.getProtocolMapper());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMappersList() {
|
||||||
|
assertFalse(oidcMappersRsc.getMappers().isEmpty());
|
||||||
|
assertFalse(samlMappersRsc.getMappers().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsMapper(List<ProtocolMapperRepresentation> mappers, ProtocolMapperRepresentation mapper) {
|
||||||
|
for (ProtocolMapperRepresentation listedMapper : mappers) {
|
||||||
|
if (listedMapper.getName().equals(mapper.getName())) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ProtocolMapperRepresentation> mappersToAdd(List<ProtocolMapperRepresentation> oldMappers,
|
||||||
|
List<ProtocolMapperRepresentation> builtins) {
|
||||||
|
List<ProtocolMapperRepresentation> mappersToAdd = new ArrayList<>();
|
||||||
|
for (ProtocolMapperRepresentation builtin : builtins) {
|
||||||
|
if (!containsMapper(oldMappers, builtin)) mappersToAdd.add(builtin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mappersToAdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testAddAllBuiltinMappers(ProtocolMappersResource resource, String resourceName) {
|
||||||
|
List<ProtocolMapperRepresentation> oldMappers = resource.getMappersPerProtocol(resourceName);
|
||||||
|
List<ProtocolMapperRepresentation> builtins = builtinMappers.get(resourceName);
|
||||||
|
|
||||||
|
List<ProtocolMapperRepresentation> mappersToAdd = mappersToAdd(oldMappers, builtins);
|
||||||
|
|
||||||
|
// This is used by admin console to add builtin mappers
|
||||||
|
resource.createMapper(mappersToAdd);
|
||||||
|
|
||||||
|
List<ProtocolMapperRepresentation> newMappers = resource.getMappersPerProtocol(resourceName);
|
||||||
|
assertEquals(oldMappers.size() + mappersToAdd.size(), newMappers.size());
|
||||||
|
|
||||||
|
for (ProtocolMapperRepresentation rep : mappersToAdd) {
|
||||||
|
assertTrue(containsMapper(newMappers, rep));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateOidcMappersFromList() {
|
||||||
|
testAddAllBuiltinMappers(oidcMappersRsc, "openid-connect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateSamlMappersFromList() {
|
||||||
|
testAddAllBuiltinMappers(samlMappersRsc, "saml");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateSamlProtocolMapper() {
|
||||||
|
|
||||||
|
//{"protocol":"saml",
|
||||||
|
// "config":{"role":"account.view-profile","new.role.name":"new-role-name"},
|
||||||
|
// "consentRequired":true,
|
||||||
|
// "consentText":"My consent text",
|
||||||
|
// "name":"saml-role-name-maper",
|
||||||
|
// "protocolMapper":"saml-role-name-mapper"}
|
||||||
|
ProtocolMapperRepresentation rep = makeSamlMapper("saml-role-name-mapper");
|
||||||
|
|
||||||
|
int totalMappers = samlMappersRsc.getMappers().size();
|
||||||
|
int totalSamlMappers = samlMappersRsc.getMappersPerProtocol("saml").size();
|
||||||
|
Response resp = samlMappersRsc.createMapper(rep);
|
||||||
|
resp.close();
|
||||||
|
assertEquals(totalMappers + 1, samlMappersRsc.getMappers().size());
|
||||||
|
assertEquals(totalSamlMappers + 1, samlMappersRsc.getMappersPerProtocol("saml").size());
|
||||||
|
|
||||||
|
String createdId = ApiUtil.getCreatedId(resp);
|
||||||
|
ProtocolMapperRepresentation created = samlMappersRsc.getMapperById(createdId);
|
||||||
|
assertEqualMappers(rep, created);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateOidcProtocolMapper() {
|
||||||
|
//{"protocol":"openid-connect",
|
||||||
|
// "config":{"role":"myrole"},
|
||||||
|
// "consentRequired":true,
|
||||||
|
// "consentText":"My consent text",
|
||||||
|
// "name":"oidc-hardcoded-role-mapper",
|
||||||
|
// "protocolMapper":"oidc-hardcoded-role-mapper"}
|
||||||
|
ProtocolMapperRepresentation rep = makeOidcMapper("oidc-hardcoded-role-mapper");
|
||||||
|
|
||||||
|
int totalMappers = oidcMappersRsc.getMappers().size();
|
||||||
|
int totalOidcMappers = oidcMappersRsc.getMappersPerProtocol("openid-connect").size();
|
||||||
|
Response resp = oidcMappersRsc.createMapper(rep);
|
||||||
|
resp.close();
|
||||||
|
assertEquals(totalMappers + 1, oidcMappersRsc.getMappers().size());
|
||||||
|
assertEquals(totalOidcMappers + 1, oidcMappersRsc.getMappersPerProtocol("openid-connect").size());
|
||||||
|
|
||||||
|
String createdId = ApiUtil.getCreatedId(resp);
|
||||||
|
ProtocolMapperRepresentation created = oidcMappersRsc.getMapperById(createdId);//findByName(samlMappersRsc, "saml-role-name-mapper");
|
||||||
|
assertEqualMappers(rep, created);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateSamlMapper() {
|
||||||
|
ProtocolMapperRepresentation rep = makeSamlMapper("saml-role-name-mapper2");
|
||||||
|
|
||||||
|
Response resp = samlMappersRsc.createMapper(rep);
|
||||||
|
resp.close();
|
||||||
|
|
||||||
|
String createdId = ApiUtil.getCreatedId(resp);
|
||||||
|
|
||||||
|
rep.getConfig().put("role", "account.manage-account");
|
||||||
|
rep.setId(createdId);
|
||||||
|
rep.setConsentRequired(false);
|
||||||
|
samlMappersRsc.update(createdId, rep);
|
||||||
|
|
||||||
|
ProtocolMapperRepresentation updated = samlMappersRsc.getMapperById(createdId);
|
||||||
|
assertEqualMappers(rep, updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateOidcMapper() {
|
||||||
|
ProtocolMapperRepresentation rep = makeOidcMapper("oidc-hardcoded-role-mapper2");
|
||||||
|
|
||||||
|
Response resp = oidcMappersRsc.createMapper(rep);
|
||||||
|
resp.close();
|
||||||
|
|
||||||
|
String createdId = ApiUtil.getCreatedId(resp);
|
||||||
|
|
||||||
|
rep.getConfig().put("role", "myotherrole");
|
||||||
|
rep.setId(createdId);
|
||||||
|
rep.setConsentRequired(false);
|
||||||
|
oidcMappersRsc.update(createdId, rep);
|
||||||
|
|
||||||
|
ProtocolMapperRepresentation updated = oidcMappersRsc.getMapperById(createdId);
|
||||||
|
assertEqualMappers(rep, updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test (expected = NotFoundException.class)
|
||||||
|
public void testDeleteSamlMapper() {
|
||||||
|
ProtocolMapperRepresentation rep = makeSamlMapper("saml-role-name-mapper3");
|
||||||
|
|
||||||
|
Response resp = samlMappersRsc.createMapper(rep);
|
||||||
|
resp.close();
|
||||||
|
|
||||||
|
String createdId = ApiUtil.getCreatedId(resp);
|
||||||
|
|
||||||
|
samlMappersRsc.delete(createdId);
|
||||||
|
|
||||||
|
samlMappersRsc.getMapperById(createdId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test (expected = NotFoundException.class)
|
||||||
|
public void testDeleteOidcMapper() {
|
||||||
|
ProtocolMapperRepresentation rep = makeOidcMapper("oidc-hardcoded-role-mapper3");
|
||||||
|
|
||||||
|
Response resp = oidcMappersRsc.createMapper(rep);
|
||||||
|
resp.close();
|
||||||
|
|
||||||
|
String createdId = ApiUtil.getCreatedId(resp);
|
||||||
|
|
||||||
|
oidcMappersRsc.delete(createdId);
|
||||||
|
|
||||||
|
oidcMappersRsc.getMapperById(createdId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.admin.client;
|
package org.keycloak.testsuite.admin.client;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
|
@ -42,16 +43,17 @@ public class ClientRolesTest extends AbstractClientTest {
|
||||||
rolesRsc = clientRsc.roles();
|
rolesRsc = clientRsc.roles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
clientRsc.remove();
|
||||||
|
}
|
||||||
|
|
||||||
private RoleRepresentation makeRole(String name) {
|
private RoleRepresentation makeRole(String name) {
|
||||||
RoleRepresentation role = new RoleRepresentation();
|
RoleRepresentation role = new RoleRepresentation();
|
||||||
role.setName(name);
|
role.setName(name);
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* private boolean hasRole(RolesResource rolesRsc, String name) {
|
|
||||||
return rolesRsc.get(name) != null;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
private boolean hasRole(RolesResource rolesRsc, String name) {
|
private boolean hasRole(RolesResource rolesRsc, String name) {
|
||||||
for (RoleRepresentation role : rolesRsc.list()) {
|
for (RoleRepresentation role : rolesRsc.list()) {
|
||||||
if (role.getName().equals(name)) return true;
|
if (role.getName().equals(name)) return true;
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.testsuite.admin.client;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.admin.client.resource.ClientAttributeCertificateResource;
|
||||||
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
|
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class CredentialsTest extends AbstractClientTest {
|
||||||
|
|
||||||
|
private ClientResource accountClient;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
accountClient = findClientResourceById("account");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAndRegenerateSecret() {
|
||||||
|
CredentialRepresentation oldCredential = accountClient.getSecret();
|
||||||
|
CredentialRepresentation newCredential = accountClient.generateNewSecret();
|
||||||
|
assertNotNull(oldCredential);
|
||||||
|
assertNotNull(newCredential);
|
||||||
|
assertNotEquals(newCredential.getValue(), oldCredential.getValue());
|
||||||
|
assertEquals(newCredential.getValue(), accountClient.getSecret().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAndRegenerateRegistrationAccessToken() {
|
||||||
|
ClientRepresentation rep = accountClient.toRepresentation();
|
||||||
|
String oldToken = rep.getRegistrationAccessToken();
|
||||||
|
String newToken = accountClient.regenerateRegistrationAccessToken().getRegistrationAccessToken();
|
||||||
|
assertNull(oldToken); // registration access token not saved in ClientRep
|
||||||
|
assertNotNull(newToken); // it's only available via regenerateRegistrationAccessToken()
|
||||||
|
assertNull(accountClient.toRepresentation().getRegistrationAccessToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetCertificateResource() {
|
||||||
|
ClientAttributeCertificateResource certRsc = accountClient.getCertficateResource("jwt.credential");
|
||||||
|
CertificateRepresentation cert = certRsc.generate();
|
||||||
|
CertificateRepresentation certFromGet = certRsc.getKeyInfo();
|
||||||
|
assertEquals(cert.getCertificate(), certFromGet.getCertificate());
|
||||||
|
assertEquals(cert.getPrivateKey(), certFromGet.getPrivateKey());
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.admin.client;
|
package org.keycloak.testsuite.admin.client;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.admin.client.resource.ClientResource;
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
|
@ -47,6 +48,12 @@ public class InstallationTest extends AbstractClientTest {
|
||||||
samlClient = findClientResource(SAML_NAME);
|
samlClient = findClientResource(SAML_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
oidcClient.remove();
|
||||||
|
samlClient.remove();
|
||||||
|
}
|
||||||
|
|
||||||
private String authServerUrl() {
|
private String authServerUrl() {
|
||||||
return AuthServerTestEnricher.getAuthServerContextRoot() + "/auth";
|
return AuthServerTestEnricher.getAuthServerContextRoot() + "/auth";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
|
||||||
|
* as indicated by the @author tags. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.testsuite.admin.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.admin.client.resource.ClientResource;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||||
|
import org.keycloak.testsuite.auth.page.account.AccountManagement;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
|
||||||
|
*/
|
||||||
|
public class SessionTest extends AbstractClientTest {
|
||||||
|
private static boolean testUserCreated = false;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
protected AccountManagement testRealmAccountManagementPage;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
// make user test user exists in test realm
|
||||||
|
if (!testUserCreated) createTestUserWithAdminClient();
|
||||||
|
testUserCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAppSessionCount() {
|
||||||
|
ClientResource accountClient = findClientResourceById("account");
|
||||||
|
int sessionCount = accountClient.getApplicationSessionCount().get("count");
|
||||||
|
assertEquals(0, sessionCount);
|
||||||
|
|
||||||
|
testRealmAccountManagementPage.navigateTo();
|
||||||
|
loginPage.form().login(testUser);
|
||||||
|
|
||||||
|
sessionCount = accountClient.getApplicationSessionCount().get("count");
|
||||||
|
assertEquals(1, sessionCount);
|
||||||
|
|
||||||
|
testRealmAccountManagementPage.signOut();
|
||||||
|
|
||||||
|
sessionCount = accountClient.getApplicationSessionCount().get("count");
|
||||||
|
assertEquals(0, sessionCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetUserSessions() {
|
||||||
|
//List<java.util.Map<String, String>> stats = this.testRealmResource().getClientSessionStats();
|
||||||
|
ClientResource account = findClientResourceById("account");
|
||||||
|
|
||||||
|
testRealmAccountManagementPage.navigateTo();
|
||||||
|
loginPage.form().login(testUser);
|
||||||
|
|
||||||
|
List<UserSessionRepresentation> sessions = account.getUserSessions(0, 5);
|
||||||
|
assertEquals(1, sessions.size());
|
||||||
|
|
||||||
|
UserSessionRepresentation rep = sessions.get(0);
|
||||||
|
|
||||||
|
UserRepresentation testUserRep = getFullUserRep(testUser.getUsername());
|
||||||
|
assertEquals(testUserRep.getId(), rep.getUserId());
|
||||||
|
assertEquals(testUserRep.getUsername(), rep.getUsername());
|
||||||
|
|
||||||
|
String clientId = account.toRepresentation().getId();
|
||||||
|
assertEquals("account", rep.getClients().get(clientId));
|
||||||
|
assertNotNull(rep.getIpAddress());
|
||||||
|
assertNotNull(rep.getLastAccess());
|
||||||
|
assertNotNull(rep.getStart());
|
||||||
|
|
||||||
|
testRealmAccountManagementPage.signOut();
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,6 +59,7 @@ import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests Undertow Adapter
|
* Tests Undertow Adapter
|
||||||
|
@ -598,7 +599,8 @@ public class AdapterTestStrategy extends ExternalResource {
|
||||||
|
|
||||||
// logout mposolda with admin client
|
// logout mposolda with admin client
|
||||||
Keycloak keycloakAdmin = Keycloak.getInstance(AUTH_SERVER_URL, "master", "admin", "admin", Constants.ADMIN_CLI_CLIENT_ID);
|
Keycloak keycloakAdmin = Keycloak.getInstance(AUTH_SERVER_URL, "master", "admin", "admin", Constants.ADMIN_CLI_CLIENT_ID);
|
||||||
ApiUtil.findClientByClientId(keycloakAdmin.realm("demo"), "session-portal").logoutUser("mposolda");
|
UserRepresentation mposolda = keycloakAdmin.realm("demo").users().search("mposolda", null, null, null, null, null).get(0);
|
||||||
|
keycloakAdmin.realm("demo").users().get(mposolda.getId()).logout();
|
||||||
|
|
||||||
// bburke should be still logged with original httpSession in our browser window
|
// bburke should be still logged with original httpSession in our browser window
|
||||||
driver.navigate().to(APP_SERVER_BASE_URL + "/session-portal");
|
driver.navigate().to(APP_SERVER_BASE_URL + "/session-portal");
|
||||||
|
|
|
@ -952,19 +952,6 @@ module.factory('ClientOfflineSessions', function($resource) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('ClientLogoutAll', function($resource) {
|
|
||||||
return $resource(authUrl + '/admin/realms/:realm/clients/:client/logout-all', {
|
|
||||||
realm : '@realm',
|
|
||||||
client : "@client"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
module.factory('ClientLogoutUser', function($resource) {
|
|
||||||
return $resource(authUrl + '/admin/realms/:realm/clients/:client/logout-user/:user', {
|
|
||||||
realm : '@realm',
|
|
||||||
client : "@client",
|
|
||||||
user : "@user"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
module.factory('RealmLogoutAll', function($resource) {
|
module.factory('RealmLogoutAll', function($resource) {
|
||||||
return $resource(authUrl + '/admin/realms/:realm/logout-all', {
|
return $resource(authUrl + '/admin/realms/:realm/logout-all', {
|
||||||
realm : '@realm'
|
realm : '@realm'
|
||||||
|
|
Loading…
Reference in a new issue