how to implement redirect on 401 (SmallRye JWT + servlet)

1,068 views
Skip to first unread message

Denis Frank

unread,
Feb 1, 2021, 8:59:55 AM2/1/21
to Quarkus Development mailing list
Hello,
I am using the servlet container in our quarkus application together with SmallRye JWT to build our application. If user is authenticated a JWT is created and passed to the frontend application (servlet) as cookie. Now, if the JWT expired, we want to implement a redirect to a login page. Because the frontend is a third party implementation (https://github.com/ff4j/ff4j/tree/master/ff4j-web) and we can not implement the redirect there, so we have to implement the redirect in the backend.

The security is enabled in the web.xml for the frontend application. Now, if the JWT expires or is absent, a HTTP 401 will be delivered from the backend. I tried different approaches to enable a redirect in this case:
But the ode is never invoked if the JWT token is absent or invalid. Can you please give me advice how can I implement the requirement?

Stuart Douglas

unread,
Feb 1, 2021, 5:30:05 PM2/1/21
to bigd...@gmail.com, Quarkus Development mailing list

I think for this to take effect quarkus.oidc.application-type=web-app also needs to be set.

Stuart

--
You received this message because you are subscribed to the Google Groups "Quarkus Development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to quarkus-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/quarkus-dev/9cf0f9f3-b4f9-458e-9a13-2cf55b8e0907n%40googlegroups.com.

Denis Frank

unread,
Feb 2, 2021, 2:28:53 AM2/2/21
to Quarkus Development mailing list
Hello Stuart,

I am using the "quarkus-smallrye-jwt" not the "quarkus-oidc"  extension. I guess in this case  "quarkus.oidc.*" properties do not have any effect.  I tied it, without success. 

There is a similar question https://groups.google.com/g/quarkus-dev/c/El7j6p9kUB4/m/eByWG4VGBAAJ and the solution was to use the property " quarkus.http.auth.proactive=false".  But it do not work in my case. Maybe because I am using quarkus-undertow extension?

Denis

Sergey Beryozkin

unread,
Feb 2, 2021, 4:39:37 AM2/2/21
to bigd...@gmail.com, Quarkus Development mailing list
Hi

The proactive authentication switch should indeed help with catching the exception with the JAX-RS mapper - but what is unexpected is that you can't even intercept it with ServletFilter.
I know (or at least heard :-) ) the undertow extension uses Vert.x internally so I wonder how the servlet filter chain is run, if it is run from one of the Vertx handlers which follow the security handler then it would explain why you can't catch the exception.I'm theorising here :-), but if it were the case then using Vert.x fault handlers would likely be the only way to intercept the faults - but not sure it can work alongside the Undertow extension

Thanks, Sergey

Denis Frank

unread,
Feb 2, 2021, 5:27:03 AM2/2/21
to Quarkus Development mailing list
Hello Sergey and  Stuart,

