Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

smallrye jwt 401 cannot be intercepted by ExceptionMapper #29896

Closed
olivierbeltrandocintoo opened this issue Dec 15, 2022 · 8 comments · Fixed by #29590
Closed

smallrye jwt 401 cannot be intercepted by ExceptionMapper #29896

olivierbeltrandocintoo opened this issue Dec 15, 2022 · 8 comments · Fixed by #29590
Labels
area/kotlin area/security area/smallrye env/windows Impacts Windows machines kind/bug Something isn't working
Milestone

Comments

@olivierbeltrandocintoo
Copy link

Describe the bug

Hello,

I cannot seem to be able to intercept the quarkus-smallrye-jwt 401 error resulting from a request with an invalid token.
Of course the normal use case of having a valid token works perfectly, and I am able to catch exceptions thrown from the code with ExceptionMapper (which is aweseome).

I have read several tickets about not being able to intercept/customize those exceptions, and I did not really succeed at discovering what was the good combination to get this working.

Would you please be so kind as to give me a pointer on a working configuration ?

content of the application.properties

smallrye.jwt.verify.key-format=JWK
smallrye.jwt.verify.key.location=jwk.json

I have tried different implementations with the following exceptions as a parameter to the Generic

  • Exception
  • AuthenticationFailedException
  • UnauthorizedException

They look like this (I have hardcoded the error code because I am stuck before :))

@Provider
@Priority(1)
class ErrorMapper : ExceptionMapper<Exception> {
    override fun toResponse(exception: Exception?): Response {
        return Response.status(401).entity(
            Json.createObjectBuilder()
                .add("error", exception?.message)
                .add("code", 401)
                .build()
        ).build()
    }
}

I also have tried the ResponseFilter that work for normal requests, but for the JWT auth it is bypassed

@Provider
@Priority(9999)
class ErrorPageResponseFilter: ContainerResponseFilter {
    override fun filter(requestContext: ContainerRequestContext?, responseContext: ContainerResponseContext?) {
        println("hello world") // this is printed in the console for normal requests
    }
}

The quarkus.platform.version in my pom.xml file

<quarkus.platform.version>2.15.0.Final</quarkus.platform.version>

Expected behavior

I should be able to override the response sent on an authentication failure (401) from the quarkus-smallrye-jwt stack, and return a custom body. Example of bodies that I'd like to send :)

{
"error": "Signature could not be verified"
}
{
"error": "Token is expired"
}

Actual behavior

Empty body, with 401 http status code

How to Reproduce?

  1. get the kotlin quickstart
quarkus create app org.acme:rest-kotlin-quickstart --extension='kotlin,resteasy-reactive-jackson'
cd rest-kotlin-quickstart
  1. add authentication mechanism by adding the small-rye extension (https://quarkus.io/guides/security-jwt)
quarkus extension add 'smallrye-jwt,smallrye-jwt-build'
  1. add valid jwk.json file in the resources dir
  2. add the following lines in the application.properties
smallrye.jwt.verify.key-format=JWK
smallrye.jwt.verify.key.location=jwk.json
  1. send a request with an invalid token in the Authorization header with Bearer

From there I tried what was described above to catch the default 401 and override it but I did not manage.

Output of uname -a or ver

Microsoft Windows [version 10.0.22000.1335]

Output of java -version

openjdk version "17" 2021-09-14 OpenJDK Runtime Environment (build 17+35-2724) OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.14.2.Final

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63) Maven home: C:\Users\OlivierBeltrando.m2\wrapper\dists\apache-maven-3.8.6-bin\67568434\apache-maven-3.8.6 Java version: 17, vendor: Oracle Corporation, runtime: C:\Users\OlivierBeltrando\bin\openjdk-17+35_windows-x64_bin\jdk-17 Default locale: fr_FR, platform encoding: Cp1252 OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

Additional information

No response

@olivierbeltrandocintoo olivierbeltrandocintoo added the kind/bug Something isn't working label Dec 15, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Dec 15, 2022

/cc @Ladicek(smallrye), @evanchooly(kotlin), @geoand(kotlin), @jmartisk(smallrye), @phillip-kruger(smallrye), @radcortez(smallrye), @sberyozkin(jwt)

@sberyozkin
Copy link
Member

sberyozkin commented Dec 15, 2022

Hi @olivierbeltrandocintoo
I think, right now, you need to either disable the proactive authentication, quarkus.http.auth.proactive=false or use the vert.x filter, https://quarkus.io/guides/security-built-in-authentication-support-concept#how-to-customize-authentication-exception-responses.

@michalvavrik has opened #29590 to also support exception mapping for Resteasy Reactive in the proactive auth mode

@michalvavrik
Copy link
Contributor

Yep, I agree with Sergey, and if you experience problem in 2.14.2.Final, let's try also 2.15.0.Final please. #29590 should handle this, but let's keep the issue open please so that I can link the PR with issue. @olivierbeltrandocintoo please let me know if it worked, thank you.

@olivierbeltrandocintoo
Copy link
Author

Firstly many many thanks !!

Note: The app I have right now is running with Quarkus 2.1.15.Final :)
(Although I wrote it in the main description (pom.xml extract), I forgot to mention it in the reproducer steps ;P)

Setting the proactive to false indeed allowed the following piece of code to work

@Provider
@Priority(1)
class AuthenticationExceptionMapper : ExceptionMapper<AuthenticationFailedException?> {
    override fun toResponse(exception: AuthenticationFailedException?): Response {
        val message = exception?.cause?.message ?: "could not get cause"
        return Response.status(Response.Status.UNAUTHORIZED)
            .entity(
                Json.createObjectBuilder()
                    .add("authentfail", message)
                    .add("code", 401)
                    .build()
            )
            .build()
    }
}

result

{"authentfail":"SRJWT07000: Failed to verify a token","code":401}

The drawback though is that I had to 'protect' manually the endpoints (ie. add the @Authenticated annotation).

Again, many many thanks for the help I really look forward to see the ExceptionMapper also doing the job with the quarkus.http.auth.proactive=true

Cheers,
Olivier

@olivierbeltrandocintoo
Copy link
Author

I forgot to mention that I failed to make the other piece of code in the examples to work.
But to be honest I am much more interested in the exceptionMapper than tweaking the router ;P

@michalvavrik
Copy link
Contributor

I forgot to mention that I failed to make the other piece of code in the examples to work. But to be honest I am much more interested in the exceptionMapper than tweaking the router ;P

We have test that should be similar to your case https://github.com/quarkusio/quarkus/blob/main/extensions/smallrye-jwt/deployment/src/test/java/io/quarkus/jwt/test/EnabledProactiveAuthFailedExceptionHandlerTest.java, but I agree with exception mappers note.

@sberyozkin
Copy link
Member

sberyozkin commented Dec 16, 2022

@olivierbeltrandocintoo

The drawback though is that I had to 'protect' manually the endpoints (ie. add the @authenticated annotation).

Just FYI, it is not required if you prefer not to,

quarkus.http.auth.permission.auth.paths=/myservice
quarkus.http.auth.permission.auth.policy=authenticated

should do as well

@olivierbeltrandocintoo
Copy link
Author

Thank you :)

@gsmet gsmet modified the milestones: 2.16 - main, 2.15.1.Final Dec 20, 2022
gsmet pushed a commit to gsmet/quarkus that referenced this issue Dec 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/kotlin area/security area/smallrye env/windows Impacts Windows machines kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants