diff --git a/docs/src/main/asciidoc/security-proactive-authentication.adoc b/docs/src/main/asciidoc/security-proactive-authentication.adoc index 1630b7e662557..b924a493021d5 100644 --- a/docs/src/main/asciidoc/security-proactive-authentication.adoc +++ b/docs/src/main/asciidoc/security-proactive-authentication.adoc @@ -13,36 +13,44 @@ Proactive authentication is enabled in Quarkus by default. This means that if an [[proactive-authentication]] -Requests with an invalid credential will always be rejected, even when the page is public. +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. +If you only want to authenticate when the target page requires authentication, you can change the default behavior. -To disable proactive authentication in Quarkus, set the following attribute in the `application.properties` configuration file: +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` +`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 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). +If proactive authentication is in use, accessing `SecurityIdentity` is a blocking operation. +This is because authentication might have yet to happen and accessing `SecurityIdentity` might require calls to external systems, such as databases, that might block the operation. +For blocking applications, this is not an issue. +However, if you have disabled authentication in a reactive application, this will fail because you cannot do blocking operations on the I/O 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. +Then, you can 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. +[NOTE] +==== +You can still access `SecurityIdentity` synchronously with `public SecurityIdentity getIdentity()` in xref:resteasy-reactive.adoc[RESTEasy Reactive] from endpoints that are annotated with `@RolesAllowed`, `@Authenticated`, or with respective configuration authorization checks because authentication has already happened. +The same is also valid for 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. +xref:security-authorization.adoc#standard-security-annotations[Standard security annotations] on CDI beans are not supported on an I/O thread if a non-void secured method returns a value synchronously and proactive authentication is disabled because they need to access `SecurityIdentity`. + +In the following example, `HelloResource` and `HelloService` are defined. +Any GET request to `/hello` will run on the I/O thread and throw a `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 +* Switch to a worker thread by annotating the `hello` endpoint with `@Blocking`. +* Change the `sayHello` method return type by using a reactive or asynchronous data type. +* Move `@RolesAllowed` annotation to the endpoint. +This could be one of the safest ways because accessing `SecurityIdentity` from endpoint methods is never the blocking operation. [source,java] ---- @@ -84,7 +92,7 @@ public class HelloService { } ---- -== How to customize authentication exception responses +== Customize authentication exception responses You can use Jakarta REST `ExceptionMapper` to capture Quarkus Security authentication exceptions such as `io.quarkus.security.AuthenticationFailedException`, for example: @@ -115,10 +123,11 @@ public class AuthenticationFailedExceptionMapper implements ExceptionMapper