2.2.2. Form-based authentication
Quarkus provides form-based authentication that works similarly to traditional Servlet form-based authentication. Unlike traditional form authentication, the authenticated user is not stored in an HTTP session because Quarkus does not support clustered HTTP sessions. Instead, the authentication information is stored in an encrypted cookie, which can be read by all cluster members who share the same encryption key.
To apply encryption, add the quarkus.http.auth.session.encryption-key property, and ensure the value you set is at least 16 characters long. The encryption key is hashed by using SHA-256. The resulting digest is used as a key for AES-256 encryption of the cookie value. The cookie contains an expiry time as part of the encrypted value, so all nodes in the cluster must have their clocks synchronized. At one-minute intervals, a new cookie gets generated with an updated expiry time if the session is in use.
To get started with form authentication, you should have similar settings as described in Enable Basic authentication and property quarkus.http.auth.form.enabled must be set to true.
Simple application.properties with form-base authentication can look similar to this:
quarkus.http.auth.form.enabled=true
quarkus.http.auth.form.login-page=login.html
quarkus.http.auth.form.landing-page=hello
quarkus.http.auth.form.error-page=
# Define testing user
quarkus.security.users.embedded.enabled=true
quarkus.security.users.embedded.plain-text=true
quarkus.security.users.embedded.users.alice=alice
quarkus.security.users.embedded.roles.alice=user
Configuring user names, secrets, and roles in the application.properties file is appropriate only for testing scenarios. For securing a production application, it is crucial to use a database or LDAP to store this information. For more information you can take a look at Quarkus Security with Jakarta Persistence or other mentioned in Enable Basic authentication.
and application login page will contain HTML form similar to this:
<form action="/j_security_check" method="post">
<label>Username</label>
<input type="text" placeholder="Username" name="j_username" required>
<label>Password</label>
<input type="password" placeholder="Password" name="j_password" required>
<button type="submit">Login</button>
</form>
With single-page applications (SPA), you typically want to avoid redirects by removing default page paths, as shown in the following example:
# do not redirect, respond with HTTP 200 OK
quarkus.http.auth.form.landing-page=
# do not redirect, respond with HTTP 401 Unauthorized
quarkus.http.auth.form.login-page=
quarkus.http.auth.form.error-page=
# HttpOnly must be false if you want to log out on the client; it can be true if logging out from the server
quarkus.http.auth.form.http-only-cookie=false
Now that you have disabled redirects for the SPA, you must log in and log out programmatically from your client. Below are examples of JavaScript methods for logging into the j_security_check endpoint and logging out of the application by destroying the cookie.
const login = () => {
// Create an object to represent the form data
const formData = new URLSearchParams();
formData.append("j_username", username);
formData.append("j_password", password);
// Make an HTTP POST request using fetch against j_security_check endpoint
fetch("j_security_check", {
method: "POST",
body: formData,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
.then((response) => {
if (response.status === 200) {
// Authentication was successful
console.log("Authentication successful");
} else {
// Authentication failed
console.error("Invalid credentials");
}
})
.catch((error) => {
console.error(error);
});
};
To log out of the SPA from the client, the cookie must be set to quarkus.http.auth.form.http-only-cookie=false so you can destroy the cookie and possibly redirect back to your main page.
const logout= () => {
// delete the credential cookie, essentially killing the session
const removeCookie = `quarkus-credential=; Max-Age=0;path=/`;
document.cookie = removeCookie;
// perform post-logout actions here, such as redirecting back to your login page
};
To log out of the SPA from the server, the cookie can be set to quarkus.http.auth.form.http-only-cookie=true and use this example code to destroy the cookie.
import io.quarkus.security.identity.CurrentIdentityAssociation;
import io.quarkus.vertx.http.runtime.security.FormAuthenticationMechanism;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.POST;
@Inject
CurrentIdentityAssociation identity;
@POST
public Response logout() {
if (identity.getIdentity().isAnonymous()) {
throw new UnauthorizedException("Not authenticated");
}
FormAuthenticationMechanism.logout(identity.getIdentity());
return Response.noContent().build();
}
- 1
- Perform the logout by removing the session cookie.
The following properties can be used to configure form-based authentication:
🔒 Fixed at build time - Configuration property fixed at build time - All other configuration properties are overridable at runtime
| Configuration property | Type | Default |
|
Determines whether the entire permission set is enabled, or not. By default, if the permission set is defined, it is enabled.
Environment variable: | boolean | |
|
The HTTP policy that this permission set is linked to. There are three built-in policies: permit, deny and authenticated. Role based policies can be defined, and extensions can add their own policies.
Environment variable: | string | required ⚠️ Required |
|
The methods that this permission set applies to. If this is not set then they apply to all methods. Note that if a request matches any path from any permission set, but does not match the constraint due to the method not being listed then the request will be denied. Method specific permissions take precedence over matches that do not have any methods set. This means that for example if Quarkus is configured to allow GET and POST requests to /admin to and no other permissions are configured PUT requests to /admin will be denied.
Environment variable: | list of string | |
|
The paths that this permission check applies to. If the path ends in /* then this is treated as a path prefix, otherwise it is treated as an exact match. Matches are done on a length basis, so the most specific path match takes precedence. If multiple permission sets match the same path then explicit methods matches take precedence over matches without methods set, otherwise the most restrictive permissions are applied.
Environment variable: | list of string | |
|
Path specific authentication mechanism which must be used to authenticate a user. It needs to match
Environment variable: | string | |
|
Indicates that this policy always applies to the matched paths in addition to the policy with a winning path. Avoid creating more than one shared policy to minimize the performance impact.
Environment variable: | boolean |
|
|
Whether permission check should be applied on all matching paths, or paths specific for the Jakarta REST resources.
Environment variable: | all: Apply on all matching paths.
jaxrs: Declares that a permission check must only be applied on the Jakarta REST request paths. Use this option to delay the permission check if an authentication mechanism is chosen with an annotation on the matching Jakarta REST endpoint. This option must be set if the following REST endpoint annotations are used: - | all |
|
The roles that are allowed to access resources protected by this policy. By default, access is allowed to any authenticated user.
Environment variable: | list of string |
|
|
Add roles granted to the
Environment variable: | Map<String,List<String>> | |
|
Permissions granted to the
Environment variable: | Map<String,List<String>> | |
|
Permissions granted by this policy will be created with a
Environment variable: | string |
|
|
Map the
For example, if
Environment variable: | Map<String,List<String>> | |
|
Client certificate attribute whose values are going to be mapped to the 'SecurityIdentity' roles according to the roles mapping specified in the certificate properties file. The attribute must be either one of the Relative Distinguished Names (RDNs) or Subject Alternative Names (SANs). By default, the Common Name (CN) attribute value is used for roles mapping. Supported values are:
Environment variable: | string |
|
|
Properties file containing the client certificate attribute value to role mappings. Use it only if the mTLS authentication mechanism is enabled with either
Properties file is expected to have the
Environment variable: | path | |
|
The authentication realm
Environment variable: | string | |
|
The login page. Redirect to login page can be disabled by setting
Environment variable: | string |
|
|
The username field name.
Environment variable: | string |
|
|
The password field name.
Environment variable: | string |
|
|
The error page. Redirect to error page can be disabled by setting
Environment variable: | string |
|
|
The landing page to redirect to if there is no saved page to redirect back to. Redirect to landing page can be disabled by setting
Environment variable: | string |
|
|
Option to control the name of the cookie used to redirect the user back to the location they want to access.
Environment variable: | string |
|
|
The inactivity (idle) timeout When inactivity timeout is reached, cookie is not renewed and a new login is enforced.
Environment variable: |
| |
|
How old a cookie can get before it will be replaced with a new cookie with an updated timeout, also referred to as "renewal-timeout". Note that smaller values will result in slightly more server load (as new encrypted cookies will be generated more often); however, larger values affect the inactivity timeout because the timeout is set when a cookie is generated. For example if this is set to 10 minutes, and the inactivity timeout is 30m, if a user’s last request is when the cookie is 9m old then the actual timeout will happen 21m after the last request because the timeout is only refreshed when a new cookie is generated. That is, no timeout is tracked on the server side; the timestamp is encoded and encrypted in the cookie itself, and it is decrypted and parsed with each request.
Environment variable: |
| |
|
The cookie that is used to store the persistent session
Environment variable: | string |
|
|
The cookie path for the session and location cookies.
Environment variable: | string |
|
|
Set the HttpOnly attribute to prevent access to the cookie via JavaScript.
Environment variable: | boolean |
|
|
SameSite attribute for the session and location cookies.
Environment variable: |
|
|
|
Max-Age attribute for the session cookie. This is the amount of time the browser will keep the cookie. The default value is empty, which means the cookie will be kept until the browser is closed.
Environment variable: | ||
|
Require that all registered HTTP authentication mechanisms must attempt to verify the request credentials.
By default, when the All produced security identities can be retrieved using the following utility method: `io.quarkus.vertx.http.runtime.security.HttpSecurityUtils++#++getSecurityIdentities(io.quarkus.security.identity.SecurityIdentity)`
An injected
This property is false by default which means that the authentication process is complete as soon as the first This property will be ignored if the path specific authentication is enabled.
Environment variable: | boolean |
|
|
Inclusive authentication mode.
Environment variable: | lax: Authentication succeeds if at least one of the registered HTTP authentication mechanisms creates the identity.
strict: Authentication succeeds if all the registered HTTP authentication mechanisms create the identity. Typically, inclusive authentication should be in the strict mode when the credentials are carried over mTLS, when both mTLS and another authentication, for example, OIDC bearer token authentication, must succeed. In such cases, | strict |
To write duration values, use the standard java.time.Duration format. See the Duration#parse() Java API documentation for more information.
You can also use a simplified format, starting with a number:
- If the value is only a number, it represents time in seconds.
-
If the value is a number followed by
ms, it represents time in milliseconds.
In other cases, the simplified format is translated to the java.time.Duration format for parsing:
-
If the value is a number followed by
h,m, ors, it is prefixed withPT. -
If the value is a number followed by
d, it is prefixed withP.