////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
= Built-In Authentication Support

include::./attributes.adoc[]

This document describes the Quarkus built-in authentication mechanisms for HTTP based FORM, BASIC and Mutual TLS authentication as well as the proactive authentication.

[[basic-auth]]
== Basic Authentication

To enable basic authentication set `quarkus.http.auth.basic=true`. You must also have at least one extension installed
that provides a username/password based `IdentityProvider`, such as xref:security-jdbc.adoc[Elytron JDBC].

Please see xref:security.adoc#identity-providers[Security Identity Providers] for more information.

Please also see xref:security-testing.adoc#configuring-user-information[Configuring User Information in application.properties] section.

[[form-auth]]
== Form Based Authentication

Quarkus provides form based authentication that works in a similar manner to traditional Servlet form based auth. Unlike
traditional form authentication, the authenticated user is not stored in an HTTP session, as Quarkus does not provide
clustered HTTP session support. Instead the authentication information is stored in an encrypted cookie, which can
be read by all members of the cluster (provided they all share the same encryption key).

The encryption key can be set using the `quarkus.http.auth.session.encryption-key` property, and it must be at least 16 characters
long. This key is hashed using SHA-256 and the resulting digest is used as a key for AES-256 encryption of the cookie
value. This 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 will be generated with an updated expiry time if the session
is in use.

The following properties can be used to configure form based auth:

include::{generated-dir}/config/quarkus-vertx-http-config-group-form-auth-config.adoc[opts=optional, leveloffset=+1]

[[mutual-tls]]
== Mutual TLS Authentication

Quarkus provides mTLS authentication so that you can authenticate users based on their X.509 certificates.

To use this authentication method, you should first enable SSL for your application. For more details, check the xref:http-reference.adoc#ssl[Supporting secure connections with SSL] guide.

Once your application is accepting secure connections, the next step is to configure a `quarkus.http.ssl.certificate.trust-store-file`
holding all the certificates that your application should trust as well as how your application should ask for certificates when
a client (e.g.: browser or another service) tries to access one of its protected resources.

[source,properties]
----
quarkus.http.ssl.certificate.key-store-file=server-keystore.jks            <1>
quarkus.http.ssl.certificate.key-store-password=the_key_store_secret
quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks        <2>
quarkus.http.ssl.certificate.trust-store-password=the_trust_store_secret
quarkus.http.ssl.client-auth=required                                      <3>

quarkus.http.auth.permission.default.paths=/*                              <4>
quarkus.http.auth.permission.default.policy=authenticated
----
<1> Configures a key store where the server's private key is located.
<2> Configures a trust store from where the trusted certificates are going to be loaded from.
<3> Defines that the server should *always* ask certificates from clients. You can relax this behavior by using `REQUEST` so
that the server should still accept requests without a certificate. Useful when you are also supporting authentication methods other than
mTLS.
<4> Defines a policy where only authenticated users should have access to resources from your application.

Once the incoming request matches a valid certificate in the truststore, your application should be able to obtain the subject by
just injecting a `SecurityIdentity` as follows:

[#x509-subject-example]
.Obtaining the subject
[source,java]
----
@Inject
SecurityIdentity identity;

@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
    return String.format("Hello, %s", identity.getPrincipal().getName());
}
----

You should also be able to get the certificate as follows:

[#x509-credential-example]
.Obtaining the certificate
[source,java]
----
import java.security.cert.X509Certificate;
import io.quarkus.security.credential.CertificateCredential;

CertificateCredential credential = identity.getCredential(CertificateCredential.class);
X509Certificate certificate = credential.getCertificate();
----

=== Authorization

The information from the client certificate can be used to enhance Quarkus `SecurityIdentity`. For example, one can add new roles after checking a client certificate subject name, etc.
Please see the xref:security-customization.adoc#security-identity-customization[SecurityIdentity Customization] section for more information about customizing Quarkus `SecurityIdentity`.

[[proactive-authentication]]
== Proactive Authentication

By default Quarkus does what we call proactive authentication. This means that if an incoming request has a
credential then that request will always be authenticated (even if the target page does not require authentication).

This means that requests with an invalid credential will always be rejected, even for public pages. You can change
this behavior and only authenticate when required by setting `quarkus.http.auth.proactive=false`.

If you disable proactive authentication then the authentication process will only be run when an identity is requested,
either because there are security rules that requires the user to be authenticated, or due to programmatic access to the
current identity.

Note that if proactive authentication is in use accessing the `SecurityIdentity` is a blocking operation. This is because
authentication may not have happened yet, and accessing it may require calls to external systems such as databases that
may block. For blocking applications this is no problem, however if you are have disabled authentication in a reactive
application this will fail (as you cannot do blocking operations on the IO thread). To work around this you need to
`@Inject` an instance of `io.quarkus.security.identity.CurrentIdentityAssociation`, and call the
`Uni<SecurityIdentity> getDeferredIdentity();` method. You can then subscribe to the resulting `Uni` and will be notified
when authentication is complete and the identity is available.

=== How to customize authentication exception responses

By default the authentication security constraints are enforced before the JAX-RS chain starts.
Disabling the proactive authentication effectively shifts this process to the moment when the JAX-RS chain starts running thus making it possible to use JAX-RS `ExceptionMapper` to capture Quarkus Security authentication exceptions such as `io.quarkus.security.AuthenticationFailedException`, for example:

[source,java]
----
package io.quarkus.it.keycloak;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import io.quarkus.security.AuthenticationFailedException;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFailedExceptionMapper implements ExceptionMapper<AuthenticationFailedException> {

    @Context
    UriInfo uriInfo;

    @Override
    public Response toResponse(AuthenticationFailedException exception) {
        return Response.status(401).header("WWW-Authenticate", "Basic realm=\"Quarkus\"").build();
    }
}
----

== References

* xref:security.adoc[Quarkus Security]
