From fb1da0fc4712e9606ee11f93217c3c1b9e46d9ea Mon Sep 17 00:00:00 2001 From: Michelle Purcell Date: Fri, 13 Jan 2023 17:56:32 +0000 Subject: [PATCH] Recompose security overview and built-in auth content to diataxis templates Recomposing security overview content to diataxis Recomposing security overview content to diataxis Addressed Sergey's review comments Further enhancements fix typos grammar Fixed broken links after recomposing to diataxis Fixed headings More link fixes Fix mTLS case Update docs/src/main/asciidoc/security-architecture-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-architecture-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-identity-providers-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-architecture-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-identity-providers-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-proactive-authentication-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-proactive-authentication-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-proactive-authentication-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-proactive-authentication-concept.adoc Co-authored-by: Mickey Maler Update docs/src/main/asciidoc/security-proactive-authentication-concept.adoc Co-authored-by: Mickey Maler Some style enhancements Update docs/src/main/asciidoc/security-proactive-authentication-concept.adoc Co-authored-by: Mickey Maler Style enhancement: reduce wordiness tweak Fixed further comments asciidocfix and added link Fixed some typos Fixed build error 2023-01-24T11:15:40.1095928Z [ERROR] asciidoctor: WARN: security-proactive-authentication-concept.adoc: line 86: section title out of sequence: expected level 1, got level 2 --- .../security-architecture-concept.adoc | 46 +++ ...ity-authentication-mechanisms-concept.adoc | 336 ++++++++++++++++++ ...ity-authorize-web-endpoints-reference.adoc | 2 +- ...security-basic-authentication-concept.adoc | 2 +- .../security-basic-authentication-howto.adoc | 12 +- ...ecurity-basic-authentication-tutorial.adoc | 12 +- ...ilt-in-authentication-support-concept.adoc | 256 ------------- .../main/asciidoc/security-customization.adoc | 6 +- .../security-identity-providers-concept.adoc | 27 ++ docs/src/main/asciidoc/security-jwt.adoc | 4 +- ...ty-oidc-bearer-authentication-concept.adoc | 7 +- ...dc-configuration-properties-reference.adoc | 3 +- .../security-openid-connect-multitenancy.adoc | 3 +- ...ity-openid-connect-web-authentication.adoc | 17 +- .../asciidoc/security-overview-concept.adoc | 315 ++-------------- ...rity-proactive-authentication-concept.adoc | 150 ++++++++ ...g-oidc-bearer-authentication-tutorial.adoc | 2 +- docs/src/main/asciidoc/spring-security.adoc | 2 +- 18 files changed, 630 insertions(+), 572 deletions(-) create mode 100644 docs/src/main/asciidoc/security-architecture-concept.adoc create mode 100644 docs/src/main/asciidoc/security-authentication-mechanisms-concept.adoc delete mode 100644 docs/src/main/asciidoc/security-built-in-authentication-support-concept.adoc create mode 100644 docs/src/main/asciidoc/security-identity-providers-concept.adoc create mode 100644 docs/src/main/asciidoc/security-proactive-authentication-concept.adoc diff --git a/docs/src/main/asciidoc/security-architecture-concept.adoc b/docs/src/main/asciidoc/security-architecture-concept.adoc new file mode 100644 index 0000000000000..e5411a1dadaa6 --- /dev/null +++ b/docs/src/main/asciidoc/security-architecture-concept.adoc @@ -0,0 +1,46 @@ +//// +This document 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 +//// +[id="security-architecture-concept"] += Quarkus Security architecture +include::_attributes.adoc[] +:categories: security +The Quarkus Security architecture provides several built-in authentication mechanisms. The `HttpAuthenticationMechanism` interface is the main entry mechanism for securing HTTP applications in Quarkus. Quarkus Security is also highly customizable. + +== Core components of Quarkus Security + +Quarkus Security uses `HttpAuthenticationMechanism` to extract the authentication credentials from the HTTP request and delegates them to `IdentityProvider` to convert the credentials to `SecurityIdentity`. +For example, the credentials can come from the `Authorization` header, client HTTPS certificates, or cookies. + +`IdentityProvider` verifies the authentication credentials and maps them to `SecurityIdentity`, which has the username, roles, original authentication credentials, and other attributes. + +You can inject a `SecurityIdentity` instance for every authenticated resource to get the authenticated identity information. + +In other contexts, it is possible to have other parallel representations of the same information or parts of it, for example, `SecurityContext` for JAX-RS or `JsonWebToken` for JSON Web Tokens (JWT). + +For more information, see xref:security-identity-providers-concept.adoc[Identity providers]. + +== Supported authentication mechanisms + +To learn more about security authentication in Quarkus and the supported mechanisms and protocols, see xref:security-authentication-mechanisms-concept.adoc[Authentication mechanisms in Quarkus]. + +== Proactive authentication + +Proactive authentication is enabled in Quarkus by default. The request is always authenticated if an incoming request has a credential, even if the target page does not require authentication +For more information, see xref:security-proactive-authentication-concept.adoc[Proactive authentication]. + +== Quarkus Security customization + +Quarkus Security is also highly customizable. You can customize the following core security components of Quarkus: + +* `HttpAuthenticationMechanism` +* `IdentityProvider` +* `SecurityidentityAugmentor` + +For more information about customizing Quarkus Security, including reactive security and how to register a security provider, see xref:security-customization.adoc[Security customization]. + +== References + +* xref:security-authorize-web-endpoints-reference.adoc[Authorization of web endpoints] \ No newline at end of file diff --git a/docs/src/main/asciidoc/security-authentication-mechanisms-concept.adoc b/docs/src/main/asciidoc/security-authentication-mechanisms-concept.adoc new file mode 100644 index 0000000000000..5ba8ecee7c2f5 --- /dev/null +++ b/docs/src/main/asciidoc/security-authentication-mechanisms-concept.adoc @@ -0,0 +1,336 @@ +[id="security-authentication-mechanisms-concept"] += Authentication mechanisms in Quarkus +include::_attributes.adoc[] +:categories: security,web + +The Quarkus Security framework supports multiple authentication mechanisms, which you can use to secure your applications. +Some of the supported authentication mechanisms are built into Quarkus and some require you to add an extension. +You can also combine authentication mechanisms. + +Before you choose an authentication mechanism for securing your Quarkus applications, review the information provided. + +== Built-in authentication support + +Quarkus Security provides the following built-in authentication mechanisms: + +* xref:security-basic-authentication-concept.adoc[Basic authentication] +* <> +* <> + +=== Basic authentication + +You can secure your Quarkus application endpoints with the built-in HTTP Basic authentication mechanism. For more information, see xref:security-basic-authentication-concept.adoc[Basic authentication]. + +[[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). + +To apply encryption, add the `quarkus.http.auth.session.encryption-key` property, and ensure that the value you set is at least 16 characters long. +This key is hashed 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. + +Single Page Application (SPA) typically wants to avoid redirects, which can be done by removing default page paths, as outlined in the following example: + +[source,properties] +---- +# 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= +---- + +The following properties can be used to configure form-based authentication: + +include::{generated-dir}/config/quarkus-vertx-http-config-group-form-auth-config.adoc[opts=optional, leveloffset=+1] + +[[mutual-tls]] +=== Mutual TLS authentication + +Quarkus provides mutual TLS (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, you can add new roles after checking a client certificate subject name, and so on. +For more information about customizing Quarkus `SecurityIdentity`, see xref:security-customization.adoc#security-identity-customization[SecurityIdentity customization] in the "Security customization" topic. + +== Other supported authentication mechanisms + +Quarkus Security also supports the following authentication mechanisms through extensions: + +* <> +* <> +* <> +* <> + +=== WebAuthn authentication + +https://webauthn.guide/[WebAuthn] is an authentication mechanism that replaces passwords. +When you write a service for registering new users, or logging them in, instead of asking for a password, you can use WebAuthn, which replaces the password. +For more information, see xref:security-webauthn.adoc[Secure a Quarkus application by using the WebAuthn authentication mechanism]. + + +=== OpenID Connect authentication + +OpenID Connect (OIDC) is an identity layer that works on top of the OAuth 2.0 protocol. OIDC enables client applications to verify the identity of a user based on the authentication performed by the OIDC provider and to retrieve basic information about that user. + +The Quarkus `quarkus-oidc` extension provides a reactive, interoperable, multitenant-enabled OIDC adapter that supports Bearer Token and Authorization Code Flow authentication mechanisms. +The Bearer Token mechanism extracts the token from the HTTP Authorization header. +The Authorization Code Flow mechanism redirects the user to an OIDC provider to authenticate the identity of the user. +After the user is redirected back to Quarkus, the mechanism completes the authentication process by exchanging the provided code that was granted for the ID, access, and refresh tokens. + +You can verify ID and access JWT tokens by using the refreshable JSON Web Key (JWK) set or you can introspect them remotely. +However, opaque (binary) tokens can only be introspected remotely. + +[NOTE] +==== +Using the Quarkus OIDC extension, both Bearer Token and Authorization Code Flow mechanisms use <> to represent JWT tokens as MicroProfile JWT `org.eclipse.microprofile.jwt.JsonWebToken`. +==== + +==== Additional Quarkus resources for OIDC authentication + +For more information about OIDC authentication and authorization methods you can use to secure your Quarkus applications, see the following detailed resources: + +[options="header"] +|==== +|OIDC topic |Quarkus information resource +|Bearer Token authentication mechanism|xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication] +|Authorization Code Flow authentication mechanism|xref:security-openid-connect-web-authentication.adoc[OpenID Connect (OIDC) authorization code flow mechanism] +|Multiple tenants that can support Bearer Token or Authorization Code Flow mechanisms|xref:security-openid-connect-multitenancy.adoc[Using OpenID Connect (OIDC) multi-tenancy] +|Using Keycloak to centralize authorization|xref:security-keycloak-authorization.adoc[Using OpenID Connect (OIDC) and Keycloak to centralize authorization] +|Configuring Keycloak programmatically|xref:security-keycloak-admin-client.adoc[Using the Keycloak admin client] +|==== + +[NOTE] +==== +* If you need to enable the Quarkus OIDC extension at runtime, set `quarkus.oidc.tenant-enabled=false` at build time and then re-enable it at runtime by using a system property. +For more information about managing the individual tenant configurations in multitenant OIDC deployments, see the _Disabling tenant configurations_ section in the xref:security-openid-connect-multitenancy.adoc#disable-tenant[Using OpenID Connect (OIDC) multi-tenancy] guide. +==== + +==== OpenID Connect client and filters + +The `quarkus-oidc-client` extension provides `OidcClient` for acquiring and refreshing access tokens from OpenID Connect and OAuth2 providers that support the following token grants: +* `client-credentials` +* `password` +* `refresh_token` + +The `quarkus-oidc-client-filter` extension requires the `quarkus-oidc-client` extension and provides JAX-RS `OidcClientRequestFilter`, which sets the access token acquired by `OidcClient` as the `Bearer` scheme value of the HTTP `Authorization` header. +This filter can be registered with MP RestClient implementations injected into the current Quarkus endpoint, but it is not related to the authentication requirements of this service endpoint. +For example, it can be a public endpoint, or it can be protected with mTLS. + +[IMPORTANT] +==== +In this scenario, you do not need to protect your Quarkus endpoint by using the Quarkus OpenID Connect adapter. +==== + +The `quarkus-oidc-token-propagation` extension requires the `quarkus-oidc` extension and provides JAX-RS `TokenCredentialRequestFilter`, which sets the OpenID Connect Bearer or Authorization Code Flow access token as the `Bearer` scheme value of the HTTP `Authorization` header. +This filter can be registered with MP RestClient implementations injected into the current Quarkus endpoint, which in turn must be protected by using the Quarkus OpenID Connect adapter. +This filter can be used to propagate the access token to the downstream services. + +For more information, see the xref:security-openid-connect-client.adoc[OpenID Connect client and token propagation quickstart] and xref:security-openid-connect-client-reference.adoc[OpenID Connect (OIDC) and OAuth2 client and filters reference] guides. + +[[smallrye-jwt]] +=== SmallRye JWT authentication + +The `quarkus-smallrye-jwt` extension provides a MicroProfile JSON Web Token (JWT) 1.2.1 implementation and multiple options to verify signed and encrypted `JWT` tokens and represents them as `org.eclipse.microprofile.jwt.JsonWebToken`. + +`quarkus-smallrye-jwt` is an alternative to the `quarkus-oidc` Bearer Token authentication mechanism, and verifies only `JWT` tokens by using either PEM keys or the refreshable `JWK` key set. +`quarkus-smallrye-jwt` also provides the JWT generation API, which you can use to easily create `signed`, `inner-signed`, and `encrypted` `JWT` tokens. + +For more information, see xref:security-jwt.adoc[Using SmallRye JWT role-based access control]. + +=== OAuth2 authentication + +`quarkus-elytron-security-oauth2` provides an alternative to the `quarkus-oidc` Bearer Token authentication mechanism. `quarkus-elytron-security-oauth2` is based on `Elytron` and is primarily intended for introspecting opaque tokens remotely. +For more information, see xref:security-oauth2.adoc[Using OAuth2]. + +[[oidc-jwt-oauth2-comparison]] + +== Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms + +Use the following information to help you to decide which authentication mechanism to use to secure your Quarkus applications: + +* `quarkus-oidc` requires an OpenID Connect provider such as Keycloak, which can be used to verify the Bearer tokens or authenticate the end users with the Authorization Code flow. +In both cases, `quarkus-oidc` requires a connection to the specified OpenID Connect provider. + +* If the user authentication requires Authorization Code flow or you need to support multiple tenants, use `quarkus-oidc`. +`quarkus-oidc` can also request user information by using both Authorization Code Flow and Bearer access tokens. + +* If your Bearer tokens must be verified, use `quarkus-oidc`, `quarkus-smallrye-jwt`, or `quarkus-elytron-security-oauth2`. + +* If your Bearer tokens are in a JWT format, you can use either of the three extensions. Both `quarkus-oidc` and `quarkus-smallrye-jwt` support refreshing the JsonWebKey (JWK) set when the OpenID Connect provider rotates the keys. +Therefore, if remote token introspection must be avoided or is unsupported by the providers, use `quarkus-oidc` or `quarkus-smallrye-jwt` for verifying JWT tokens. + +* If you need to introspect the JWT tokens remotely, you can use either `quarkus-oidc` or `quarkus-elytron-security-oauth2` because they support the verification of the opaque or binary tokens by using remote introspection. +`quarkus-smallrye-jwt` does not support the remote introspection of both opaque or JWT tokens but instead relies on the locally available keys that are usually retrieved from the OpenID Connect provider. + +* `quarkus-oidc` and `quarkus-smallrye-jwt` support the injecting of JWT and opaque tokens into the endpoint code. +Injected JWT tokens provide more information about the user. All extensions can have the tokens injected as `Principal`. + +* `quarkus-smallrye-jwt` supports more key formats than `quarkus-oidc`. `quarkus-oidc` uses only the JWK-formatted keys that are part of a JWK set, whereas `quarkus-smallrye-jwt` supports PEM keys. + +* `quarkus-smallrye-jwt` handles locally signed, inner-signed-and-encrypted, and encrypted tokens. +While `quarkus-oidc` and `quarkus-elytron-security-oauth2` can also verify such tokens but treats them as opaque tokens and verifies them through remote introspection. + +* If you need a lightweight library for the remote introspection of opaque or JWT tokens, use `quarkus-elytron-security-oauth2`. + +[NOTE] +==== +Your decision to choose whether to use opaque or JWT token format will be driven by architectural considerations. +Opaque tokens tend to be much shorter than JWT tokens but need most of the token-associated state to be maintained in the provider database. +Opaque tokens are effectively database pointers. +JWT tokens are significantly longer than the opaque tokens but the providers are effectively delegating storing most of the token-associated state to the client by storing it as the token claims and either signing or encrypting them. +==== + +The following table provides a summary of the options for each authentication mechanism: + +|=== +| | quarkus-oidc| quarkus-smallrye-jwt | quarkus-elytron-security-oauth2 + +|Requires Bearer JWT verification +|Local verification or introspection +|Local verification +|Introspection +|Requires Bearer opaque token verification +|Introspection +|No +|Introspection +|Refreshing `JsonWebKey` set for verifying JWT tokens +|Yes +|Yes +|No +|Represent token as `Principal` +|Yes +|Yes +|Yes +|Inject JWT as MP JSON Web Token (JWT) +|Yes +|Yes +|No +|Authorization Code Flow +|Yes +|No +|No +|Multi-tenancy +|Yes +|No +|No +|User info support +|Yes +|No +|No +|PEM key format support +|No +|Yes +|No +|SecretKey support +|No +|In JSON Web Key (JWK) format +|No +|Inner-signed and encrypted or encrypted tokens +|Introspection +|Local verification +|Introspection +|Custom token verification +|No +|With injected JWT parser +|No +|Accept JWT as a cookie +|No +|Yes +|No +|=== + +== Combining authentication mechanisms + +If the user credentials are provided by different sources, you can combine authentication mechanisms. +For example, you can combine built-in `Basic` and `quarkus-oidc` `Bearer` authentication mechanisms. + +[IMPORTANT] +==== +You cannot combine the `quarkus-oidc` `Bearer` and `smallrye-jwt` authentication mechanisms because both mechanisms attempt to verify the token extracted from the HTTP `Authorization Bearer` scheme. +==== + +=== Path-specific authentication mechanisms + +The following configuration example demonstrates how you can enforce a single selectable authentication mechanism for a given request path: + +[source,properties] +---- +quarkus.http.auth.permission.basic-or-bearer.paths=/service +quarkus.http.auth.permission.basic-or-bearer.policy=authenticated + +quarkus.http.auth.permission.basic.paths=/basic-only +quarkus.http.auth.permission.basic.policy=authenticated +quarkus.http.auth.permission.basic.auth-mechanism=basic + +quarkus.http.auth.permission.bearer.paths=/bearer-only +quarkus.http.auth.permission.bearer.policy=authenticated +quarkus.http.auth.permission.bearer.auth-mechanism=bearer +---- + +Ensure that the value of the `auth-mechanism` property matches the authentication scheme supported by `HttpAuthenticationMechanism`, for example, `basic`, `bearer`, or `form`. + +== Proactive authentication + +Proactive authentication is enabled in Quarkus by default. 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. +For more information, see xref:security-proactive-authentication-concept.adoc[Proactive authentication]. \ No newline at end of file diff --git a/docs/src/main/asciidoc/security-authorize-web-endpoints-reference.adoc b/docs/src/main/asciidoc/security-authorize-web-endpoints-reference.adoc index 488954932d6df..af9de1cc4851d 100644 --- a/docs/src/main/asciidoc/security-authorize-web-endpoints-reference.adoc +++ b/docs/src/main/asciidoc/security-authorize-web-endpoints-reference.adoc @@ -301,7 +301,7 @@ public class SubjectExposingResource { <4> The call to obtain the user principal returns null if the caller is unauthenticated and non-null if the caller is authenticated. <5> The `/subject/denied` endpoint declares the `@DenyAll` annotation, thus disallowing all direct access to it as a REST method, regardless of the user calling it. The method is still invokable internally by other methods in this class. -CAUTION: Please refer to the xref:security-built-in-authentication-support-concept.adoc#proactive-authentication[Proactive Authentication] section of the Built-In Authentication Support guide if you plan to use standard security annotations on the IO thread. +CAUTION: If you plan to use standard security annotations on the IO thread, review the information in xref:security-proactive-authentication-concept.adoc[Proactive Authentication]. The `@RolesAllowed` annotation value supports <> including default values and nested Property Expressions. Configuration properties used with the annotation are resolved at runtime. diff --git a/docs/src/main/asciidoc/security-basic-authentication-concept.adoc b/docs/src/main/asciidoc/security-basic-authentication-concept.adoc index 8fe22c7f2d4dd..744bd28812e6c 100644 --- a/docs/src/main/asciidoc/security-basic-authentication-concept.adoc +++ b/docs/src/main/asciidoc/security-basic-authentication-concept.adoc @@ -1,5 +1,5 @@ [id="security-basic-authentication-concept"] -= Basic Authentication += Basic authentication include::_attributes.adoc[] :categories: security,web diff --git a/docs/src/main/asciidoc/security-basic-authentication-howto.adoc b/docs/src/main/asciidoc/security-basic-authentication-howto.adoc index 20349b9695a91..f35eeabc258d2 100644 --- a/docs/src/main/asciidoc/security-basic-authentication-howto.adoc +++ b/docs/src/main/asciidoc/security-basic-authentication-howto.adoc @@ -4,9 +4,9 @@ include::_attributes.adoc[] :categories: security Enable Basic authentication for your Quarkus project and allow users to authenticate with a username and password. - + == Prerequisites - + * You have installed at least one extension that provides an `IdentityProvider` based on username and password, such as xref:security-jdbc.adoc[Elytron JDBC]. == Procedure @@ -17,7 +17,7 @@ Enable Basic authentication for your Quarkus project and allow users to authenti ---- quarkus.http.auth.basic=true ---- - + An easy way to configure the required user credentials for Basic authentication to work is to configure the user name, secret, and roles directly in the `application.properties` file. .Example of Basic authentication properties @@ -42,9 +42,9 @@ Configuring user names, secrets, and roles in the `application.properties` file ==== To walk through how to configure Basic authentication together with JPA for storing user credentials in a database, see the xref:security-basic-authentication-tutorial.adoc[Secure a Quarkus application with Basic authentication] tutorial. - -== Additional resources + +== References * xref:security-overview-concept.adoc[Quarkus Security overview] -* xref:security-overview-concept.adoc#identity-providers[Security Identity Providers] +* xref:security-identity-providers.adoc[Identity Providers] * xref:security-testing.adoc#configuring-user-information[Configuring User Information in application.properties] diff --git a/docs/src/main/asciidoc/security-basic-authentication-tutorial.adoc b/docs/src/main/asciidoc/security-basic-authentication-tutorial.adoc index 8a037b5054775..a6cbfdec3a42f 100644 --- a/docs/src/main/asciidoc/security-basic-authentication-tutorial.adoc +++ b/docs/src/main/asciidoc/security-basic-authentication-tutorial.adoc @@ -1,9 +1,9 @@ [id="security-basic-authentication-tutorial"] = Secure a Quarkus application with Basic authentication include::_attributes.adoc[] -:categories: security, getting-started +:categories: security,getting-started -Secure your Quarkus application endpoints by combining xref:security-built-in-authentication-support-concept.adoc#basic-auth[Quarkus built-in basic HTTP authentication] with the JPA identity provider to enable role-based access control (RBAC). +Secure your Quarkus application endpoints by combining the built-in Quarkus xref:security-basic-authentication-concept.adoc[Basic authentication] with the JPA identity provider to enable role-based access control (RBAC). The JPA `IdentityProvider` creates a `SecurityIdentity` instance, which is used during user authentication to verify and authorize access requests making your Quarkus application secure. This tutorial prepares you for implementing more advanced security mechanisms in Quarkus, for example, how to use the OpenID Connect (OIDC) authentication mechanism. @@ -211,14 +211,14 @@ The `security-jpa` extension initializes only if there is a single entity annota === Configure the application -. Enable xref:security-built-in-authentication-support-concept.adoc#basic-auth[Quarkus built-in basic HTTP authentication] by setting the `quarkus.http.auth.basic` property to `true`: +. Enable the built-in Quarkus xref:security-basic-authentication-concept.adoc[Basic authentication] by setting the `quarkus.http.auth.basic` property to `true`: + `quarkus.http.auth.basic`=true` + [NOTE] ==== -When secure access is required and no other authentication mechanisms are enabled, xref:security-built-in-authentication-support-concept.adoc#basic-auth[Quarkus built-in basic HTTP authentication] is the fallback authentication mechanism. -Therefore, in this tutorial, you do not need to set the property `quarkus.http.auth.basic=true`. +When secure access is required and no other authentication mechanisms are enabled, the built-in xref:security-basic-authentication-concept.adoc[Basic authentication] of Quarkus is the fallback authentication mechanism. +Therefore, in this tutorial, you do not need to set the property `quarkus.http.auth.basic` to `true`. ==== + . Configure at least one data source so that the `security-jpa` extension can access your database. @@ -583,7 +583,7 @@ For applications running in production, do not store passwords in plain text. == What's next Congratulations! -You have learned how to create and test a secure Quarkus application by combining the xref:security-built-in-authentication-support-concept.adoc#basic-auth[Quarkus built-in basic HTTP authentication] with the JPA identity provider. +You have learned how to create and test a secure Quarkus application by combining the built-in xref:security-basic-authentication-concept.adoc[Basic authentication] in Quarkus with the JPA identity provider. After you have completed this tutorial, explore some of the more advanced security mechanisms in Quarkus. Use the following information to learn how you can securely use `OpenID Connect` to provide secure single sign-on access to your Quarkus endpoints: diff --git a/docs/src/main/asciidoc/security-built-in-authentication-support-concept.adoc b/docs/src/main/asciidoc/security-built-in-authentication-support-concept.adoc deleted file mode 100644 index ecc879b17d7d5..0000000000000 --- a/docs/src/main/asciidoc/security-built-in-authentication-support-concept.adoc +++ /dev/null @@ -1,256 +0,0 @@ -//// -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 -//// -[id="security-built-in-authentication-support-concept"] -= Built-In Authentication Support -include::_attributes.adoc[] -:categories: security,web - -The following section describes the Quarkus built-in authentication mechanisms for HTTP based FORM, BASIC, and Mutual TLS authentication. Proactive authentication is also described. - -include::security-basic-authentication-concept.adoc[leveloffset=+1] - -// include::security-enabling-basic-auth-howto.adoc[leveloffset=+2] -// How to I convert this how-to into a guide that appears alongside all the other guides? - - -[[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. - -Single Page Application (SPA) typically wants to avoid redirects, this can be done by removing default page paths: - -[source,properties] ----- -# 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= ----- - -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, and so on. -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 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 getDeferredIdentity();` method. You can then subscribe to the resulting `Uni` and will be notified -when authentication is complete and the identity is available. - -NOTE: It's still possible to access the `SecurityIdentity` synchronously with `public SecurityIdentity getIdentity()` -in the xref:resteasy-reactive.adoc[RESTEasy Reactive] from endpoints annotated with `@RolesAllowed`, `@Authenticated`, -or with respective configuration authorization checks as authentication has already happened. The same is also valid -for the xref:reactive-routes.adoc[Reactive routes] if a route response is synchronous. - -xref:security-authorization.adoc#standard-security-annotations[Standard security annotations] on CDI beans are not supported on IO thread if a non-void secured method returns a value synchronously and proactive authentication is disabled, as they need to access the `SecurityIdentity`. -In the example below, we have defined `HelloResource` and `HelloService`. It's easy to see that any GET request to `/hello` will run on IO thread and throw `BlockingOperationNotAllowedException` exception. -There is more than one way to fix the example: - -* switch to a worker thread (annotate `hello` endpoint with `@Blocking`) -* change `sayHello` method return type (use reactive or asynchronous data type) -* arguably the safest way is to move `@RolesAllowed` annotation to the endpoint, as accessing `SecurityIdentity` from endpoint methods is never the blocking operation - -[source,java] ----- -import javax.annotation.security.PermitAll; -import javax.inject.Inject; -import javax.ws.rs.GET; -import javax.ws.rs.Path; - -import io.smallrye.mutiny.Uni; - -@Path("/hello") -@PermitAll -public class HelloResource { - - @Inject - HelloService helloService; - - @GET - public Uni hello() { - return Uni.createFrom().item(helloService.sayHello()); - } - -} ----- - -[source,java] ----- -import javax.annotation.security.RolesAllowed; -import javax.enterprise.context.ApplicationScoped; - -@ApplicationScoped -public class HelloService { - - @RolesAllowed("admin") - public String sayHello() { - return "Hello"; - } - -} ----- - - -=== How to customize authentication exception responses - -You can 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 { - - @Context - UriInfo uriInfo; - - @Override - public Response toResponse(AuthenticationFailedException exception) { - return Response.status(401).header("WWW-Authenticate", "Basic realm=\"Quarkus\"").build(); - } -} ----- - -CAUTION: Some HTTP authentication mechanisms need to handle authentication exceptions themselves in order to create a correct authentication challenge. -For example, `io.quarkus.oidc.runtime.CodeAuthenticationMechanism` which manages OpenId Connect authorization code flow authentication, needs to build a correct redirect URL, cookies, etc. -For that reason, using custom exception mappers to customize authentication exceptions thrown by such mechanisms is not recommended. -In such cases, a safer way to customize authentication exceptions is to make sure the proactive authentication is not disabled and use Vert.x HTTP route failure handlers, as events come to the handler with the correct response status and headers. -To that end, the only thing that needs to be done is to customize the response like this: - -[source,java] ----- -package io.quarkus.it.keycloak; - -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.event.Observes; - -import io.quarkus.security.AuthenticationFailedException; -import io.vertx.core.Handler; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.RoutingContext; - -@ApplicationScoped -public class AuthenticationFailedExceptionHandler { - - public void init(@Observes Router router) { - router.route().failureHandler(new Handler() { - @Override - public void handle(RoutingContext event) { - if (event.failure() instanceof AuthenticationFailedException) { - event.response().end("CUSTOMIZED_RESPONSE"); - } else { - event.next(); - } - } - }); - } -} ----- - -== References - -* xref:security-overview-concept.adoc[Quarkus Security overview] diff --git a/docs/src/main/asciidoc/security-customization.adoc b/docs/src/main/asciidoc/security-customization.adoc index 03be170603fc7..053ac4e3e6847 100644 --- a/docs/src/main/asciidoc/security-customization.adoc +++ b/docs/src/main/asciidoc/security-customization.adoc @@ -32,7 +32,7 @@ implementation("io.quarkus:quarkus-security") == HttpAuthenticationMechanism Customization One can customize `HttpAuthenticationMechanism` by registering a CDI implementation bean. -In the example below the custom authenticator delegates to `JWTAuthMechanism` provided by `quarkus-smallrye-jwt`: +In the example below the custom authenticator delegates to `JWTAuthMechanism` provided by `quarkus-smallrye-jwt`: [source,java] ---- @@ -48,7 +48,7 @@ public class CustomAwareJWTAuthMechanism implements HttpAuthenticationMechanism @Override public Uni authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) { - // do some custom action and delegate + // do some custom action and delegate return delegate.authenticate(context, identityProviderManager); } @@ -175,7 +175,7 @@ public class RolesAugmentor implements SecurityIdentityAugmentor { } ---- -Here is another example showing how to use the client certificate available in the current xref:security-built-in-authentication-support-concept.adoc#mutual-tls[Mutual TLS] request to add more roles: +Here is another example showing how to use the client certificate available in the current xref:security-authentication-mechanisms-concept.adoc#mutual-TLS-authentication[mutual TLS (mTLS) authentication] request to add more roles: [source,java] ---- diff --git a/docs/src/main/asciidoc/security-identity-providers-concept.adoc b/docs/src/main/asciidoc/security-identity-providers-concept.adoc new file mode 100644 index 0000000000000..865b84736cf4d --- /dev/null +++ b/docs/src/main/asciidoc/security-identity-providers-concept.adoc @@ -0,0 +1,27 @@ +//// +This document 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 +//// +[id="security-identity-providers-concept"] += Identity providers +include::_attributes.adoc[] +:categories: security +In the Quarkus Security framework, identity providers play a key role in authentication and authorization, providing services for storing and verifying user identities. +The JPA `IdentityProvider` creates a `SecurityIdentity` instance used during user authentication to verify and authorize access requests, making your Quarkus application secure. +[[identity-providers]] + +`IdentityProvider` converts the authentication credentials provided by `HttpAuthenticationMechanism` to a `SecurityIdentity` instance. + +Some extensions, for example, `OIDC`, `OAuth2`, and `SmallRye JWT` have inline `IdentityProvider` implementations specific to the supported authentication flow. +For example, `quarkus-oidc` uses its own `IdentityProvider` to convert a token to a `SecurityIdentity` instance. + +If you use Basic or form-based authentication, you must add an `IdentityProvider` instance that can convert a username and password to a `SecurityIdentity` instance. + +To get started with security in Quarkus, we recommend you combine the Quarkus built-in Basic HTTP authentication with the JPA identity provider to enable role-based access control (RBAC). + +* For more information about Basic authentication or form-based authentication, see the following resources: +** xref:security-basic-authentication-tutorial.adoc[Secure a Quarkus application with Basic authentication] +** xref:security-authentication-mechanisms-concept.adoc#form-based-authentication[Form-based authentication] +** xref:security-jdbc.adoc[Using security with JDBC] +** xref:security-ldap.adoc[Using security with an LDAP realm] diff --git a/docs/src/main/asciidoc/security-jwt.adoc b/docs/src/main/asciidoc/security-jwt.adoc index daae464f8ff2a..73b707568761d 100644 --- a/docs/src/main/asciidoc/security-jwt.adoc +++ b/docs/src/main/asciidoc/security-jwt.adoc @@ -968,7 +968,7 @@ quarkus.log.category."io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator".min-l === Proactive Authentication -If you'd like to skip the token verification when the public endpoint methods are invoked then please disable the xref:security-built-in-authentication-support-concept.adoc#proactive-authentication[proactive authentication]. +If you'd like to skip the token verification when the public endpoint methods are invoked then please disable the xref:security-proactive-authentication-concept.adoc[Proactive authentication]. Note that you can't access the injected `JsonWebToken` in the public methods if the token verification has not been done. @@ -1080,5 +1080,5 @@ SmallRye JWT provides more properties which can be used to customize the token p * link:https://tools.ietf.org/html/rfc7516[JSON Web Encryption] * link:https://tools.ietf.org/html/rfc7518[JSON Web Algorithms] * xref:security-jwt-build.adoc[Sign and encrypt JWT tokens with SmallRye JWT Build] -* xref:security-overview-concept.adoc#oidc-jwt-oauth2-comparison[Summary of Quarkus OIDC, JWT and OAuth2 features] +* xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] * xref:security-overview-concept.adoc[Quarkus Security overview] diff --git a/docs/src/main/asciidoc/security-oidc-bearer-authentication-concept.adoc b/docs/src/main/asciidoc/security-oidc-bearer-authentication-concept.adoc index 97263c423bcd0..0afe0de765411 100644 --- a/docs/src/main/asciidoc/security-oidc-bearer-authentication-concept.adoc +++ b/docs/src/main/asciidoc/security-oidc-bearer-authentication-concept.adoc @@ -915,6 +915,7 @@ Note Quarkus `web-app` applications always require `quarkus.oidc.client-id` prop * xref:security-openid-connect-client-reference.adoc[OpenID Connect and OAuth2 Client and Filters Reference Guide] * xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] * xref:security-jwt-build.adoc[Sign and encrypt JWT tokens with SmallRye JWT Build] -* xref:security-overview-concept.adoc#oidc-jwt-oauth2-comparison[Summary of Quarkus OIDC, JWT and OAuth2 features] -* xref:security-overview-concept.adoc[Quarkus Security] -* xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] +* xref:security-authentication-mechanisms.adoc#oidc-jwt-oauth2-comparison[Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms] +* xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] +* xref:security-overview-concept.adoc[Quarkus Security overview] +* xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] \ No newline at end of file diff --git a/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc b/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc index 475e9abec9a05..7c6a662c638a4 100644 --- a/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc +++ b/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc @@ -23,7 +23,8 @@ include::{generated-dir}/config/quarkus-oidc.adoc[opts=optional, leveloffset=+1] * xref:security-openid-connect-client-reference.adoc[OpenID Connect and OAuth2 Client and Filters Reference Guide] // * xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] // * xref:security-jwt-build.adoc[Sign and encrypt JWT tokens with SmallRye JWT Build] -// * xref:security-overview-concept.adoc#oidc-jwt-oauth2-comparison[Summary of Quarkus OIDC, JWT and OAuth2 features] +* xref:security-authentication-mechanisms.adoc#oidc-jwt-oauth2-comparison[Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms] +* xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] * xref:security-overview-concept.adoc[Quarkus Security] // * xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] // TASK - Select some references and eliminate the rest. diff --git a/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc b/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc index 6333e05dadf6f..e6bdffb49e478 100644 --- a/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc @@ -586,8 +586,7 @@ annotation per tenant ID other than default: [NOTE] ==== -Proactive HTTP authentication needs to be disabled (`quarkus.http.auth.proactive=false`) for this to work. See -xref:security-built-in-authentication-support-concept.adoc#proactive-authentication[Proactive Authentication] section for further details. +Proactive HTTP authentication must be disabled (`quarkus.http.auth.proactive=false`) for this to work. For more information, see xref:security-proactive-authentication-concept.adoc[Proactive authentication]. ==== [source,java] diff --git a/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc b/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc index 5e2077ff40360..a74c361b85b67 100644 --- a/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc @@ -186,12 +186,13 @@ quarkus.http.auth.permission.authenticated.policy=authenticated This is the simplest configuration you can have when enabling authentication to your application. -The `quarkus.oidc.client-id` property references the `client_id` issued by the OpenID Connect Provider and the `quarkus.oidc.credentials.secret` property sets the client secret. +The `quarkus.oidc.client-id` property references the `client_id` issued by the OIDC provider and the `quarkus.oidc.credentials.secret` property sets the client secret. -The `quarkus.oidc.application-type` property is set to `web-app` in order to tell Quarkus that you want to enable the OpenID Connect Authorization Code Flow, so that your users are redirected to the OpenID Connect Provider to authenticate. +When the `quarkus.oidc.application-type` property is set to `web-app`, this intructs Quarkus to enable the OIDC Authorization Code Flow, so that your users get redirected to the OIDC provider to authenticate. -For last, the `quarkus.http.auth.permission.authenticated` permission is set to tell Quarkus about the paths you want to protect. In this case, -all paths are being protected by a policy that ensures that only `authenticated` users are allowed to access. For more details check xref:security-authorize-web-endpoints-reference.adoc[Security Authorization Guide]. +The `quarkus.http.auth.permission.authenticated` property tells Quarkus about the paths that you want to protect. +In the example provided, all paths are being protected by a policy that ensures that only `authenticated` users are allowed to access. +For more information, see xref:security-authorize-web-endpoints-reference.adoc[Authorization of web endpoints]. === Starting and Configuring the Keycloak Server @@ -361,7 +362,7 @@ If only the access token contains the roles and this access token is not meant t If UserInfo is the source of the roles then set `quarkus.oidc.authentication.user-info-required=true` and `quarkus.oidc.roles.source=userinfo`, and if needed, `quarkus.oidc.roles.role-claim-path`. -Additionally, a custom `SecurityIdentityAugmentor` can also be used to add the roles as documented xref:security-overview-concept.adoc#security-identity-customization[here]. +Additionally, a custom `SecurityIdentityAugmentor` can also be used to add the roles. For more information, see xref:security-customization.adoc#security-identity-customization[SecurityIdentity customization]. [[token-verification-introspection]] === Token Verification And Introspection @@ -1444,7 +1445,8 @@ In such cases HTTP `401` will be returned by default. However, you can instead r quarkus.oidc.authentication.error-path=/error ---- -It has to start from a forward slash and be relative to the current endpoint's base URI. For example, if it is set as '/error' and the current request URI is `https://localhost:8080/callback?error=invalid_scope` then a final redirect will be made to `https://localhost:8080/error?error=invalid_scope`. +It has to start from a forward slash and be relative to the base URI of the current endpoint. +For example, if it is set as '/error' and the current request URI is `https://localhost:8080/callback?error=invalid_scope` then a final redirect will be made to `https://localhost:8080/error?error=invalid_scope`. It is important that this error endpoint is a public resource to avoid the user redirected to this page be authenticated again. @@ -1457,5 +1459,6 @@ It is important that this error endpoint is a public resource to avoid the user * xref:security-openid-connect-providers.adoc[Well Known OpenID Connect providers]. * xref:security-openid-connect-client-reference.adoc[OpenID Connect and OAuth2 Client and Filters Reference Guide] * xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] -* xref:security-overview-concept.adoc#oidc-jwt-oauth2-comparison[Summary of Quarkus OIDC, JWT and OAuth2 features] +* xref:security-authentication-mechanisms.adoc#oidc-jwt-oauth2-comparison[Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms] +* xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] * xref:security-overview-concept.adoc[Quarkus Security overview] diff --git a/docs/src/main/asciidoc/security-overview-concept.adoc b/docs/src/main/asciidoc/security-overview-concept.adoc index 6cde185a925dc..59757dabd64ac 100644 --- a/docs/src/main/asciidoc/security-overview-concept.adoc +++ b/docs/src/main/asciidoc/security-overview-concept.adoc @@ -5,322 +5,78 @@ include::_attributes.adoc[] Quarkus Security is a framework that provides the architecture, multiple authentication and authorization mechanisms, and other tools for you to build secure and production-quality Java applications. -== Getting started with Quarkus Security - -Before you start building security into your Quarkus applications, review the overview information to learn about the Quarkus Security architecture and the different authentication and authorization mechanisms that Quarkus supports. - -To get started with security in Quarkus, we recommend that you first combine the Quarkus built-in xref:security-basic-authentication-concept.adoc[Basic HTTP authentication] with the JPA identity provider to enable role-based access control (RBAC). -Complete the steps in the xref:security-basic-authentication-tutorial.adoc[Secure a Quarkus application with Basic authentication] tutorial. -After you have successfully secured your Quarkus application with basic HTTP authentication, you can increase the security further by adding more advanced authentication mechanisms, for example, OpenID Connect (OIDC) authentication. - -== Security architecture - -The `HttpAuthenticationMechanism` interface is the main entry mechanism for securing HTTP applications in Quarkus. - -Quarkus Security uses `HttpAuthenticationMechanism` to extract the authentication credentials from the HTTP request and delegates them to `IdentityProvider` to convert the credentials to `SecurityIdentity`. -For example, the credentials can come from the `Authorization` header, client HTTPS certificates, or cookies. - -`IdentityProvider` verifies the authentication credentials and maps them to `SecurityIdentity`, which has the username, roles, original authentication credentials, and other attributes. - -For every authenticated resource, you can inject a `SecurityIdentity` instance to get the authenticated identity information. - -In other contexts, it is possible to have other parallel representations of the same information or parts of it, for example, `SecurityContext` -for JAX-RS or `JsonWebToken` for JSON Web Tokens (JWT). - -== Authentication mechanisms - -Quarkus supports multiple authentication mechanisms - -=== Basic and Form HTTP authentication - -xref:security-basic-authentication-concept.adoc[Basic HTTP Authentication] and xref:security-built-in-authentication-support-concept.adoc#form-auth[Form HTTP authentication] are the core authentication mechanisms supported in Quarkus. - -=== WebAuthn authentication - -https://webauthn.guide/[WebAuthn] is an authentication mechanism that replaces passwords. -When you write a service for registering new users, or logging them in, instead of asking for a password, you can use WebAuthn, which replaces the password. -For more information, see xref:security-webauthn.adoc[Secure a Quarkus application by using the WebAuthn authentication mechanism]. - -=== Mutual TLS (mTLS) authentication - -Quarkus provides mutual TLS (mTLS) authentication so that you can authenticate users based on their X.509 certificates. -For more information, see xref:security-built-in-authentication-support-concept.adoc#mutual-tls[mutual TLS authentication]. - -=== OpenID Connect authentication - -OpenID Connect (OIDC) is an identity layer that works on top of the OAuth 2.0 protocol. OIDC enables client applications to verify the identity of a user based on the authentication performed by the OIDC provider and to retrieve basic information about that user. - -The Quarkus `quarkus-oidc` extension provides a reactive, interoperable, multitenant-enabled OIDC adapter that supports Bearer Token and Authorization Code Flow authentication mechanisms. -The Bearer Token mechanism extracts the token from the HTTP Authorization header. -The Authorization Code Flow mechanism redirects the user to an OIDC provider to authenticate the identity of the user. -After the user is redirected back to Quarkus, the mechanism completes the authentication process by exchanging the provided code that was granted for the ID, access, and refresh tokens. - -You can verify ID and access JWT tokens by using the refreshable JSON Web Key (JWK) set or you can introspect them remotely. -However, opaque (binary) tokens can only be introspected remotely. - -[NOTE] -==== -Using the Quarkus OIDC extension, both Bearer Token and Authorization Code Flow mechanisms use <> to represent JWT tokens as MicroProfile JWT `org.eclipse.microprofile.jwt.JsonWebToken`. -==== - -==== Additional Quarkus resources for OIDC authentication - -For more information about OIDC authentication and authorization methods you can use to secure your Quarkus applications, see the following detailed resources: - -[options="header"] -|==== -|OIDC topic |Quarkus information resource -|Bearer Token authentication mechanism|xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication] -|Authorization Code Flow authentication mechanism|xref:security-openid-connect-web-authentication.adoc[OpenID Connect (OIDC) authorization code flow mechanism] -|Multiple tenants that can support Bearer Token or Authorization Code Flow mechanisms|xref:security-openid-connect-multitenancy.adoc[Using OpenID Connect (OIDC) multi-tenancy] -|Using Keycloak to centralize authorization|xref:security-keycloak-authorization.adoc[Using OpenID Connect (OIDC) and Keycloak to centralize authorization] -|Configuring Keycloak programmatically|xref:security-keycloak-admin-client.adoc[Using the Keycloak admin client] -|==== - -[NOTE] -==== -* If you need to enable the Quarkus OIDC extension at runtime, set `quarkus.oidc.tenant-enabled=false` at build time and then re-enable it at runtime by using a system property. -For more information about managing the individual tenant configurations in multitenant OIDC deployments, see the _Disabling tenant configurations_ section in the xref:security-openid-connect-multitenancy.adoc#disable-tenant[Using OpenID Connect (OIDC) multi-tenancy] guide. -==== - -=== OpenID Connect client and filters - -The `quarkus-oidc-client` extension provides `OidcClient` for acquiring and refreshing access tokens from OpenID Connect and OAuth2 providers that support the following token grants: -* `client-credentials` -* `password` -* `refresh_token` - -The `quarkus-oidc-client-filter` extension requires the `quarkus-oidc-client` extension and provides JAX-RS `OidcClientRequestFilter`, which sets the access token acquired by `OidcClient` as the `Bearer` scheme value of the HTTP `Authorization` header. -This filter can be registered with MP RestClient implementations injected into the current Quarkus endpoint, but it is not related to the authentication requirements of this service endpoint. -For example, it can be a public endpoint, or it can be protected with mTLS. - -[IMPORTANT] -==== -In this scenario, you do not need to protect your Quarkus endpoint by using the Quarkus OpenID Connect adapter. -==== - -The `quarkus-oidc-token-propagation` extension requires the `quarkus-oidc` extension and provides JAX-RS `TokenCredentialRequestFilter`, which sets the OpenID Connect Bearer or Authorization Code Flow access token as the `Bearer` scheme value of the HTTP `Authorization` header. -This filter can be registered with MP RestClient implementations injected into the current Quarkus endpoint, which in turn must be protected by using the Quarkus OpenID Connect adapter. -This filter can be used to propagate the access token to the downstream services. - -For more information, see the xref:security-openid-connect-client.adoc[OpenID Connect client and token propagation quickstart] and xref:security-openid-connect-client-reference.adoc[OpenID Connect (OIDC) and OAuth2 client and filters reference] guides. - -[[smallrye-jwt]] -=== SmallRye JWT authentication - -The `quarkus-smallrye-jwt` extension provides a MicroProfile JSON Web Token (JWT) 1.2.1 implementation and multiple options to verify signed and encrypted `JWT` tokens and represents them as `org.eclipse.microprofile.jwt.JsonWebToken`. - -`quarkus-smallrye-jwt` is an alternative to the `quarkus-oidc` Bearer Token authentication mechanism, and verifies only `JWT` tokens by using either PEM keys or the refreshable `JWK` key set. -`quarkus-smallrye-jwt` also provides the JWT generation API, which you can use to easily create `signed`, `inner-signed`, and `encrypted` `JWT` tokens. - -For more information, see xref:security-jwt.adoc[Using SmallRye JWT role-based access control]. +Before you start building security into your Quarkus applications, learn about the xref:security-architecture-concept.adoc[Quarkus Security architecture] and the different authentication mechanisms and features that you can use. -=== OAuth2 authentication +== Key features of Quarkus Security -`quarkus-elytron-security-oauth2` provides an alternative to the `quarkus-oidc` Bearer Token authentication mechanism. `quarkus-elytron-security-oauth2` is based on `Elytron` and is primarily intended for introspecting opaque tokens remotely. -For more information, see xref:security-oauth2.adoc[Using OAuth2]. +The Quarkus Security framework provides built-in security mechanisms for Basic, form-based, and mutual TLS (mTLS) authentication. +You can also integrate Quarkus with several well-known security xref:security-authentication-mechanisms-concept.adoc#other-supported-authentication-mechanisms[authentication mechanisms] and protocols. -[[oidc-jwt-oauth2-comparison]] -=== Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms +{project-name} also includes built-in security to allow for role-based Access control (RBAC) based on the common security annotations @RolesAllowed, @DenyAll, @PermitAll on REST endpoints and CDI beans. +For more information, see xref:security-authorize-web-endpoints-reference.adoc[Authorization of web endpoints]. -Use the following information to help you to decide which authentication mechanism to use to secure your Quarkus applications: +Quarkus Security also supports the following features: -* `quarkus-oidc` requires an OpenID Connect provider such as Keycloak, which can be used to verify the Bearer tokens or authenticate the end users with the Authorization Code flow. -In both cases, `quarkus-oidc` requires a connection to the specified OpenID Connect provider. +* xref:security-proactive-authentication-concept.adoc[Proactive authentication] +* xref:security-identity-providers-concept.adoc[Identity providers] +* xref:http-reference.adoc#ssl[Secure connections with SSL/TLS] +* <> +* <> +* <> +* <> +* <> +* <> +* <> -* If the user authentication requires Authorization Code flow or you need to support multiple tenants, use `quarkus-oidc`. -`quarkus-oidc` can also request user information by using both Authorization Code Flow and Bearer access tokens. +Quarkus Security is also highly customizable. For more information, see xref:security-customization.adoc[Security customization]. -* If your Bearer tokens must be verified, use `quarkus-oidc`, `quarkus-smallrye-jwt`, or `quarkus-elytron-security-oauth2`. - -* If your Bearer tokens are in a JWT format, you can use either of the three extensions. Both `quarkus-oidc` and `quarkus-smallrye-jwt` support refreshing the JsonWebKey (JWK) set when the OpenID Connect provider rotates the keys. -Therefore, if remote token introspection must be avoided or is unsupported by the providers, use `quarkus-oidc` or `quarkus-smallrye-jwt` for verifying JWT tokens. - -* If you need to introspect the JWT tokens remotely, you can use either `quarkus-oidc` or `quarkus-elytron-security-oauth2` because they support the verification of the opaque or binary tokens by using remote introspection. -`quarkus-smallrye-jwt` does not support the remote introspection of both opaque or JWT tokens but instead relies on the locally available keys that are usually retrieved from the OpenID Connect provider. - -* `quarkus-oidc` and `quarkus-smallrye-jwt` support the injecting of JWT and opaque tokens into the endpoint code. -Injected JWT tokens provide more information about the user. All extensions can have the tokens injected as `Principal`. - -* `quarkus-smallrye-jwt` supports more key formats than `quarkus-oidc`. `quarkus-oidc` uses only the JWK-formatted keys that are part of a JWK set, whereas `quarkus-smallrye-jwt` supports PEM keys. - -* `quarkus-smallrye-jwt` handles locally signed, inner-signed-and-encrypted, and encrypted tokens. -While `quarkus-oidc` and `quarkus-elytron-security-oauth2` can also verify such tokens but treats them as opaque tokens and verifies them through remote introspection. - -* If you need a lightweight library for the remote introspection of opaque or JWT tokens, use `quarkus-elytron-security-oauth2`. - -[NOTE] -==== -Your decision to choose whether to use opaque or JWT token format will be driven by architectural considerations. -Opaque tokens tend to be much shorter than JWT tokens but need most of the token-associated state to be maintained in the provider database. -Opaque tokens are effectively database pointers. -JWT tokens are significantly longer than the opaque tokens but the providers are effectively delegating storing most of the token-associated state to the client by storing it as the token claims and either signing or encrypting them. -==== - -The following table provides a summary of the options for each authentication mechanism: - -|=== -| | quarkus-oidc| quarkus-smallrye-jwt | quarkus-elytron-security-oauth2 - -|Requires Bearer JWT verification -|Local verification or introspection -|Local verification -|Introspection -|Requires Bearer opaque token verification -|Introspection -|No -|Introspection -|Refreshing `JsonWebKey` set for verifying JWT tokens -|Yes -|Yes -|No -|Represent token as `Principal` -|Yes -|Yes -|Yes -|Inject JWT as MP JSON Web Token (JWT) -|Yes -|Yes -|No -|Authorization Code Flow -|Yes -|No -|No -|Multi-tenancy -|Yes -|No -|No -|User info support -|Yes -|No -|No -|PEM key format support -|No -|Yes -|No -|SecretKey support -|No -|In JSON Web Key (JWK) format -|No -|Inner-signed and encrypted or encrypted tokens -|Introspection -|Local verification -|Introspection -|Custom token verification -|No -|With injected JWT parser -|No -|Accept JWT as a cookie -|No -|Yes -|No -|=== - -[[identity-providers]] -== Identity providers - - -The JPA `IdentityProvider` creates a `SecurityIdentity` instance, which is used during user authentication to verify and authorize access requests making your Quarkus application secure. - - -`IdentityProvider` converts the authentication credentials provided by `HttpAuthenticationMechanism` to a `SecurityIdentity` instance. - -Some extensions, for example, `OIDC`, `OAuth2`, and `SmallRye JWT` have inline `IdentityProvider` implementations specific to the supported authentication flow. -For example, `quarkus-oidc` uses its own `IdentityProvider` to convert a token to a `SecurityIdentity` instance. - -If you use `Basic` or `Form` HTTP-based authentication then you must add an `IdentityProvider` instance that can convert a username and password to a `SecurityIdentity` instance. - -* For more information about `Basic` or `Form` HTTP-based authentication, see the following resources: -** xref:security-basic-authentication-tutorial.adoc[Secure a Quarkus application with Basic authentication] -** xref:security-jdbc.adoc[Using security with JDBC] -** xref:security-ldap.adoc[Using security with an LDAP realm] - -== Authorization - -Quarkus also supports role-based access control (RBAC). -For more information about RBAC and other authorization options in Quarkus, see xref:security-authorize-web-endpoints-reference.adoc[Security authorization]. - -== Quarkus Security customization - -Quarkus Security is highly customizable. You can customize the following core security components of Quarkus: - -* `HttpAuthenticationMechanism` -* `IdentityProvider` -* `SecurityidentityAugmentor` - -For more information about customizing Quarkus Security including reactive security, and how to register a security provider, see xref:security-customization.adoc[Security customization]. - -== Combining authentication mechanisms - -If the user credentials are provided by different sources, you can combine authentication mechanisms. -For example, you can combine built-in `Basic` and `quarkus-oidc` `Bearer` authentication mechanisms. - -[IMPORTANT] -==== -You cannot combine the `quarkus-oidc` `Bearer` and `smallrye-jwt` authentication mechanisms because both mechanisms attempt to verify the token extracted from the HTTP `Authorization Bearer` scheme. -==== - -=== Path-specific authentication mechanisms - -The following configuration example demonstrates how you can enforce a single selectable authentication mechanism for a given request path: - -[source,properties] ----- -quarkus.http.auth.permission.basic-or-bearer.paths=/service -quarkus.http.auth.permission.basic-or-bearer.policy=authenticated - -quarkus.http.auth.permission.basic.paths=/basic-only -quarkus.http.auth.permission.basic.policy=authenticated -quarkus.http.auth.permission.basic.auth-mechanism=basic +== Getting started with Quarkus Security -quarkus.http.auth.permission.bearer.paths=/bearer-only -quarkus.http.auth.permission.bearer.policy=authenticated -quarkus.http.auth.permission.bearer.auth-mechanism=bearer ----- +To get started with security in Quarkus, we recommend you combine the Quarkus built-in xref:security-basic-authentication-concept.adoc[Basic authentication] with the JPA identity provider to enable role-based access control (RBAC). +Complete the steps in the xref:security-basic-authentication-tutorial.adoc[Secure a Quarkus application with Basic authentication] tutorial. -Ensure that the value of the `auth-mechanism` property matches the authentication scheme supported by `HttpAuthenticationMechanism`, for example, `basic`, `bearer`, or `form`. +After you have successfully secured your Quarkus application with Basic authentication, you can increase the security further by adding more advanced authentication mechanisms, for example, OpenID Connect (OIDC) authentication. -== Proactive authentication +//Add a link to the recomposed OIDC intro concept here. -By default, Quarkus does proactive authentication, which means that all incoming requests with credentials are authenticated regardless of whether the target page requires authentication. -For more information, see xref:security-built-in-authentication-support-concept.adoc#proactive-authentication[Proactive authentication]. +== Quarkus Security testing -== Secure connections with SSL/TLS +Guidance for testing Quarkus Security features and ensuring that your Quarkus applications are securely protected is provided in xref:security-testing.adoc[Security Testing]. -For more information about how Quarkus supports secure connections with SSL/TLS, see the xref:http-reference.adoc#ssl[HTTP reference] information. +== More about security features in Quarkus -== Cross-origin resource sharing +=== Cross-origin resource sharing To make your Quarkus application accessible to another application running on a different domain, you need to configure cross-origin resource sharing (CORS). For more information about the CORS filter that is provided by Quarkus, see the xref:http-reference.adoc#cors-filter[HTTP reference] information. -== Cross-site Request Forgery (CSRF) prevention +=== Cross-site Request Forgery (CSRF) prevention Quarkus Security provides a RESTEasy Reactive filter that can protect your applications against a https://owasp.org/www-community/attacks/csrf[Cross-Site Request Forgery] attack. For more information, see xref:security-csrf-prevention.adoc[Cross-Site Request Forgery Prevention]. -== SameSite cookies +=== SameSite cookies You can add a https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite[SameSite] cookie property to any of the cookies set by a Quarkus endpoint. For more information, see xref:http-reference.adoc#same-site-cookie[SameSite cookies]. -== Secret engines +=== Secret engines Secrets engines are components that store, generate, or encrypt data. Quarkus provides comprehensive HashiCorp Vault support. For more information, see the link:{vault-guide}[Quarkus and HashiCorp Vault] documentation. -== Secure serialization +=== Secure serialization If your Quarkus Security architecture includes RESTEasy Reactive and Jackson, Quarkus can limit the fields that are included in JSON serialization based on the configured security. For more information, see xref:resteasy-reactive.adoc#secure-serialization[Writing REST services with RESTEasy Reactive]. -== Secure auto-generated resources by REST Data with Panache +=== Secure auto-generated resources by REST Data with Panache If you're using the REST Data with Panache extension to auto-generate your resources, you can still use the Security annotations within the package `javax.annotation.security`. For more information, see xref:rest-data-panache.adoc#securing-endpoints[Securing auto-generated resources]. -== National Vulnerability Database +=== US National Vulnerability Database registration Most of the Quarkus tags are registered in the US link:https://nvd.nist.gov[National Vulnerability Database] (NVD) in Common Platform Enumeration (CPE) name format. To view the registered Quarkus CPE names, use link:https://nvd.nist.gov/products/cpe/search/results?namingFormat=2.3&keyword=quarkus[this search query]. @@ -437,8 +193,3 @@ You can optionally apply a time limit to individual suppressions by adding an ex `...` You can adjust the expiry date if you need to. - -== Quarkus Security testing - -When testing Quarkus security, ensure that your `IdentityProvider` is already set with usernames, passwords, and roles in `application.properties`. -For more information about testing Quarkus Security, see xref:security-testing.adoc#configuring-user-information[Configuring user information]. diff --git a/docs/src/main/asciidoc/security-proactive-authentication-concept.adoc b/docs/src/main/asciidoc/security-proactive-authentication-concept.adoc new file mode 100644 index 0000000000000..7acefe164099b --- /dev/null +++ b/docs/src/main/asciidoc/security-proactive-authentication-concept.adoc @@ -0,0 +1,150 @@ +//// +This document 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 +//// +[id="security-proactive-authentication-concept"] += Proactive authentication +include::_attributes.adoc[] +:categories: security,web + +Proactive authentication is enabled in Quarkus by default. 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. + +[[proactive-authentication]] + +Requests with an invalid credential will always be rejected, even when the page is public. + +You can change the default behavior if you only want to authenticate when the target page requires authentication. + +To disable proactive authentication in Quarkus, set the following attribute in the `application.properties` configuration file: + +[source,xml,options="nowrap",role="white-space-pre"] +---- +`quarkus.http.auth.proactive=false` +---- + +If you disable proactive authentication, the authentication process runs only when an identity is requested. An identity can be requested because of security rules that require the user to authenticate or because programmatic access to the current identity is required. + +If proactive authentication is in use, accessing the `SecurityIdentity` is a blocking operation. +This is because authentication may have yet to happen, 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 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 getDeferredIdentity();` method. +You can then subscribe to the resulting `Uni` and will be notified when authentication is complete and the identity is available. + +NOTE: It's still possible to access the `SecurityIdentity` synchronously with `public SecurityIdentity getIdentity()` in the xref:resteasy-reactive.adoc[RESTEasy Reactive] from endpoints annotated with `@RolesAllowed`, `@Authenticated`, or with respective configuration authorization checks as authentication has already happened. +The same is also valid for the xref:reactive-routes.adoc[Reactive routes] if a route response is synchronous. + +xref:security-authorization.adoc#standard-security-annotations[Standard security annotations] on CDI beans are not supported on IO thread if a non-void secured method returns a value synchronously and proactive authentication is disabled, as they need to access the `SecurityIdentity`. +In the example below, we have defined `HelloResource` and `HelloService`. It's easy to see that any GET request to `/hello` will run on IO thread and throw `BlockingOperationNotAllowedException` exception. + +There is more than one way to fix the example: + +* switch to a worker thread (annotate `hello` endpoint with `@Blocking`) +* change `sayHello` method return type (use reactive or asynchronous data type) +* arguably the safest way is to move `@RolesAllowed` annotation to the endpoint, as accessing `SecurityIdentity` from endpoint methods is never the blocking operation + +[source,java] +---- +import javax.annotation.security.PermitAll; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import io.smallrye.mutiny.Uni; + +@Path("/hello") +@PermitAll +public class HelloResource { + + @Inject + HelloService helloService; + + @GET + public Uni hello() { + return Uni.createFrom().item(helloService.sayHello()); + } + +} +---- + +[source,java] +---- +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class HelloService { + + @RolesAllowed("admin") + public String sayHello() { + return "Hello"; + } + +} +---- + +== How to customize authentication exception responses + +You can 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 { + + @Context + UriInfo uriInfo; + + @Override + public Response toResponse(AuthenticationFailedException exception) { + return Response.status(401).header("WWW-Authenticate", "Basic realm=\"Quarkus\"").build(); + } +} +---- + +CAUTION: Some HTTP authentication mechanisms need to handle authentication exceptions themselves to create a correct authentication challenge. +For example, `io.quarkus.oidc.runtime.CodeAuthenticationMechanism` which manages OpenId Connect authorization code flow authentication, needs to build a correct redirect URL, cookies, etc. +For that reason, using custom exception mappers to customize authentication exceptions thrown by such mechanisms is not recommended. +Instead, a safer approach would be to ensure that proactive authentication is enabled and to use Vert.x HTTP route failure handlers. This is because events come to the handler with the correct response status and headers. +You will then only need to customize the response, as outlined in the following example: + +[source,java] +---- +package io.quarkus.it.keycloak; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; + +import io.quarkus.security.AuthenticationFailedException; +import io.vertx.core.Handler; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; + +@ApplicationScoped +public class AuthenticationFailedExceptionHandler { + + public void init(@Observes Router router) { + router.route().failureHandler(new Handler() { + @Override + public void handle(RoutingContext event) { + if (event.failure() instanceof AuthenticationFailedException) { + event.response().end("CUSTOMIZED_RESPONSE"); + } else { + event.next(); + } + } + }); + } +} +---- \ No newline at end of file diff --git a/docs/src/main/asciidoc/security-protect-service-application-using-oidc-bearer-authentication-tutorial.adoc b/docs/src/main/asciidoc/security-protect-service-application-using-oidc-bearer-authentication-tutorial.adoc index 6731aa6bcfc47..328f509eafd16 100644 --- a/docs/src/main/asciidoc/security-protect-service-application-using-oidc-bearer-authentication-tutorial.adoc +++ b/docs/src/main/asciidoc/security-protect-service-application-using-oidc-bearer-authentication-tutorial.adoc @@ -321,6 +321,6 @@ Please also see the xref:security-oidc-bearer-authentication-concept.adoc#integr * xref:security-openid-connect-client-reference.adoc[OpenID Connect and OAuth2 Client and Filters Reference Guide] * xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] * xref:security-jwt-build.adoc[Sign and encrypt JWT tokens with SmallRye JWT Build] -* xref:security-overview-concept.adoc#oidc-jwt-oauth2-comparison[Summary of Quarkus OIDC, JWT and OAuth2 features] +* xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] * xref:security-overview-concept.adoc[Quarkus Security] * xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] diff --git a/docs/src/main/asciidoc/spring-security.adoc b/docs/src/main/asciidoc/spring-security.adoc index c0f4781ad90e8..651fede4e61ea 100644 --- a/docs/src/main/asciidoc/spring-security.adoc +++ b/docs/src/main/asciidoc/spring-security.adoc @@ -8,7 +8,7 @@ include::_attributes.adoc[] :categories: compatibility :summary: While you are encouraged to use the Quarkus security layer to secure your applications, Quarkus provides a compatibility layer for Spring Security in the form of the spring-security extension. -While users are encouraged to use xref:security-overview-concept.adoc#standard-security-annotations[Java standard annotations for security authorizations], Quarkus provides a compatibility layer for Spring Security in the form of the `spring-security` extension. +While users are encouraged to use Java standard annotations for security authorizations, Quarkus provides a compatibility layer for Spring Security in the form of the `spring-security` extension. This guide explains how a Quarkus application can leverage the well known Spring Security annotations to define authorizations on RESTful services using roles.