quarkiverse / quarkus-renarde

Server-side Web Framework with Qute templating, magic/easier controllers, auth, reverse-routing
Apache License 2.0
73 stars 16 forks source link

Seems quarkus.security.jaxrs.deny-unannotated-endpoints=true is not working #160

Closed gbourant closed 8 months ago

gbourant commented 10 months ago

It throws the following exception

io.quarkus.dev.appstate.ApplicationStartException: java.lang.NoSuchMethodError: 'void io.quarkiverse.renarde.security.impl.RenardeSecurityController_Bean.<init>(java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier)'

Also how we can redirect to login page if the user is not authenticated? This works great but it does not work when used with quarkus.http.auth properties. The quarkus.http.auth properties are used in pre-matching so a UnauthorizedException is never thrown.

gbourant commented 10 months ago

Also how we can redirect to login page if the user is not authenticated? This works great but it does not work when used with quarkus.http.auth properties. The quarkus.http.auth properties are used in pre-matching so a UnauthorizedException is never thrown.

Seems there is an undocumented @LoginPage annotation which does that.

FroMage commented 9 months ago

Sorry about the late answer. Can you give me an example of your quarkus.http.auth properties?

gbourant commented 9 months ago

The following is what i'm using right now.

quarkus.http.auth.form.enabled=true
quarkus.http.auth.permission.dashboard.paths=admin/*
quarkus.http.auth.permission.dashboard.policy=dashboard-policy
quarkus.http.auth.policy.dashboard-policy.roles-allowed=ADMIN,ADMIN_EMPLOYEE,SHOP,SHOP_EMPLOYEE
quarkus.http.auth.proactive=false
quarkus.security.jaxrs.deny-unannotated-endpoints=true
FroMage commented 9 months ago

OK thanks. Lemme try that.

gbourant commented 9 months ago

After some quick investigation i found the following:

In order to reproduce it you have to start the project without quarkus.security.jaxrs.deny-unannotated-endpoints property and add it after (quarkus.security.jaxrs.deny-unannotated-endpoints=true) so you can get that exception java.lang.NoSuchMethodError.

If you start the project with quarkus.security.jaxrs.deny-unannotated-endpoints=true it seems it is working but if an annotation does not exist (e.g. @PermitAll) it tries to redirect indefinitely. (idk if this has to do because i try to access a page that requires authentication, maybe it has to do with my project?)

I see that RenardeJWTAuthMechanism.getChallenge is called and it returns from the first if block (return getRedirect(context, config.getLoginPage());).

    @Override
    public Uni<ChallengeData> getChallenge(RoutingContext context) {
        if (config.getLoginPage() != null) {
            // we need to store the URL
            storeInitialLocation(context);
            return getRedirect(context, config.getLoginPage());
        } else {
            return super.getChallenge(context);
        }
    }

image

FroMage commented 8 months ago

Mmmm, I actually need more info. How do you serve your /login.html file? This is the default path for form auth. Also, where do you place your @PermitAll to trigger the error?

gbourant commented 8 months ago

I serve the login page with the following class.

@Path("/p/auth")
//@PermitAll
public class AuthResource extends Controller {

    @Path("login")
    @LoginPage
    @Blocking
    public TemplateInstance loginForm() {
    }
}

There are two errors:

  1. The first error is the io.quarkus.dev.appstate.ApplicationStartException: java.lang.NoSuchMethodError: 'void io.quarkiverse.renarde.security.impl.RenardeSecurityController_Bean.<init>(java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier, java.util.function.Supplier)'. Which you can reproduce with the following way: just add quarkus.security.jaxrs.deny-unannotated-endpoints=true to an already running Renarde application.
  2. The second error is when you start a Renarde application with quarkus.security.jaxrs.deny-unannotated-endpoints=true it doesn't throw the previous exception but it tries to redirect indefinitely. The way i fixed it was to add @PermitAll to AuthResource class.

Let me know if you can reproduce it, if not i will try to create a reproducer project.

FroMage commented 8 months ago

I can reproduce the first issue.

As to the second issue, this is because we're redirecting to your loginForm method which is denied due to quarkus.security.jaxrs.deny-unannotated-endpoints=true. If you add @PermitAll to your loginForm method, it will work.

Now, I could do several things to mitigate this:

Let me think a bit about this.

FroMage commented 8 months ago

I've fixed the first issue. For the second, I will now log the following error and return a 401:

2023-10-20 16:45:36,401 ERROR [io.qua.ren.uti.RenardeJWTAuthMechanism] (vert.x-eventloop-thread-0) Avoiding redirect loop, make sure that your endpoint annotated with @LoginPage is accessible without being authenticated: /Application/login

If there are no other issues, I'll close this issue :)