Search code examples
quarkus

Blocking thread while decoding jwt token


In the quarkus security-jwt, the token payloads contains the claim groups that can be used to control endpoint access. But I'm looking for a way to load the claim groups from another source, like from a database or from a http request send to another service.

Currently, I'm trying to load them from my database inside the principal factory, as described in the Quarkus security-jwt guide. How ever, these is a blocking process, so Quarkus throws the exception io.quarkus.runtime.BlockingOperationNotAllowedException: Cannot start a JTA transaction from the IO thread.

I've already try using quarkus-hibernate-orm-panache and quarkus-hibernate-reactive-panache packages, but no success so far.

Code Example:

import io.smallrye.common.annotation.Blocking;
import io.smallrye.jwt.auth.principal.*;
import jakarta.annotation.Priority;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Alternative;
import org.jose4j.jwt.consumer.JwtContext;
import org.jose4j.jwx.JsonWebStructure;

import java.util.Set;

@ApplicationScoped
@Alternative
@Priority(1)
public class JwtPrincipalFactory extends JWTCallerPrincipalFactory {

    private final DefaultJWTTokenParser parser = new DefaultJWTTokenParser();

    @Blocking
    @Override
    public JWTCallerPrincipal parse(final String token, final JWTAuthContextInfo context) throws ParseException {
        final JwtContext jwtContext = this.parser.parse(token, context);
        final String type = ((JsonWebStructure) jwtContext.getJoseObjects().getFirst()).getHeader("typ");

        // TODO: io.quarkus.runtime.BlockingOperationNotAllowedException: Cannot start a JTA transaction from the IO thread.
        final Set<String> groups = Set.of("none");
        
        // insert "groups" into context claims
        jwtContext.getJwtClaims().setClaim("groups", groups);

        return new DefaultJWTCallerPrincipal(type, jwtContext.getJwtClaims());
    }

}

Solution

  • Using the custom JWT factory works better when you need to customize or optimize the verification, but if you prefer to use it to augment the token content from DB, then it must be run in a blocking mode, see https://quarkus.io/guides/security-jwt#blocking-calls. But the recommended Quarkus security way for augmenting the identity is to use SecurityIdentityAugmentor, see https://quarkus.io/guides/security-customization#security-identity-customization