Search in sources :

Example 6 with SignatureException

use of io.jsonwebtoken.security.SignatureException in project sonarqube by SonarSource.

the class JwtSerializer method decode.

Optional<Claims> decode(String token) {
    checkIsStarted();
    Claims claims = null;
    try {
        claims = Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token).getBody();
        requireNonNull(claims.getId(), "Token id hasn't been found");
        requireNonNull(claims.getSubject(), "Token subject hasn't been found");
        requireNonNull(claims.getExpiration(), "Token expiration date hasn't been found");
        requireNonNull(claims.getIssuedAt(), "Token creation date hasn't been found");
        return Optional.of(claims);
    } catch (UnsupportedJwtException | ExpiredJwtException | SignatureException e) {
        return Optional.empty();
    } catch (Exception e) {
        throw AuthenticationException.newBuilder().setSource(Source.jwt()).setLogin(claims == null ? null : claims.getSubject()).setMessage(e.getMessage()).build();
    }
}
Also used : Claims(io.jsonwebtoken.Claims) ExpiredJwtException(io.jsonwebtoken.ExpiredJwtException) SignatureException(io.jsonwebtoken.security.SignatureException) UnsupportedJwtException(io.jsonwebtoken.UnsupportedJwtException) AuthenticationException(org.sonar.server.authentication.event.AuthenticationException) ExpiredJwtException(io.jsonwebtoken.ExpiredJwtException) SignatureException(io.jsonwebtoken.security.SignatureException) UnsupportedJwtException(io.jsonwebtoken.UnsupportedJwtException)

Example 7 with SignatureException

use of io.jsonwebtoken.security.SignatureException in project killbill by killbill.

the class KillBillAuth0Realm method loadPublicKey.