I implemented a showcase without quarkus-undertow (https://github.com/franden/quarkus_jwt_401_handling_issue_showcase) . Only with Vert.x, quarkus-smallrye-jwt, quarkus-resteasy. I put the property "quarkus.http.auth.proactive=false". And still have the same Problem. In case of 401 the CustomExceptionMapper  is not invoked.
Steps to reproduce:
  1. mvnw clean quarkus:dev
  2. curl http://localhost:8080/api/exception ->500 from CustomExceptionMapper  + its log message. CustomExceptionMapper  works
  3. curl http://localhost:8080/api/secured -> 401, no log from CustomExceptionMapper -> Problem
It seems that usage of servlet is not the cause of the problem. It seems that the setting "quarkus.http.auth.proactive=false" do not change the behavior. 

According to your post and this request an AuthenticationFailedException should be thrown. Did I forget something? maybe some additional setting?

Greeting Denis

Sergey Beryozkin

unread,
Feb 2, 2021, 6:10:09 AM2/2/21
to bigd...@gmail.com, Quarkus Development mailing list
Hi

I'm not sure, I recall the user confirming it worked, just checked that forum thread again, but it needs to be verified with our own test.

Thanks, Sergey

Stuart Douglas

unread,
Feb 2, 2021, 6:59:15 PM2/2/21
to bigd...@gmail.com, Quarkus Development mailing list
You need to directly map UnauthorizedException not Exception.

We have a built in ExceptionMapper for UnauthorizedException that will be used otherwise, so lazy auth works out of the box.

Stuart

Denis Frank

unread,
Feb 3, 2021, 2:58:22 AM2/3/21
to Quarkus Development mailing list
Hello Stuart,

thank you for clarification. I tried only the mapper with "io.quarkus.security.AuthenticationFailedException" as documented and as it did not work, I tried the more generic "Exception"....
Now I implemented the mapper with "io.quarkus.security.UnauthorizedException". The ExceptionMapper will now be invoked even with "quarkus.http.auth.proactive=true", but only on the jax-rx resources. A call to a URL served by a servlet is still not covered.
I updated the GitHub Example. now:
  1. ✅ curl http://localhost:8080/api/secured ->500 from CustomExceptionMapper<AuthenticationFailedException>  + its log message. CustomExceptionMapper  works
  2. ❌curl http://localhost:8080/servlet/secured -> 401, no log from CustomExceptionMapper<AuthenticationFailedException> -> Problem  
Is it still somehow possible? 

Greetings 
Denis

Denis Frank

unread,
Feb 3, 2021, 7:15:25 AM2/3/21
to Quarkus Development mailing list
Pardon, the two topics should contain  CustomExceptionMapper<UnauthorizedException> in the description , rather then  CustomExceptionMapper<AuthenticationFailedException>
Correct list:
  1. ✅ curl http://localhost:8080/api/secured ->500 from CustomExceptionMapper<UnauthorizedException>  + its log message. CustomExceptionMapper  works
  2. ❌curl http://localhost:8080/servlet/secured -> 401, no log from CustomExceptionMapper<UnauthorizedException> -> Problem  

Stuart Douglas

unread,
Feb 3, 2021, 5:34:14 PM2/3/21
to bigd...@gmail.com, Quarkus Development mailing list
You can do the same thing with a Servlet filter, basically just catch the exception and handle it appropriately.

We need a better approach to this, one way would be to just write a HttpAuthenticationMechanism that only handles the sendChallenge part, and then have some way of making sure it is always called first. At the moment we don't seem to have a way to guarantee ordering.

Stuart

Stuart Douglas

unread,
Feb 3, 2021, 5:46:35 PM2/3/21
to bigd...@gmail.com, Quarkus Development mailing list
Here is a better way to do it, re-enable proactive auth, then add the following class to your app:


If there is an invalid token getChallenge() will be called and you can do what you like there.

Stuart

Denis Frank

unread,
Feb 4, 2021, 5:34:03 AM2/4/21
to Quarkus Development mailing list
Hello Stuart,

thank you very much for the answer. As I wrote in the first mail, ether servlet filter nor error-page as tag in the web.xml are not invoked in case of 401.

Your example with JwtAuth class is working great. Thank you. That covers the requirement with 401. 👍
How can I do it for HTTP code 403? This seems to work, but I do not know if it is a solution that will work also in the future version of quarkus: router.route().failureHandler(failedRoutingContext ->(...)); would you do it another way?

Is there a general approach to handle also other situations. e.g. 403 or 500 etc.? Like it is designed for servlets with error-page tags in web.xml or ExceptionMappper for jax-rs errors?

Greetings 
Denis

Sergey Beryozkin

unread,
Feb 4, 2021, 8:21:28 AM2/4/21
to bigd...@gmail.com, Quarkus Development mailing list
Hi

I'd like to clarify one thing.
You've mentioned earlier that your JAX-RS ExceptionMapper is activated even if the proactive authentication is enabled. This is unexpected to me because in this case the token verification is happening before the JAX-RS chain starts and the invalid token should lead to AuthenticationFailedException earlier.

Do you see it happening with and without undertow ?

Thanks, Sergey

Denis Frank

unread,
Feb 4, 2021, 9:53:53 AM2/4/21
to Quarkus Development mailing list
Hello Sergey,

yes it do. JAX-RS ExceptionMapper<UnauthorizedException>  is activated even if the proactive authentication is enabled with and without undertow.  But only if exception happens in JAX-RS resource, not in the servlet context.
I created two branches in my showcase repository: 
  1. https://github.com/franden/quarkus_jwt_401_handling_issue_showcase/tree/proactive_true_undertow
  2. https://github.com/franden/quarkus_jwt_401_handling_issue_showcase/tree/proactive_true_vertx
In both cases the proactive authentication is enabled. If you now execute a GET on a secured JAX-RS resource ("curl http://localhost:8080/api/secured") the ExceptionMapper<UnauthorizedException>  is invoked.

Greetings
Denis

Sergey Beryozkin

unread,
Feb 4, 2021, 10:23:52 AM2/4/21
to bigd...@gmail.com, Quarkus Development mailing list
Hi,

> But only if exception happens in JAX-RS resource

But this is expected - I thought the problem was that you were not able to intercept the exception thrown by the security layer...

Thanks, Sergey



Reply all
Reply to author
Forward
0 new messages