Search in sources :

Example 1 with SignatureException

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

the class JwtSerializer method decode.

Optional<Claims> decode(String token) {
    checkIsStarted();
    Claims claims = null;
    try {
        claims = Jwts.parser().setSigningKey(secretKey).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 (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.SignatureException) AuthenticationException(org.sonar.server.authentication.event.AuthenticationException) SignatureException(io.jsonwebtoken.SignatureException) ExpiredJwtException(io.jsonwebtoken.ExpiredJwtException)

Example 2 with SignatureException

use of io.jsonwebtoken.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.SignatureException) SignatureException(io.jsonwebtoken.SignatureException) InvalidKeyException(java.security.InvalidKeyException)

Example 3 with SignatureException

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

the class DefaultJwtParser method parse.

@Override
public Jwt parse(String jwt) throws ExpiredJwtException, MalformedJwtException, SignatureException {
    Assert.hasText(jwt, "JWT String argument cannot be null or empty.");
    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();
    }
    if (base64UrlEncodedPayload == null) {
        throw new MalformedJwtException("JWT string '" + jwt + "' is missing a body/payload.");
    }
    // =============== Header =================
    Header header = null;
    CompressionCodec compressionCodec = null;
    if (base64UrlEncodedHeader != null) {
        String origValue = TextCodec.BASE64URL.decodeToString(base64UrlEncodedHeader);
        Map<String, Object> m = readValue(origValue);
        if (base64UrlEncodedDigest != null) {
            header = new DefaultJwsHeader(m);
        } else {
            header = new DefaultHeader(m);
        }
        compressionCodec = compressionCodecResolver.resolveCompressionCodec(header);
    }
    // =============== Body =================
    String payload;
    if (compressionCodec != null) {
        byte[] decompressed = compressionCodec.decompress(TextCodec.BASE64URL.decode(base64UrlEncodedPayload));
        payload = new String(decompressed, Strings.UTF_8);
    } else {
        payload = TextCodec.BASE64URL.decodeToString(base64UrlEncodedPayload);
    }
    Claims claims = null;
    if (payload.charAt(0) == '{' && payload.charAt(payload.length() - 1) == '}') {
        //likely to be json, parse it:
        Map<String, Object> claimsMap = 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 + base64UrlEncodedPayload;
        JwtSignatureValidator validator;
        try {
            validator = createSignatureValidator(algorithm, key);
        } catch (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) {
        SimpleDateFormat sdf;
        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)) {
                sdf = new SimpleDateFormat(ISO_8601_FORMAT);
                String expVal = sdf.format(exp);
                String nowVal = sdf.format(now);
                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)) {
                sdf = new SimpleDateFormat(ISO_8601_FORMAT);
                String nbfVal = sdf.format(nbf);
                String nowVal = sdf.format(now);
                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<Object>((JwsHeader) header, body, base64UrlEncodedDigest);
    } else {
        return new DefaultJwt<Object>(header, body);
    }
}
Also used : SignatureAlgorithm(io.jsonwebtoken.SignatureAlgorithm) SignatureException(io.jsonwebtoken.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) Date(java.util.Date) Header(io.jsonwebtoken.Header) JwsHeader(io.jsonwebtoken.JwsHeader) MalformedJwtException(io.jsonwebtoken.MalformedJwtException) SimpleDateFormat(java.text.SimpleDateFormat) Key(java.security.Key)

Example 4 with SignatureException

use of io.jsonwebtoken.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 Arrays.equals(computed, signature);
    }
}
Also used : RSAPublicKey(java.security.interfaces.RSAPublicKey) PublicKey(java.security.PublicKey) Signature(java.security.Signature) SignatureException(io.jsonwebtoken.SignatureException) SignatureException(io.jsonwebtoken.SignatureException) InvalidKeyException(java.security.InvalidKeyException)

Aggregations

SignatureException (io.jsonwebtoken.SignatureException)4 Claims (io.jsonwebtoken.Claims)2 ExpiredJwtException (io.jsonwebtoken.ExpiredJwtException)2 InvalidKeyException (java.security.InvalidKeyException)2 PublicKey (java.security.PublicKey)2 Signature (java.security.Signature)2 CompressionCodec (io.jsonwebtoken.CompressionCodec)1 Header (io.jsonwebtoken.Header)1 JwsHeader (io.jsonwebtoken.JwsHeader)1 MalformedJwtException (io.jsonwebtoken.MalformedJwtException)1 PrematureJwtException (io.jsonwebtoken.PrematureJwtException)1 SignatureAlgorithm (io.jsonwebtoken.SignatureAlgorithm)1 UnsupportedJwtException (io.jsonwebtoken.UnsupportedJwtException)1 DefaultJwtSignatureValidator (io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator)1 JwtSignatureValidator (io.jsonwebtoken.impl.crypto.JwtSignatureValidator)1 Key (java.security.Key)1 ECPublicKey (java.security.interfaces.ECPublicKey)1 RSAPublicKey (java.security.interfaces.RSAPublicKey)1 SimpleDateFormat (java.text.SimpleDateFormat)1 Date (java.util.Date)1