Chapter 1. Getting started with security by using Basic authentication and Jakarta Persistence
Get started with Quarkus Security by securing your Quarkus application endpoints with the built-in Quarkus Basic authentication and the Jakarta Persistence identity provider, enabling role-based access control.
The Jakarta Persistence IdentityProvider verifies and converts a Basic authentication user name and password pair to a SecurityIdentity instance, which is used to authorize access requests, making your Quarkus application secure.
For more information about Jakarta Persistence, see the Quarkus Security with Jakarta Persistence guide.
This tutorial prepares you to implement more advanced security mechanisms in Quarkus, for example, how to use the OpenID Connect (OIDC) authentication mechanism.
1.1. Prerequisites Copy linkLink copied to clipboard!
To complete this guide, you need:
- Roughly 15 minutes
- An IDE
-
JDK 17+ installed with
JAVA_HOMEconfigured appropriately - Apache Maven 3.8.6 or later
- Optionally the Quarkus CLI if you want to use it
- Optionally Mandrel or GraalVM installed and configured appropriately if you want to build a native executable (or Docker if you use a native container build)
1.2. Building your application Copy linkLink copied to clipboard!
This tutorial gives detailed steps for creating an application with endpoints that illustrate various authorization policies:
| Endpoint | Description |
|---|---|
|
| Accessible without authentication, this endpoint allows anonymous access. |
|
|
Secured with role-based access control (RBAC), this endpoint is accessible only to users with the |
|
|
Also secured by RBAC, this endpoint is accessible only to users with the |
To examine the completed example, download the archive or clone the Git repository:
git clone https://github.com/quarkusio/quarkus-quickstarts.git -b 3.20
git clone https://github.com/quarkusio/quarkus-quickstarts.git -b 3.20
You can find the solution in the security-jpa-quickstart directory.
1.3. Create and verify the Maven project Copy linkLink copied to clipboard!
For Quarkus Security to be able to map your security source to Jakarta Persistence entities, ensure that the Maven project in this tutorial includes the quarkus-security-jpa extension.
Hibernate ORM with Panache is used to store your user identities, but you can also use Hibernate ORM with the quarkus-security-jpa extension.
You must also add your preferred database connector library. The instructions in this example tutorial use a PostgreSQL database for the identity store.
1.3.1. Create the Maven project Copy linkLink copied to clipboard!
You can create a new Maven project with the Security Jakarta Persistence extension or add the extension to an existing Maven project. You can use either Hibernate ORM or Hibernate Reactive.
1.3.1.1. Creating new Maven project Copy linkLink copied to clipboard!
To create a new Maven project with the Jakarta Persistence extension, complete one of the following steps:
- To create the Maven project with Hibernate ORM, use the following command:
Using the Quarkus CLI:
quarkus create app org.acme:security-jpa-quickstart \ --extension='security-jpa,jdbc-postgresql,rest,hibernate-orm-panache' \ --no-code cd security-jpa-quickstartquarkus create app org.acme:security-jpa-quickstart \ --extension='security-jpa,jdbc-postgresql,rest,hibernate-orm-panache' \ --no-code cd security-jpa-quickstartCopy to Clipboard Copied! Toggle word wrap Toggle overflow To create a Gradle project, add the
--gradleor--gradle-kotlin-dsloption.For more information about how to install and use the Quarkus CLI, see the Quarkus CLI guide.
Using Maven:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow To create a Gradle project, add the
-DbuildTool=gradleor-DbuildTool=gradle-kotlin-dsloption.
For Windows users:
-
If using cmd, (don’t use backward slash
\and put everything on the same line) -
If using Powershell, wrap
-Dparameters in double quotes e.g."-DprojectArtifactId=security-jpa-quickstart"
1.3.1.2. Adding Jakarta Persistence extension to existing project Copy linkLink copied to clipboard!
To add the Jakarta Persistence extension to an existing Maven project, complete one of the following steps:
To add the Security Jakarta Persistence extension to an existing Maven project with Hibernate ORM, run the following command from your project base directory:
Using the Quarkus CLI:
quarkus extension add security-jpa
quarkus extension add security-jpaCopy to Clipboard Copied! Toggle word wrap Toggle overflow Using Maven:
./mvnw quarkus:add-extension -Dextensions='security-jpa'
./mvnw quarkus:add-extension -Dextensions='security-jpa'Copy to Clipboard Copied! Toggle word wrap Toggle overflow Using Gradle:
./gradlew addExtension --extensions='security-jpa'
./gradlew addExtension --extensions='security-jpa'Copy to Clipboard Copied! Toggle word wrap Toggle overflow
1.3.2. Verify the quarkus-security-jpa dependency Copy linkLink copied to clipboard!
After you have run either of the preceding commands to create the Maven project, verify that the quarkus-security-jpa dependency was added to your project build XML file.
To verify the
quarkus-security-jpaextension, check for the following configuration:Using Maven:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-security-jpa</artifactId> </dependency><dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-security-jpa</artifactId> </dependency>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Using Gradle:
implementation("io.quarkus:quarkus-security-jpa")implementation("io.quarkus:quarkus-security-jpa")Copy to Clipboard Copied! Toggle word wrap Toggle overflow
1.4. Write the application Copy linkLink copied to clipboard!
Secure the API endpoint to determine who can access the application by using one of the following approaches:
Implement the
/api/publicendpoint to allow all users access to the application. Add a regular Jakarta REST resource to your Java source code, as shown in the following code snippet:src/main/java/org/acme/security/jpa/PublicResource.javaCopy to Clipboard Copied! Toggle word wrap Toggle overflow Implement an /api/admin endpoint that can only be accessed by users who have the admin role. The source code for the
/api/adminendpoint is similar, but instead, you use a@RolesAllowedannotation to ensure that only users granted theadminrole can access the endpoint. Add a Jakarta REST resource with the following@RolesAllowedannotation:src/main/java/org/acme/security/jpa/AdminResource.javaCopy to Clipboard Copied! Toggle word wrap Toggle overflow Implement an
/api/users/meendpoint that can only be accessed by users who have theuserrole. UseSecurityContextto get access to the currently authenticatedPrincipaluser and to return their username, all of which is retrieved from the database.src/main/java/org/acme/security/jpa/UserResource.javaCopy to Clipboard Copied! Toggle word wrap Toggle overflow
1.5. Define the user entity Copy linkLink copied to clipboard!
Specify how security information is stored in the model by adding the following annotations to the user entity:
src/main/java/org/acme/security/jpa/User.java
The quarkus-security-jpa extension only initializes if a single entity is annotated with @UserDefinition.
- 1
- The
@UserDefinitionannotation must be present on a single entity, either a regular Hibernate ORM entity or a Hibernate ORM with Panache entity. - 2
- Indicates the field used for the username.
- 3
- Indicates the field used for the password. By default, it uses bcrypt-hashed passwords. You can configure it to use plain text or custom passwords.
- 4
- Indicates the comma-separated list of roles added to the target principal representation attributes.
- 5
- Allows us to add users while hashing passwords with the proper bcrypt hash.
Don’t forget to set up the Panache and PostgreSQL JDBC driver, please see Setting up and configuring Hibernate ORM with Panache for more information.
1.6. Configure the application Copy linkLink copied to clipboard!
Enable the built-in Quarkus Basic authentication mechanism by setting the
quarkus.http.auth.basicproperty totrue:quarkus.http.auth.basic=trueNoteWhen secure access is required, and no other authentication mechanisms are enabled, the built-in Basic authentication of Quarkus is the fallback authentication mechanism. Therefore, in this tutorial, you do not need to set the property
quarkus.http.auth.basictotrue.Configure at least one data source in the
src/main/resources/application.propertiesfile so thequarkus-security-jpaextension can access your database. For example:src/main/resources/application.properties
Copy to Clipboard Copied! Toggle word wrap Toggle overflow By adding the
%prod.profile prefix, you ensure that the data source properties are only observed by an application running in production mode.-
To initialize the database with users and roles, implement the
Startupclass, as outlined in the following code snippet:
src/main/java/org/acme/security/jpa/Startup.java
The preceding example demonstrates how the application can be protected and identities provided by the specified database.
In a production environment, do not store plain text passwords. As a result, the quarkus-security-jpa defaults to using bcrypt-hashed passwords.
1.7. Test your application in dev mode by using Dev Services for PostgreSQL Copy linkLink copied to clipboard!
Complete the integration testing of your application in JVM and native modes by using Dev Services for PostgreSQL before you run your application in production mode.
Start by adding the following dependencies to your test project:
Using Maven:
<dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency><dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency>Copy to Clipboard Copied! Toggle word wrap Toggle overflow Using Gradle:
testImplementation("io.rest-assured:rest-assured")testImplementation("io.rest-assured:rest-assured")Copy to Clipboard Copied! Toggle word wrap Toggle overflow
To run your application in dev mode:
Using the Quarkus CLI:
quarkus dev
quarkus devCopy to Clipboard Copied! Toggle word wrap Toggle overflow Using Maven:
./mvnw quarkus:dev
./mvnw quarkus:devCopy to Clipboard Copied! Toggle word wrap Toggle overflow Using Gradle:
./gradlew --console=plain quarkusDev
./gradlew --console=plain quarkusDevCopy to Clipboard Copied! Toggle word wrap Toggle overflow
In this scenario, Dev Services for PostgreSQL launches and configures a PostgreSQL test container. Make sure that either Podman or Docker is installed on your computer.
To write the integration test, use the following code sample:
src/test/java/org/acme/security/jpa/JpaSecurityRealmTest.java
As you can see in this code sample, you do not need to start the test container from the test code.
To run these tests, choose Press [r] to resume testing option which is shown in the console after you started your application in dev mode.
When you start your application in dev mode, Dev Services for PostgreSQL launches a PostgreSQL dev mode container so that you can start developing your application. While developing your application, you can add and run tests individually by using the Continuous Testing feature. Dev Services for PostgreSQL supports testing while you develop by providing a separate PostgreSQL test container that does not conflict with the dev mode container.
Alternatively, you can run these tests using Maven:
./mvnw test
./mvnw test
1.8. Test your application in production mode by using Curl or browser Copy linkLink copied to clipboard!
To test your application using Curl or a browser start a PostgreSQL server first. Then, compile and run your application in either JVM or native mode.
1.8.1. Start the PostgreSQL server Copy linkLink copied to clipboard!
docker run --rm=true --name security-getting-started -e POSTGRES_USER=quarkus \
-e POSTGRES_PASSWORD=quarkus -e POSTGRES_DB=quarkus \
-p 5432:5432 postgres:17
docker run --rm=true --name security-getting-started -e POSTGRES_USER=quarkus \
-e POSTGRES_PASSWORD=quarkus -e POSTGRES_DB=quarkus \
-p 5432:5432 postgres:17
1.8.2. Compile and run the application Copy linkLink copied to clipboard!
Compile and run your Quarkus application by using one of the following methods:
JVM mode
Compile the application:
Using the Quarkus CLI:
quarkus build
quarkus buildCopy to Clipboard Copied! Toggle word wrap Toggle overflow Using Maven:
./mvnw install
./mvnw installCopy to Clipboard Copied! Toggle word wrap Toggle overflow Using Gradle:
./gradlew build
./gradlew buildCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Run the application:
java -jar target/quarkus-app/quarkus-run.jar
java -jar target/quarkus-app/quarkus-run.jarCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Native mode
Compile the application:
Using the Quarkus CLI:
quarkus build --native
quarkus build --nativeCopy to Clipboard Copied! Toggle word wrap Toggle overflow Using Maven:
./mvnw install -Dnative
./mvnw install -DnativeCopy to Clipboard Copied! Toggle word wrap Toggle overflow Using Gradle:
./gradlew build -Dquarkus.native.enabled=true
./gradlew build -Dquarkus.native.enabled=trueCopy to Clipboard Copied! Toggle word wrap Toggle overflow
Run the application:
./target/security-jpa-quickstart-1.0.0-SNAPSHOT-runner
./target/security-jpa-quickstart-1.0.0-SNAPSHOT-runnerCopy to Clipboard Copied! Toggle word wrap Toggle overflow
1.8.3. Access and test the application security with Curl Copy linkLink copied to clipboard!
When your application is running, you can access its endpoints by using one of the following Curl commands.
Connect to a protected endpoint anonymously:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Connect to a protected endpoint anonymously:
curl -i -X GET http://localhost:8080/api/admin HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic
$ curl -i -X GET http://localhost:8080/api/admin HTTP/1.1 401 Unauthorized WWW-Authenticate: BasicCopy to Clipboard Copied! Toggle word wrap Toggle overflow Connect to a protected endpoint as an authorized user:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
You can also access the same endpoint URLs by using a browser.
1.8.4. Access and test the application security with the browser Copy linkLink copied to clipboard!
If you use a browser to connect to a protected resource anonymously, a Basic authentication form displays, prompting you to enter credentials.
1.8.5. Results Copy linkLink copied to clipboard!
When you provide the credentials of an authorized user, for example, admin:admin, the Jakarta Persistence security extension authenticates and loads the user’s roles. The admin user is authorized to access the protected resources.
If a resource is protected with @RolesAllowed("user"), the user admin is not authorized to access the resource because it is not assigned to the "user" role, as shown in the following example:
curl -i -X GET -u admin:admin http://localhost:8080/api/users/me HTTP/1.1 403 Forbidden
$ curl -i -X GET -u admin:admin http://localhost:8080/api/users/me
HTTP/1.1 403 Forbidden
Finally, the user named user is authorized, and the security context contains the principal details, for example, the username.
1.9. What’s next Copy linkLink copied to clipboard!
You have successfully learned how to create and test a secure Quarkus application. This was achieved by integrating the built-in Basic authentication in Quarkus with the Jakarta Persistence identity provider.
After completing this tutorial, you can explore more advanced security mechanisms in Quarkus. The following information shows you how to use OpenID Connect for secure single sign-on access to your Quarkus endpoints: