From ea47a55dc717ec9954bbd67a8642cc1fadbd4a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vav=C5=99=C3=ADk?= Date: Mon, 14 Nov 2022 12:31:15 +0100 Subject: [PATCH] Document RBAC used on CDI beans and IO thread when return is synchronous --- .../main/asciidoc/security-authorization.adoc | 2 + .../security-built-in-authentication.adoc | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/docs/src/main/asciidoc/security-authorization.adoc b/docs/src/main/asciidoc/security-authorization.adoc index 0d91d3b6902ab..35877e1ec43da 100644 --- a/docs/src/main/asciidoc/security-authorization.adoc +++ b/docs/src/main/asciidoc/security-authorization.adoc @@ -270,6 +270,8 @@ public class SubjectExposingResource { <4> This call to obtain the user principal will return null if the caller is unauthenticated, non-null if the caller is authenticated. <5> The `/subject/denied` endpoint disallows any access regardless of whether the call is authenticated by specifying the `@DenyAll` annotation. +CAUTION: Please refer to the xref:security-built-in-authentication.adoc#proactive-authentication[Proactive Authentication] section of the Built-In Authentication Support guide if you plan to use standard security annotations on IO thread. + == References * xref:security.adoc[Quarkus Security] diff --git a/docs/src/main/asciidoc/security-built-in-authentication.adoc b/docs/src/main/asciidoc/security-built-in-authentication.adoc index adb07bec0b51e..11599ca5b8837 100644 --- a/docs/src/main/asciidoc/security-built-in-authentication.adoc +++ b/docs/src/main/asciidoc/security-built-in-authentication.adoc @@ -122,6 +122,55 @@ in the xref:resteasy-reactive.adoc[RESTEasy Reactive] from endpoints annotated w 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 By default, the authentication security constraints are enforced before the JAX-RS chain starts and only way to handle Quarkus Security authentication exceptions is to provide a failure handler like this one: