auth0 / java-jwt

Java implementation of JSON Web Token (JWT)
MIT License
5.85k stars 922 forks source link

UrlJwkProvider.get is hitting the internet on every call #380

Closed glorat closed 4 years ago

glorat commented 4 years ago

Description

Provide a clear and concise description of the issue, including what you expected to happen. UrlJwkProvider.get is hitting the internet on every call. I'd expect to hit at most once on construction to obtain the public keys once

Reproduction

Detail the steps taken to reproduce this error, what was expected, and whether this issue can be reproduced consistently or if it is intermittent. The original problem I was trying to solve was handling the case where auth0 was holding multiple public keys and they need to be matched to the JWT being verified. The obvious code to write would be like this

  val provider = new UrlJwkProvider(issuer)
  val decoded = JWT.decode(token)
    val keyId = decoded.getKeyId
    val keyInfo = provider.get(keyId)
    val publicKey = keyInfo.getPublicKey.asInstanceOf[RSAPublicKey]
    val algorithm = Algorithm.RSA256(publicKey, null)
    val verifier = JWT.require(algorithm)
      .withIssuer(issuer)
      .withAudience(audience)
      .build

    assertThrows[TokenExpiredException] {
      val jwt = verifier.verify(token)
    }

where we obtain only the right public key from the provider, which obtains it from the URL. However, the provider.get does an internet check on every call, which defeats the purpose of JWT verification being self-contained and fast

Expectation

UrlJwkProvider instances should load public keys only once.

Also, it would be good to have an explicitly documented way of verifying a JWT subject to multiple keys - auth0 docs say this case should be accounted for but I find no code samples that do it well. My above may not be the preferred way. If so, I'll take alternative code

Environment

Please provide the following: jwks-rsa-0.9.0 deps were

"com.auth0" % "java-jwt" % "3.8.3",
"com.auth0" % "jwks-rsa" % "0.9.0"

p.s. I'm using scala for my testing but it is close enough to Java to understand

glorat commented 4 years ago

For reference, the dodgy code in question is in UrlJwkProvider

    @Override
    public Jwk get(String keyId) throws JwkException {
        final List<Jwk> jwks = getAll();  // This calls getJwks, which then does the network hit
        if (keyId == null && jwks.size() == 1) {
            return jwks.get(0);
        }
glorat commented 4 years ago

Apologies, I just realised I've posted this to the wrong project... I'll move it