Skip to content
Snippets Groups Projects
Verified Commit 4550c77d authored by Ira ¯\_(ツ)_/¯'s avatar Ira ¯\_(ツ)_/¯
Browse files

Fix formatting and linting (google style checks)

parent 7b32f32f
No related branches found
No related tags found
No related merge requests found
Pipeline #4182 passed
Showing with 203 additions and 145 deletions
package org.archlinux.keycloak.mailpass.rest;
import static io.restassured.RestAssured.given;
import static org.junit.Assert.assertEquals;
import com.palantir.docker.compose.DockerComposeRule;
import com.palantir.docker.compose.connection.waiting.HealthChecks;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import static io.restassured.RestAssured.given;
import static org.junit.Assert.assertEquals;
import java.text.MessageFormat;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
public class MailPassResourceIntegrationTest {
private final static String ROOT_URI = "http://localhost:{0,number,#}/auth/realms/master/mailpass/roleauth";
private final static String TOKEN_GEN_URI = "http://localhost:{0,number,#}/auth/realms/master/protocol/openid-connect/token";
private static final String ROOT_URI =
"http://localhost:{0,number,#}/auth/realms/master/mailpass/roleauth";
private static final String TOKEN_GEN_URI =
"http://localhost:{0,number,#}/auth/realms/master/protocol/openid-connect/token";
private static String adminToken;
private static int port;
@ClassRule
public static DockerComposeRule docker = DockerComposeRule.builder()
.file("src/integrationTest/resources/docker-compose.yml").waitingForService("keycloak", HealthChecks
.toRespondOverHttp(8080, (port) -> port.inFormat("http://$HOST:$EXTERNAL_PORT/auth/realms/master")))
.build();
public static DockerComposeRule docker =
DockerComposeRule.builder()
.file("src/integrationTest/resources/docker-compose.yml")
.waitingForService(
"keycloak",
HealthChecks.toRespondOverHttp(
8080, (port) -> port.inFormat("http://$HOST:$EXTERNAL_PORT/auth/realms/master")))
.build();
/** Generate bearer token and make it available to all the tests in the class. */
@BeforeClass
public static void setup() {
port = docker.containers().container("keycloak").port(8080).getExternalPort();
Response response = given().accept(ContentType.JSON).contentType(ContentType.URLENC)
.body("grant_type=password&username=admin&password=admin&client_id=admin-cli")
.post(MessageFormat.format(TOKEN_GEN_URI, port));
Response response =
given()
.accept(ContentType.JSON)
.contentType(ContentType.URLENC)
.body("grant_type=password&username=admin&password=admin&client_id=admin-cli")
.post(MessageFormat.format(TOKEN_GEN_URI, port));
adminToken = response.jsonPath().getString("access_token");
}
@Test
public void testNonAuthenticatedAccessReturnsUnauthorized401() {
Response response = given().contentType(ContentType.JSON).body("{ \"password\": \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
Response response =
given()
.contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
assertEquals(401, response.getStatusCode());
}
@Test
public void testAuthenticatedAccessReturnsCreated200() {
Response response = given().header("Authorization", "Bearer " + adminToken).contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
Response response =
given()
.header("Authorization", "Bearer " + adminToken)
.contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
assertEquals(201, response.getStatusCode());
}
@Test
public void testMalformedJsonRaisesBadRequestException400() {
Response response = given().header("Authorization", "Bearer " + adminToken).contentType(ContentType.JSON)
.body("{ \"password\"x \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
Response response =
given()
.header("Authorization", "Bearer " + adminToken)
.contentType(ContentType.JSON)
.body("{ \"password\"x \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
assertEquals(400, response.getStatusCode());
}
@Test
public void testMalformedJsonExceptionMessage() {
Response response = given().header("Authorization", "Bearer " + adminToken).contentType(ContentType.JSON)
.body("{ \"password\"x \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
Response response =
given()
.header("Authorization", "Bearer " + adminToken)
.contentType(ContentType.JSON)
.body("{ \"password\"x \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
String error = response.jsonPath().getString("error");
......@@ -75,21 +98,28 @@ public class MailPassResourceIntegrationTest {
@Test
public void testMissingJsonObjectRaisesBadRequestException400() {
Response response = given().header("Authorization", "Bearer " + adminToken).contentType(ContentType.JSON)
.body("{ \"missing_password\": \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
Response response =
given()
.header("Authorization", "Bearer " + adminToken)
.contentType(ContentType.JSON)
.body("{ \"missing_password\": \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
assertEquals(400, response.getStatusCode());
}
@Test
public void testMissingJsonObjectExceptionMessage() {
Response response = given().header("Authorization", "Bearer " + adminToken).contentType(ContentType.JSON)
.body("{ \"missing_password\": \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
Response response =
given()
.header("Authorization", "Bearer " + adminToken)
.contentType(ContentType.JSON)
.body("{ \"missing_password\": \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
String error = response.jsonPath().getString("error");
assertEquals("password object not detected in provided JSON body", error);
}
}
package org.archlinux.keycloak.mailpass.rest;
import static io.restassured.RestAssured.given;
import static org.junit.Assert.assertEquals;
import com.palantir.docker.compose.DockerComposeRule;
import com.palantir.docker.compose.connection.waiting.HealthChecks;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import static io.restassured.RestAssured.given;
import static org.junit.Assert.assertEquals;
import java.text.MessageFormat;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
public class MailPassRestResourceIntegrationTest {
private final static String ROOT_URI = "http://localhost:{0,number,#}/auth/realms/master/mailpass/roleauth";
private final static String ALT_URI = "http://localhost:{0,number,#}/auth/realms/develop/mailpass/roleauth";
private final static String TOKEN_GEN_URI = "http://localhost:{0,number,#}/auth/realms/master/protocol/openid-connect/token";
private static String testToken;
private static int port;
@ClassRule
public static DockerComposeRule docker = DockerComposeRule.builder()
.file("src/integrationTest/resources/docker-compose.yml")
.waitingForService("keycloak", HealthChecks.toRespondOverHttp(8080,
(port) -> port.inFormat("http://$HOST:$EXTERNAL_PORT/auth/realms/master")))
.build();
@BeforeClass
public static void setup() {
port = docker.containers().container("keycloak").port(8080).getExternalPort();
Response response = given().accept(ContentType.JSON).contentType(ContentType.URLENC)
.body("grant_type=password&username=test&password=test&client_id=admin-cli")
.post(MessageFormat.format(TOKEN_GEN_URI, port));
testToken = response.jsonPath().getString("access_token");
}
@Test
public void testInvalidRoleReturnsForbidden403() {
Response response = given().header("Authorization", "Bearer " + testToken).contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
assertEquals(403, response.getStatusCode());
}
@Test
public void testInvalidRoleMessage() {
Response response = given().header("Authorization", "Bearer " + testToken).contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }").when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
String error = response.jsonPath().getString("error");
assertEquals("Does not have realm admin role", error);
}
@Test
public void testInvalidRealmReturnsForbidden403() {
Response response = given().header("Authorization", "Bearer " + testToken).contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }").when()
.post(MessageFormat.format(ALT_URI, port) + "/compute-password-hash");
assertEquals(403, response.getStatusCode());
}
@Test
public void testInvalidRealmMessage() {
Response response = given().header("Authorization", "Bearer " + testToken).contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }").when()
.post(MessageFormat.format(ALT_URI, port) + "/compute-password-hash");
String error = response.jsonPath().getString("error");
assertEquals("Operation not allowed on this realm", error);
}
private static final String ROOT_URI =
"http://localhost:{0,number,#}/auth/realms/master/mailpass/roleauth";
private static final String ALT_URI =
"http://localhost:{0,number,#}/auth/realms/develop/mailpass/roleauth";
private static final String TOKEN_GEN_URI =
"http://localhost:{0,number,#}/auth/realms/master/protocol/openid-connect/token";
private static String testToken;
private static int port;
@ClassRule
public static DockerComposeRule docker =
DockerComposeRule.builder()
.file("src/integrationTest/resources/docker-compose.yml")
.waitingForService(
"keycloak",
HealthChecks.toRespondOverHttp(
8080, (port) -> port.inFormat("http://$HOST:$EXTERNAL_PORT/auth/realms/master")))
.build();
/** Generate bearer token and make it available to all the tests in the class. */
@BeforeClass
public static void setup() {
port = docker.containers().container("keycloak").port(8080).getExternalPort();
Response response =
given()
.accept(ContentType.JSON)
.contentType(ContentType.URLENC)
.body("grant_type=password&username=test&password=test&client_id=admin-cli")
.post(MessageFormat.format(TOKEN_GEN_URI, port));
testToken = response.jsonPath().getString("access_token");
}
@Test
public void testInvalidRoleReturnsForbidden403() {
Response response =
given()
.header("Authorization", "Bearer " + testToken)
.contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
assertEquals(403, response.getStatusCode());
}
@Test
public void testInvalidRoleMessage() {
Response response =
given()
.header("Authorization", "Bearer " + testToken)
.contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }")
.when()
.post(MessageFormat.format(ROOT_URI, port) + "/compute-password-hash");
String error = response.jsonPath().getString("error");
assertEquals("Does not have realm admin role", error);
}
@Test
public void testInvalidRealmReturnsForbidden403() {
Response response =
given()
.header("Authorization", "Bearer " + testToken)
.contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }")
.when()
.post(MessageFormat.format(ALT_URI, port) + "/compute-password-hash");
assertEquals(403, response.getStatusCode());
}
@Test
public void testInvalidRealmMessage() {
Response response =
given()
.header("Authorization", "Bearer " + testToken)
.contentType(ContentType.JSON)
.body("{ \"password\": \"password\" }")
.when()
.post(MessageFormat.format(ALT_URI, port) + "/compute-password-hash");
String error = response.jsonPath().getString("error");
assertEquals("Operation not allowed on this realm", error);
}
}
package org.archlinux.keycloak.mailpass.rest;
import io.restassured.path.json.JsonPath;
import io.restassured.path.json.exception.JsonPathException;
import java.security.SecureRandom;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
......@@ -9,20 +10,15 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.bouncycastle.crypto.generators.OpenBSDBCrypt;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.models.KeycloakSession;
import io.restassured.path.json.JsonPath;
import io.restassured.path.json.exception.JsonPathException;
/**
* A custom REST endpoint to trigger functionality on the Keycloak server, which
* is not available through the default set of built-in Keycloak REST endpoints.
* This is to be used during the storage of a custom attribute on the Account
* Management Console for the mail password. The data stored will be a Bcrypt
* hash instead of the plain text password.
* A custom REST endpoint to trigger functionality on the Keycloak server, which is not available
* through the default set of built-in Keycloak REST endpoints. This is to be used during the
* storage of a custom attribute on the Account Management Console for the mail password. The data
* stored will be a Bcrypt hash instead of the plain text password.
*/
public class MailPassResource {
......@@ -77,5 +73,4 @@ public class MailPassResource {
throw new BadRequestException("provided data is not in valid JSON format");
}
}
}
......@@ -4,9 +4,8 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.services.resource.RealmResourceProvider;
/**
* A provider of a custom REST resource for a path relative to Realm's RESTful
* API that cannot be resolved by the Keycloak server. This implementation is a
* requirement for custom REST endpoints.
* A provider of a custom REST resource for a path relative to Realm's RESTful API that cannot be
* resolved by the Keycloak server. This implementation is a requirement for custom REST endpoints.
*/
public class MailPassResourceProvider implements RealmResourceProvider {
......@@ -14,6 +13,13 @@ public class MailPassResourceProvider implements RealmResourceProvider {
private String realmName;
private String realmRole;
/**
* Store the pre-configured SPI fields to enable verification before requests take place.
*
* @param session The Keycloak session.
* @param realmName The Keycloak realm under which requests are allowed.
* @param realmRole The role required to submit requests.
*/
public MailPassResourceProvider(KeycloakSession session, String realmName, String realmRole) {
this.session = session;
this.realmName = realmName;
......@@ -26,7 +32,5 @@ public class MailPassResourceProvider implements RealmResourceProvider {
}
@Override
public void close() {
}
public void close() {}
}
......@@ -7,9 +7,8 @@ import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.resource.RealmResourceProviderFactory;
/**
* A factory that extends RealmResourceProviderFactory instance to create the
* custom mail pass resource provider. This implementation is a requirement for
* custom REST endpoints.
* A factory that extends RealmResourceProviderFactory instance to create the custom mail pass
* resource provider. This implementation is a requirement for custom REST endpoints.
*/
public class MailPassResourceProviderFactory implements RealmResourceProviderFactory {
......@@ -38,11 +37,8 @@ public class MailPassResourceProviderFactory implements RealmResourceProviderFac
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
public void postInit(KeycloakSessionFactory factory) {}
@Override
public void close() {
}
public void close() {}
}
......@@ -8,11 +8,10 @@ import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager;
/**
* A custom REST resource in the form of a domain extension which makes the
* custom endpoint accessible just for authenticated users. The REST request
* must be authenticated with bearer access token of an authenticated user and
* the user must be part of a pre-configured realm role in order to access the
* resource.
* A custom REST resource in the form of a domain extension which makes the custom endpoint
* accessible just for authenticated users. The REST request must be authenticated with bearer
* access token of an authenticated user and the user must be part of a pre-configured realm role in
* order to access the resource.
*/
public class MailPassRestResource {
......@@ -21,6 +20,13 @@ public class MailPassRestResource {
private final String realmRole;
private final AuthenticationManager.AuthResult auth;
/**
* Store the pre-configured SPI fields to enable verification before requests take place.
*
* @param session The Keycloak session.
* @param realmName The Keycloak realm under which requests are allowed.
* @param realmRole The role required to submit requests.
*/
public MailPassRestResource(KeycloakSession session, String realmName, String realmRole) {
this.session = session;
this.auth = new AppAuthManager.BearerTokenAuthenticator(session).authenticate();
......@@ -28,6 +34,11 @@ public class MailPassRestResource {
this.realmRole = realmRole;
}
/**
* Ensure the realm and role match the SPI configuration before enabling mailpass requests.
*
* @return MailPassResource instance after successful verification.
*/
@Path("roleauth")
public MailPassResource getMailPassResourceAuthenticated() {
checkRealm();
......@@ -45,9 +56,9 @@ public class MailPassRestResource {
private void checkRealmAdmin() {
if (auth == null) {
throw new NotAuthorizedException("Bearer");
} else if (auth.getToken().getRealmAccess() == null || !auth.getToken().getRealmAccess().isUserInRole(realmRole)) {
} else if (auth.getToken().getRealmAccess() == null
|| !auth.getToken().getRealmAccess().isUserInRole(realmRole)) {
throw new ForbiddenException("Does not have realm admin role");
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment