Search in sources :

Example 1 with Clock

use of com.auth0.jwt.interfaces.Clock in project sonarqube by SonarSource.

the class GithubAppSecurityImpl method createAppToken.

@Override
public AppToken createAppToken(long appId, String privateKey) {
    Algorithm algorithm = readApplicationPrivateKey(appId, privateKey);
    LocalDateTime now = LocalDateTime.now(clock);
    // Expiration period is configurable and could be greater if needed.
    // See https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-a-github-app
    LocalDateTime expiresAt = now.plus(AppToken.EXPIRATION_PERIOD_IN_MINUTES, ChronoUnit.MINUTES);
    ZoneOffset offset = clock.getZone().getRules().getOffset(now);
    Date nowDate = Date.from(now.toInstant(offset));
    Date expiresAtDate = Date.from(expiresAt.toInstant(offset));
    JWTCreator.Builder builder = JWT.create().withIssuer(String.valueOf(appId)).withIssuedAt(nowDate).withExpiresAt(expiresAtDate);
    return new AppToken(builder.sign(algorithm));
}
Also used : LocalDateTime(java.time.LocalDateTime) JWTCreator(com.auth0.jwt.JWTCreator) Algorithm(com.auth0.jwt.algorithms.Algorithm) Date(java.util.Date) ZoneOffset(java.time.ZoneOffset)

Example 2 with Clock

use of com.auth0.jwt.interfaces.Clock in project wikidata-query-rdf by wikimedia.

the class TimeLimitedAccessTokenFactoryUnitTest method timeControlledVerifier.

private JWTVerifier timeControlledVerifier(long verifyAtEpochSecond) {
    Clock jwtClock = mock(Clock.class);
    when(jwtClock.getToday()).thenReturn(Date.from(Instant.ofEpochSecond(verifyAtEpochSecond)));
    return ((JWTVerifier.BaseVerification) JWT.require(algo)).build(jwtClock);
}
Also used : Clock(com.auth0.jwt.interfaces.Clock)

Example 3 with Clock

use of com.auth0.jwt.interfaces.Clock in project java-rest-api by messagebird.

the class RequestValidator method validateSignature.

/**
 * Returns raw signature payload after validating a signature successfully,
 * otherwise throws {@code RequestValidationException}.
 * <p>
 * This JWT is signed with a MessageBird account unique secret key, ensuring the request is from MessageBird and
 * a specific account.
 * The JWT contains the following claims:
 * </p>
 * <ul>
 *   <li>"url_hash" - the raw URL hashed with SHA256 ensuring the URL wasn't altered.</li>
 *   <li> "payload_hash" - the raw payload hashed with SHA256 ensuring the payload wasn't altered.</li>
 *   <li> "jti" - a unique token ID to implement an optional non-replay check (NOT validated by default).</li>
 *   <li> "nbf" - the not before timestamp.</li>
 *   <li> "exp" - the expiration timestamp is ensuring that a request isn't captured and used at a later time.</li>
 *   <li> "iss" - the issuer name, always MessageBird.</li>
 * </ul>
 *
 * @param clock       custom {@link Clock} instance to validate timestamp claims.
 * @param signature   the actual signature.
 * @param url         the raw url including the protocol, hostname and query string,
 *                    {@code https://example.com/?example=42}.
 * @param requestBody the raw request body.
 * @return raw signature payload as {@link DecodedJWT} object.
 * @throws RequestValidationException when the signature is invalid.
 * @see <a href="https://developers.messagebird.com/docs/verify-http-requests">Verify HTTP Requests</a>
 */
public DecodedJWT validateSignature(Clock clock, String signature, String url, byte[] requestBody) throws RequestValidationException {
    if (signature == null || signature.length() == 0)
        throw new RequestValidationException("The signature can not be empty.");
    if (!skipURLValidation && (url == null || url.length() == 0))
        throw new RequestValidationException("The url can not be empty.");
    DecodedJWT jwt = JWT.decode(signature);
    Algorithm algorithm;
    switch(jwt.getAlgorithm()) {
        case "HS256":
            algorithm = HMAC256;
            break;
        case "HS384":
            algorithm = HMAC384;
            break;
        case "HS512":
            algorithm = HMAC512;
            break;
        default:
            throw new RequestValidationException(String.format("The signing method '%s' is invalid.", jwt.getAlgorithm()));
    }
    BaseVerification builder = (BaseVerification) JWT.require(algorithm).withIssuer("MessageBird").ignoreIssuedAt().acceptLeeway(1);
    if (!skipURLValidation)
        builder.withClaim("url_hash", calculateSha256(url.getBytes()));
    boolean payloadHashClaimExist = !jwt.getClaim("payload_hash").isNull();
    if (requestBody != null && requestBody.length > 0) {
        if (!payloadHashClaimExist) {
            throw new RequestValidationException("The Claim 'payload_hash' is not set but payload is present.");
        }
        builder.withClaim("payload_hash", calculateSha256(requestBody));
    } else if (payloadHashClaimExist) {
        throw new RequestValidationException("The Claim 'payload_hash' is set but actual payload is missing.");
    }
    JWTVerifier verifier = clock == null ? builder.build() : builder.build(clock);
    try {
        return verifier.verify(jwt);
    } catch (SignatureVerificationException e) {
        throw new RequestValidationException("Signature is invalid.", e);
    } catch (JWTVerificationException e) {
        throw new RequestValidationException(e.getMessage(), e.getCause());
    }
}
Also used : JWTVerificationException(com.auth0.jwt.exceptions.JWTVerificationException) SignatureVerificationException(com.auth0.jwt.exceptions.SignatureVerificationException) RequestValidationException(com.messagebird.exceptions.RequestValidationException) DecodedJWT(com.auth0.jwt.interfaces.DecodedJWT) Algorithm(com.auth0.jwt.algorithms.Algorithm) JWTVerifier(com.auth0.jwt.interfaces.JWTVerifier) BaseVerification(com.auth0.jwt.JWTVerifier.BaseVerification)

Example 4 with Clock

use of com.auth0.jwt.interfaces.Clock in project java-rest-api by messagebird.

the class RequestValidatorTest method testWebhookSignature.

@Test
public void testWebhookSignature() throws Throwable {
    RequestValidator validator = new RequestValidator(testCase.secret != null ? testCase.secret : "");
    Clock clock = mock(Clock.class);
    Date clockDate = spy(Date.from(OffsetDateTime.parse(testCase.timestamp).toInstant()));
    when(clock.getToday()).thenReturn(clockDate);
    ThrowingRunnable runnable = () -> validator.validateSignature(clock, testCase.token, testCase.url, (testCase.payload == null) ? null : testCase.payload.getBytes(StandardCharsets.UTF_8));
    if (testCase.valid) {
        runnable.run();
        return;
    }
    assertTrue(String.format("Expected error message mapping for '%s' but it was not found.", testCase.reason), ERROR_MAP.containsKey(testCase.reason));
    String expectedError = ERROR_MAP.get(testCase.reason);
    RequestValidationException err = assertThrows(RequestValidationException.class, runnable);
    assertTrue(String.format("Expected error message containing: %s (originally %s) but was: %s", expectedError, testCase.reason, err.getMessage()), err.getMessage().contains(expectedError));
}
Also used : Clock(com.auth0.jwt.interfaces.Clock) RequestValidationException(com.messagebird.exceptions.RequestValidationException) ThrowingRunnable(org.junit.function.ThrowingRunnable) Test(org.junit.Test)

Aggregations

Algorithm (com.auth0.jwt.algorithms.Algorithm)2 Clock (com.auth0.jwt.interfaces.Clock)2 RequestValidationException (com.messagebird.exceptions.RequestValidationException)2 JWTCreator (com.auth0.jwt.JWTCreator)1 BaseVerification (com.auth0.jwt.JWTVerifier.BaseVerification)1 JWTVerificationException (com.auth0.jwt.exceptions.JWTVerificationException)1 SignatureVerificationException (com.auth0.jwt.exceptions.SignatureVerificationException)1 DecodedJWT (com.auth0.jwt.interfaces.DecodedJWT)1 JWTVerifier (com.auth0.jwt.interfaces.JWTVerifier)1 LocalDateTime (java.time.LocalDateTime)1 ZoneOffset (java.time.ZoneOffset)1 Date (java.util.Date)1 Test (org.junit.Test)1 ThrowingRunnable (org.junit.function.ThrowingRunnable)1