Quarkus security includes several extensions from Elytron. In this tutorial we will learn how to use the Database Realm Authentication with a simple REST Service.
Our project will perform authentication against the H2 in-memory database. In order to bootstrap our project we will need the following extensions
mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create \ -DprojectGroupId=com.mastertheboss \ -DprojectArtifactId=quarkus-jdbc-realm \ -DclassName="com.mastertheboss.SecuredResource" \ -Dextensions="elytron-security-jdbc, jdbc-h2, resteasy" \ -Dpath="/hello"
Now let’s add at first some protected resources in our REST Service. We will add one resource secured against the “admin” Role and one secured against the “guest” Role:
package com.mastertheboss; import javax.annotation.security.RolesAllowed; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/") public class SecuredResource { @GET @Path("/securedAdmin") @RolesAllowed("admin") @Produces(MediaType.TEXT_PLAIN) public String helloAdmin() { return "Hello from secured resource!"; } @GET @Path("/securedGuest") @RolesAllowed("guest") @Produces(MediaType.TEXT_PLAIN) public String helloGuest() { return "Hello from secured resource!"; } }
package com.mastertheboss; import io.quarkus.test.junit.QuarkusTest; import org.apache.http.HttpStatus; import org.junit.jupiter.api.Test; import static io.restassured.RestAssured.given; @QuarkusTest public class SecuredResourceTest { @Test public void testHelloEndpoint() { given() .auth().preemptive().basic("admin", "admin") .when() .get("/securedAdmin") .then() .statusCode(HttpStatus.SC_OK); given() .auth().preemptive().basic("guest", "guest") .when() .get("/securedGuest") .then() .statusCode(HttpStatus.SC_OK); } }
To have Quarkus bootstrap the H2 Database, include the following class which triggers the H2DatabaseTestResource:
package com.mastertheboss; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.h2.H2DatabaseTestResource; @QuarkusTestResource(H2DatabaseTestResource.class) public class TestResources { }
As the above class is included in an external JAR file, you have to add its dependency to the pom.xml file:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-test-h2</artifactId> <scope>test</scope> </dependency>
Configuring Elytron Database Realm with Quarkus
Done with the source code, let’s now add the configuration to bootstrap the Database Realm. First of all, an import.sql script to create the Tables at start is needed. It will also add two users for testing our project:
CREATE TABLE test_user ( id INT, username VARCHAR(255), password VARCHAR(255), role VARCHAR(255) ); INSERT INTO test_user (id, username, password, role) VALUES (1, 'admin', 'admin', 'admin'); INSERT INTO test_user (id, username, password, role) VALUES (2, 'user','user', 'user');
Then, into the application.properties file, add the configuration of the Elytron Realm, which points to the Table we have just created:
quarkus.datasource.url=jdbc:h2:tcp://localhost/mem:elytron_jdbc_test;DB_CLOSE_DELAY=-1;DB_CLOSE_DELAY=-1;INIT=RUNSCRIPT FROM 'classpath:import.sql' quarkus.datasource.driver=org.h2.Driver quarkus.datasource.username=username-default quarkus.security.jdbc.enabled=true quarkus.security.jdbc.principal-query.sql=SELECT u.password, u.role FROM test_user u WHERE u.username=? quarkus.security.jdbc.principal-query.clear-password-mapper.enabled=true quarkus.security.jdbc.principal-query.clear-password-mapper.password-index=1 quarkus.security.jdbc.principal-query.attribute-mappings.0.index=2 quarkus.security.jdbc.principal-query.attribute-mappings.0.to=groups
Here is the full project structure:
src ├── main │ ├── docker │ │ ├── Dockerfile.jvm │ │ └── Dockerfile.native │ ├── java │ │ └── com │ │ └── mastertheboss │ │ └── SecuredResource.java │ └── resources │ ├── application.properties │ └── META-INF │ └── resources │ └── index.html └── test ├── java │ └── com │ └── mastertheboss │ ├── NativeSecuredResourceIT.java │ ├── SecuredResourceTest.java │ └── TestResources.java └── resources └── import.sql
Running the Test class
Done with the code and configuration, you can run the Test as follows:
mvn install
As you can see from the logs, the test completed successfully and, behind the hoods, the IT started and stopped the Database when done:
[INFO] H2 database started in TCP server mode; server status: TCP server running at tcp://10.5.126.52:9092 (only local connections) 2019-11-11 18:20:03,126 INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation 2019-11-11 18:20:04,122 INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 996ms 2019-11-11 18:20:04,735 INFO [io.quarkus] (main) Quarkus 1.0.0.CR1 started in 0.585s. Listening on: http://0.0.0.0:8081 2019-11-11 18:20:04,735 INFO [io.quarkus] (main) Profile test activated. 2019-11-11 18:20:04,736 INFO [io.quarkus] (main) Installed features: [agroal, cdi, jdbc-h2, narayana-jta, resteasy, security, security-jdbc] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.258 s - in com.mastertheboss.SecuredResourceTest
That’s all! Source code for this tutorial: https://github.com/fmarchioni/mastertheboss/tree/master/quarkus/quarkus-jdbc-realm