private PublicKey loadPublicKey(final String keyId) {
    final BoundRequestBuilder builder = httpClient.prepareGet(securityConfig.getShiroAuth0Url() + "/.well-known/jwks.json");
    final Response response;
    try {
        final ListenableFuture<Response> futureStatus = builder.execute(new AsyncCompletionHandler<Response>() {

            @Override
            public Response onCompleted(final Response response) throws Exception {
                return response;
            }
        });
        response = futureStatus.get(DEFAULT_TIMEOUT_SECS, TimeUnit.SECONDS);
    } catch (final TimeoutException toe) {
        throw new SignatureException("Timeout while connecting to Auth0 to fetch public keys", toe);
    } catch (final Exception e) {
        throw new SignatureException("Error while connecting to Auth0 to fetch public keys", e);
    }
    final Map<String, List<Map<String, Object>>> keysResponse;
    try {
        keysResponse = mapper.readValue(response.getResponseBodyAsStream(), new TypeReference<Map<String, List<Map<String, Object>>>>() {
        });
    } catch (final IOException e) {
        throw new SignatureException("Unable to read public keys from Auth0", e);
    }
    if (keysResponse.get("keys") == null || keysResponse.get("keys").isEmpty()) {
        throw new SignatureException("Auth0 returned no key");
    }
    final List<Map<String, Object>> newKeys = keysResponse.get("keys");
    for (final Map<String, Object> newKey : newKeys) {
        if (newKey.get("kid") == null || !newKey.get("kid").equals(keyId) || newKey.get("kty") == null) {
            continue;
        }
        final String kty = (String) newKey.get("kty");
        switch(kty) {
            case "RSA":
                final BigInteger modulus = getBigInteger(newKey.get("n"));
                final BigInteger exponent = getBigInteger(newKey.get("e"));
                if (modulus == null || exponent == null) {
                    continue;
                }
                return new RSAPublicKey() {

                    @Override
                    public BigInteger getPublicExponent() {
                        return exponent;
                    }

                    @Override
                    public String getAlgorithm() {
                        return "RSA";
                    }

                    @Override
                    public String getFormat() {
                        return "JWK";
                    }

                    @Override
                    public byte[] getEncoded() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public BigInteger getModulus() {
                        return modulus;
                    }
                };
            case "EC":
                final String curveName = (String) newKey.get("crv");
                final BigInteger x = getBigInteger(newKey.get("x"));
                final BigInteger y = getBigInteger(newKey.get("y"));
                if (curveName == null || x == null || y == null) {
                    continue;
                }
                final ECParameterSpec curve = EcCurve.tryGet(curveName);
                if (curve == null) {
                    continue;
                }
                final ECPoint w = new ECPoint(x, y);
                return new ECPublicKey() {

                    @Override
                    public ECPoint getW() {
                        return w;
                    }

                    @Override
                    public String getAlgorithm() {
                        return "EC";
                    }

                    @Override
                    public String getFormat() {
                        return "JWK";
                    }

                    @Override
                    public byte[] getEncoded() {
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public ECParameterSpec getParams() {
                        return curve;
                    }
                };
            default:
        }
    }
    throw new SignatureException("Could not find Auth0 public key " + keyId);
}
Also used : SignatureException(io.jsonwebtoken.security.SignatureException) IOException(java.io.IOException) ECPoint(java.security.spec.ECPoint) TimeoutException(java.util.concurrent.TimeoutException) AuthorizationException(org.apache.shiro.authz.AuthorizationException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) SignatureException(io.jsonwebtoken.security.SignatureException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) AuthenticationException(org.apache.shiro.authc.AuthenticationException) JwtException(io.jsonwebtoken.JwtException) Response(org.asynchttpclient.Response) BoundRequestBuilder(org.asynchttpclient.BoundRequestBuilder) RSAPublicKey(java.security.interfaces.RSAPublicKey) ECPublicKey(java.security.interfaces.ECPublicKey) ECParameterSpec(java.security.spec.ECParameterSpec) BigInteger(java.math.BigInteger) List(java.util.List) TypeReference(com.fasterxml.jackson.core.type.TypeReference) Map(java.util.Map) TimeoutException(java.util.concurrent.TimeoutException)

Example 8 with SignatureException

use of io.jsonwebtoken.security.SignatureException in project jjwt by jwtk.

the class EllipticCurveSignatureValidator method isValid.

@Override
public boolean isValid(byte[] data, byte[] signature) {
    Signature sig = createSignatureInstance();
    PublicKey publicKey = (PublicKey) key;
    try {
        int expectedSize = getSignatureByteArrayLength(alg);
        /**
         * If the expected size is not valid for JOSE, fall back to ASN.1 DER signature.
         * This fallback is for backwards compatibility ONLY (to support tokens generated by previous versions of jjwt)
         * and backwards compatibility will possibly be removed in a future version of this library.
         *
         * *
         */
        byte[] derSignature = expectedSize != signature.length && signature[0] == 0x30 ? signature : EllipticCurveProvider.transcodeSignatureToDER(signature);
        return doVerify(sig, publicKey, data, derSignature);
    } catch (Exception e) {
        String msg = "Unable to verify Elliptic Curve signature using configured ECPublicKey. " + e.getMessage();
        throw new SignatureException(msg, e);
    }
}
Also used : PublicKey(java.security.PublicKey) ECPublicKey(java.security.interfaces.ECPublicKey) Signature(java.security.Signature) SignatureException(io.jsonwebtoken.security.SignatureException) InvalidKeyException(java.security.InvalidKeyException) SignatureException(io.jsonwebtoken.security.SignatureException)

Example 9 with SignatureException

use of io.jsonwebtoken.security.SignatureException in project jjwt by jwtk.

the class DefaultJwtParser method parse.

@Override
public Jwt parse(String jwt) throws ExpiredJwtException, MalformedJwtException, SignatureException {
    // remove this block in v1.0 (the equivalent is already in DefaultJwtParserBuilder)
    if (this.deserializer == null) {
        // try to find one based on the services available
        // TODO: This util class will throw a UnavailableImplementationException here to retain behavior of previous version, remove in v1.0
        this.deserializeJsonWith(LegacyServices.loadFirst(Deserializer.class));
    }
    Assert.hasText(jwt, "JWT String argument cannot be null or empty.");
    if ("..".equals(jwt)) {
        String msg = "JWT string '..' is missing a header.";
        throw new MalformedJwtException(msg);
    }
    String base64UrlEncodedHeader = null;
    String base64UrlEncodedPayload = null;
    String base64UrlEncodedDigest = null;
    int delimiterCount = 0;
    StringBuilder sb = new StringBuilder(128);
    for (char c : jwt.toCharArray()) {
        if (c == SEPARATOR_CHAR) {
            CharSequence tokenSeq = Strings.clean(sb);
            String token = tokenSeq != null ? tokenSeq.toString() : null;
            if (delimiterCount == 0) {
                base64UrlEncodedHeader = token;
            } else if (delimiterCount == 1) {
                base64UrlEncodedPayload = token;
            }
            delimiterCount++;
            sb.setLength(0);
        } else {
            sb.append(c);
        }
    }
    if (delimiterCount != 2) {
        String msg = "JWT strings must contain exactly 2 period characters. Found: " + delimiterCount;
        throw new MalformedJwtException(msg);
    }
    if (sb.length() > 0) {
        base64UrlEncodedDigest = sb.toString();
    }
    // =============== Header =================
    Header header = null;
    CompressionCodec compressionCodec = null;
    if (base64UrlEncodedHeader != null) {
        byte[] bytes = base64UrlDecoder.decode(base64UrlEncodedHeader);
        String origValue = new String(bytes, Strings.UTF_8);
        Map<String, Object> m = (Map<String, Object>) readValue(origValue);
        if (base64UrlEncodedDigest != null) {
            header = new DefaultJwsHeader(m);
        } else {
            header = new DefaultHeader(m);
        }
        compressionCodec = compressionCodecResolver.resolveCompressionCodec(header);
    }
    // =============== Body =================
    // https://github.com/jwtk/jjwt/pull/540
    String payload = "";
    if (base64UrlEncodedPayload != null) {
        byte[] bytes = base64UrlDecoder.decode(base64UrlEncodedPayload);
        if (compressionCodec != null) {
            bytes = compressionCodec.decompress(bytes);
        }
        payload = new String(bytes, Strings.UTF_8);
    }
    Claims claims = null;
    if (!payload.isEmpty() && payload.charAt(0) == '{' && payload.charAt(payload.length() - 1) == '}') {
        // likely to be json, parse it:
        Map<String, Object> claimsMap = (Map<String, Object>) readValue(payload);
        claims = new DefaultClaims(claimsMap);
    }
    // =============== Signature =================
    if (base64UrlEncodedDigest != null) {
        // it is signed - validate the signature
        JwsHeader jwsHeader = (JwsHeader) header;
        SignatureAlgorithm algorithm = null;
        if (header != null) {
            String alg = jwsHeader.getAlgorithm();
            if (Strings.hasText(alg)) {
                algorithm = SignatureAlgorithm.forName(alg);
            }
        }
        if (algorithm == null || algorithm == SignatureAlgorithm.NONE) {
            // it is plaintext, but it has a signature.  This is invalid:
            String msg = "JWT string has a digest/signature, but the header does not reference a valid signature " + "algorithm.";
            throw new MalformedJwtException(msg);
        }
        if (key != null && keyBytes != null) {
            throw new IllegalStateException("A key object and key bytes cannot both be specified. Choose either.");
        } else if ((key != null || keyBytes != null) && signingKeyResolver != null) {
            String object = key != null ? "a key object" : "key bytes";
            throw new IllegalStateException("A signing key resolver and " + object + " cannot both be specified. Choose either.");
        }
        // digitally signed, let's assert the signature:
        Key key = this.key;
        if (key == null) {
            // fall back to keyBytes
            byte[] keyBytes = this.keyBytes;
            if (Objects.isEmpty(keyBytes) && signingKeyResolver != null) {
                // use the signingKeyResolver
                if (claims != null) {
                    key = signingKeyResolver.resolveSigningKey(jwsHeader, claims);
                } else {
                    key = signingKeyResolver.resolveSigningKey(jwsHeader, payload);
                }
            }
            if (!Objects.isEmpty(keyBytes)) {
                Assert.isTrue(algorithm.isHmac(), "Key bytes can only be specified for HMAC signatures. Please specify a PublicKey or PrivateKey instance.");
                key = new SecretKeySpec(keyBytes, algorithm.getJcaName());
            }
        }
        Assert.notNull(key, "A signing key must be specified if the specified JWT is digitally signed.");
        // re-create the jwt part without the signature.  This is what needs to be signed for verification:
        String jwtWithoutSignature = base64UrlEncodedHeader + SEPARATOR_CHAR;
        if (base64UrlEncodedPayload != null) {
            jwtWithoutSignature += base64UrlEncodedPayload;
        }
        JwtSignatureValidator validator;
        try {
            // since 0.10.0: https://github.com/jwtk/jjwt/issues/334
            algorithm.assertValidVerificationKey(key);
            validator = createSignatureValidator(algorithm, key);
        } catch (WeakKeyException e) {
            throw e;
        } catch (InvalidKeyException | IllegalArgumentException e) {
            String algName = algorithm.getValue();
            String msg = "The parsed JWT indicates it was signed with the " + algName + " signature " + "algorithm, but the specified signing key of type " + key.getClass().getName() + " may not be used to validate " + algName + " signatures.  Because the specified " + "signing key reflects a specific and expected algorithm, and the JWT does not reflect " + "this algorithm, it is likely that the JWT was not expected and therefore should not be " + "trusted.  Another possibility is that the parser was configured with the incorrect " + "signing key, but this cannot be assumed for security reasons.";
            throw new UnsupportedJwtException(msg, e);
        }
        if (!validator.isValid(jwtWithoutSignature, base64UrlEncodedDigest)) {
            String msg = "JWT signature does not match locally computed signature. JWT validity cannot be " + "asserted and should not be trusted.";
            throw new SignatureException(msg);
        }
    }
    final boolean allowSkew = this.allowedClockSkewMillis > 0;
    // since 0.3:
    if (claims != null) {
        final Date now = this.clock.now();
        long nowTime = now.getTime();
        // https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-30#section-4.1.4
        // token MUST NOT be accepted on or after any specified exp time:
        Date exp = claims.getExpiration();
        if (exp != null) {
            long maxTime = nowTime - this.allowedClockSkewMillis;
            Date max = allowSkew ? new Date(maxTime) : now;
            if (max.after(exp)) {
                String expVal = DateFormats.formatIso8601(exp, false);
                String nowVal = DateFormats.formatIso8601(now, false);
                long differenceMillis = maxTime - exp.getTime();
                String msg = "JWT expired at " + expVal + ". Current time: " + nowVal + ", a difference of " + differenceMillis + " milliseconds.  Allowed clock skew: " + this.allowedClockSkewMillis + " milliseconds.";
                throw new ExpiredJwtException(header, claims, msg);
            }
        }
        // https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-30#section-4.1.5
        // token MUST NOT be accepted before any specified nbf time:
        Date nbf = claims.getNotBefore();
        if (nbf != null) {
            long minTime = nowTime + this.allowedClockSkewMillis;
            Date min = allowSkew ? new Date(minTime) : now;
            if (min.before(nbf)) {
                String nbfVal = DateFormats.formatIso8601(nbf, false);
                String nowVal = DateFormats.formatIso8601(now, false);
                long differenceMillis = nbf.getTime() - minTime;
                String msg = "JWT must not be accepted before " + nbfVal + ". Current time: " + nowVal + ", a difference of " + differenceMillis + " milliseconds.  Allowed clock skew: " + this.allowedClockSkewMillis + " milliseconds.";
                throw new PrematureJwtException(header, claims, msg);
            }
        }
        validateExpectedClaims(header, claims);
    }
    Object body = claims != null ? claims : payload;
    if (base64UrlEncodedDigest != null) {
        return new DefaultJws<>((JwsHeader) header, body, base64UrlEncodedDigest);
    } else {
        return new DefaultJwt<>(header, body);
    }
}
Also used : WeakKeyException(io.jsonwebtoken.security.WeakKeyException) SignatureAlgorithm(io.jsonwebtoken.SignatureAlgorithm) SignatureException(io.jsonwebtoken.security.SignatureException) DefaultJwtSignatureValidator(io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator) JwtSignatureValidator(io.jsonwebtoken.impl.crypto.JwtSignatureValidator) SecretKeySpec(javax.crypto.spec.SecretKeySpec) CompressionCodec(io.jsonwebtoken.CompressionCodec) UnsupportedJwtException(io.jsonwebtoken.UnsupportedJwtException) Claims(io.jsonwebtoken.Claims) ExpiredJwtException(io.jsonwebtoken.ExpiredJwtException) JwsHeader(io.jsonwebtoken.JwsHeader) PrematureJwtException(io.jsonwebtoken.PrematureJwtException) InvalidKeyException(io.jsonwebtoken.security.InvalidKeyException) Date(java.util.Date) Header(io.jsonwebtoken.Header) JwsHeader(io.jsonwebtoken.JwsHeader) Deserializer(io.jsonwebtoken.io.Deserializer) MalformedJwtException(io.jsonwebtoken.MalformedJwtException) Map(java.util.Map) Key(java.security.Key)

Example 10 with SignatureException

use of io.jsonwebtoken.security.SignatureException in project jjwt by jwtk.

the class RsaSignatureValidator method isValid.

@Override
public boolean isValid(byte[] data, byte[] signature) {
    if (key instanceof PublicKey) {
        Signature sig = createSignatureInstance();
        PublicKey publicKey = (PublicKey) key;
        try {
            return doVerify(sig, publicKey, data, signature);
        } catch (Exception e) {
            String msg = "Unable to verify RSA signature using configured PublicKey. " + e.getMessage();
            throw new SignatureException(msg, e);
        }
    } else {
        Assert.notNull(this.SIGNER, "RSA Signer instance cannot be null.  This is a bug.  Please report it.");
        byte[] computed = this.SIGNER.sign(data);
        return MessageDigest.isEqual(computed, signature);
    }
}
Also used : RSAPublicKey(java.security.interfaces.RSAPublicKey) PublicKey(java.security.PublicKey) Signature(java.security.Signature) SignatureException(io.jsonwebtoken.security.SignatureException) InvalidKeyException(java.security.InvalidKeyException) SignatureException(io.jsonwebtoken.security.SignatureException)

Aggregations

SignatureException (io.jsonwebtoken.security.SignatureException)20 Claims (io.jsonwebtoken.Claims)17 CloudStore (com.yahoo.athenz.zts.store.CloudStore)15 MockCloudStore (com.yahoo.athenz.zts.store.MockCloudStore)15 Principal (com.yahoo.athenz.auth.Principal)14 Test (org.testng.annotations.Test)14 HttpServletResponse (javax.servlet.http.HttpServletResponse)3 Response (javax.ws.rs.core.Response)3 JWSObject (com.nimbusds.jose.JWSObject)2 AthenzObject (com.yahoo.athenz.zts.ZTSImpl.AthenzObject)2 ExpiredJwtException (io.jsonwebtoken.ExpiredJwtException)2 UnsupportedJwtException (io.jsonwebtoken.UnsupportedJwtException)2 Path (java.nio.file.Path)2 InvalidKeyException (java.security.InvalidKeyException)2 PublicKey (java.security.PublicKey)2 Signature (java.security.Signature)2 X509Certificate (java.security.cert.X509Certificate)2 ECPublicKey (java.security.interfaces.ECPublicKey)2 RSAPublicKey (java.security.interfaces.RSAPublicKey)2 Map (java.util.Map)2