O jose4j implementa JWS, JWE, JWK e JWT sobre os próprios provedores do JDK, com JsonWebSignature para assinar e um JwtConsumer, criado por JwtConsumerBuilder, para a verificação e a validação das claims. A versão 0.9.7 fez o ciclo completo de ida e volta com HS, RS, PS e ES em 256/384/512 e com EdDSA; ES256K, Ed25519 e Ed448 não são nomes de algoritmo reconhecidos.
Os padrões bloqueiam os dois ataques clássicos, mas deixam o algoritmo em aberto. none é recusado ('none' is a blocked algorithm.), a menos que as assinaturas sejam desativadas explicitamente, e o tipo da chave precisa ser compatível: um token RS256 verificado com uma chave EC e um token HS256 que usava como chave o texto PEM da chave EC falharam (cannot be used for HMAC verification). Já qualquer outro algoritmo que a chave consiga executar é aceito; por isso, fixe o algoritmo com setJwsAlgorithmConstraints(ConstraintType.PERMIT, ...), como faz o exemplo. Uma HmacKey criada a partir dos bytes PEM verificou o token HS256 forjado — as chaves devem vir da configuração, nunca do que o token declara.
A biblioteca impõe os tamanhos de chave: o ES256 recusa uma chave P-384 (expects a key using P-256 but was P-384), e o HS256 recusou uma chave de 16 bytes porque a RFC 7518 exige chaves pelo menos do tamanho da saída do hash. As assinaturas ES256 são o r‖s bruto de 64 bytes; uma assinatura DER falha com Invalid JWS Signature — o depurador de JWT mostra o tamanho.
Os padrões das claims apontam em direções opostas: não ter tolerância para diferença de relógio é mais estrito do que a maioria das equipes espera, e não exigir exp é mais permissivo. setRequireExpirationTime(), setExpectedIssuer(), setExpectedAudience() e setAllowedClockSkewInSeconds() devem constar em todo consumidor que lê tokens de outro serviço.
Para tokens criptografados, o inspetor de JWE mostra o que contém um JWE produzido pelo jose4j.