From b7931b120532bf248a0f44e02706c29313c1cc47 Mon Sep 17 00:00:00 2001 From: Avin Buricha Date: Sun, 11 Dec 2022 08:30:01 +0530 Subject: [PATCH] BAEL-5982 | Article code (#13097) * BAEL-5982 | Article code * Renaming unit test methods * Rearranging module list in alphabetic order --- security-modules/jwt/.gitignore | 3 + security-modules/jwt/pom.xml | 28 ++++ .../baeldung/jwt/auth0/Auth0JsonWebToken.java | 99 ++++++++++++++ .../jwt/auth0/Auth0JsonWebTokenUnitTest.java | 127 ++++++++++++++++++ security-modules/pom.xml | 3 +- 5 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 security-modules/jwt/.gitignore create mode 100644 security-modules/jwt/pom.xml create mode 100644 security-modules/jwt/src/main/java/com/baeldung/jwt/auth0/Auth0JsonWebToken.java create mode 100644 security-modules/jwt/src/test/java/com/baeldung/jwt/auth0/Auth0JsonWebTokenUnitTest.java diff --git a/security-modules/jwt/.gitignore b/security-modules/jwt/.gitignore new file mode 100644 index 0000000000..f83e8cf07c --- /dev/null +++ b/security-modules/jwt/.gitignore @@ -0,0 +1,3 @@ +.idea +target +*.iml diff --git a/security-modules/jwt/pom.xml b/security-modules/jwt/pom.xml new file mode 100644 index 0000000000..5ec563dcfa --- /dev/null +++ b/security-modules/jwt/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + jwt + jwt + jar + + + com.baeldung + security-modules + 1.0.0-SNAPSHOT + + + + + com.auth0 + java-jwt + ${auth0-jwt.version} + + + + + 4.2.1 + + + \ No newline at end of file diff --git a/security-modules/jwt/src/main/java/com/baeldung/jwt/auth0/Auth0JsonWebToken.java b/security-modules/jwt/src/main/java/com/baeldung/jwt/auth0/Auth0JsonWebToken.java new file mode 100644 index 0000000000..0d5e7a4839 --- /dev/null +++ b/security-modules/jwt/src/main/java/com/baeldung/jwt/auth0/Auth0JsonWebToken.java @@ -0,0 +1,99 @@ +package com.baeldung.jwt.auth0; + +import java.util.Date; +import java.util.UUID; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; + +public class Auth0JsonWebToken { + + private static final String SECRET = "baeldung"; + private static final String ISSUER = "Baeldung"; + private static final String SUBJECT = "Baeldung Details"; + private static final String DATA_CLAIM = "userId"; + private static final String DATA = "1234"; + private static final long TOKEN_VALIDITY_IN_MILLIS = 5000L; + + private static Algorithm algorithm; + private static JWTVerifier verifier; + + public static void initialize() { + algorithm = Algorithm.HMAC256(SECRET); + + verifier = JWT.require(algorithm) + .withIssuer(ISSUER) + .build(); + } + + private static String createJWT() { + String jwtToken = JWT.create() + .withIssuer(ISSUER) + .withSubject(SUBJECT) + .withClaim(DATA_CLAIM, DATA) + .withIssuedAt(new Date()) + .withExpiresAt(new Date(System.currentTimeMillis() + TOKEN_VALIDITY_IN_MILLIS)) + .withJWTId(UUID.randomUUID() + .toString()) + .withNotBefore(new Date(System.currentTimeMillis() + 1000L)) + .sign(algorithm); + + return jwtToken; + } + + private static DecodedJWT verifyJWT(String jwtToken) { + try { + DecodedJWT decodedJWT = verifier.verify(jwtToken); + return decodedJWT; + } catch (JWTVerificationException e) { + System.out.println(e.getMessage()); + } + return null; + } + + private static boolean isJWTExpired(DecodedJWT decodedJWT) { + Date expiresAt = decodedJWT.getExpiresAt(); + return expiresAt.getTime() < System.currentTimeMillis(); + } + + private static String getClaim(DecodedJWT decodedJWT, String claimName) { + Claim claim = decodedJWT.getClaim(claimName); + return claim != null ? claim.asString() : null; + } + + public static void main(String args[]) throws InterruptedException { + + initialize(); + + String jwtToken = createJWT(); + System.out.println("Created JWT : " + jwtToken); + + DecodedJWT decodedJWT = verifyJWT(jwtToken); + if (decodedJWT == null) { + System.out.println("JWT Verification Failed"); + } + + Thread.sleep(1000L); + + decodedJWT = verifyJWT(jwtToken); + if (decodedJWT != null) { + System.out.println("Token Issued At : " + decodedJWT.getIssuedAt()); + System.out.println("Token Expires At : " + decodedJWT.getExpiresAt()); + System.out.println("Subject : " + decodedJWT.getSubject()); + System.out.println("Data : " + getClaim(decodedJWT, DATA_CLAIM)); + System.out.println("Header : " + decodedJWT.getHeader()); + System.out.println("Payload : " + decodedJWT.getPayload()); + System.out.println("Signature : " + decodedJWT.getSignature()); + System.out.println("Algorithm : " + decodedJWT.getAlgorithm()); + System.out.println("JWT Id : " + decodedJWT.getId()); + + Boolean isExpired = isJWTExpired(decodedJWT); + System.out.println("Is Expired : " + isExpired); + } + } + +} diff --git a/security-modules/jwt/src/test/java/com/baeldung/jwt/auth0/Auth0JsonWebTokenUnitTest.java b/security-modules/jwt/src/test/java/com/baeldung/jwt/auth0/Auth0JsonWebTokenUnitTest.java new file mode 100644 index 0000000000..a9c3b4185d --- /dev/null +++ b/security-modules/jwt/src/test/java/com/baeldung/jwt/auth0/Auth0JsonWebTokenUnitTest.java @@ -0,0 +1,127 @@ +package com.baeldung.jwt.auth0; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Date; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.IncorrectClaimException; +import com.auth0.jwt.exceptions.SignatureVerificationException; +import com.auth0.jwt.exceptions.TokenExpiredException; +import com.auth0.jwt.interfaces.Claim; +import com.auth0.jwt.interfaces.DecodedJWT; + +public class Auth0JsonWebTokenUnitTest { + + private static final String SECRET = "baeldung"; + private static final String SECRET_NEW = "baeldung.com"; + private static final String ISSUER = "Baeldung"; + private static final String DATA_CLAIM = "userId"; + private static final String DATA = "1234"; + + private static Algorithm algorithm; + private static Algorithm algorithmWithDifferentSecret; + private static JWTVerifier verifier; + private static String jwtToken; + + @BeforeAll + public static void setUp() { + algorithm = Algorithm.HMAC256(SECRET); + + algorithmWithDifferentSecret = Algorithm.HMAC256(SECRET_NEW); + + verifier = JWT.require(algorithm) + .withIssuer(ISSUER) + .build(); + } + + private static boolean isJWTExpired(DecodedJWT decodedJWT) { + Date expiresAt = decodedJWT.getExpiresAt(); + return expiresAt.getTime() < System.currentTimeMillis(); + } + + private static DecodedJWT verifyJWT(String jwtToken) { + DecodedJWT decodedJWT = verifier.verify(jwtToken); + return decodedJWT; + } + + @Test + public void givenJWT_whenNotExpired_thenCheckingIfNotExpired() { + + jwtToken = JWT.create() + .withIssuer(ISSUER) + .withClaim(DATA_CLAIM, DATA) + .withExpiresAt(new Date(System.currentTimeMillis() + 1000L)) + .sign(algorithm); + + DecodedJWT decodedJWT = verifyJWT(jwtToken); + assertNotNull(decodedJWT); + assertFalse(isJWTExpired(decodedJWT)); + } + + @Test + public void givenJWT_whenExpired_thenCheckingIfExpired() { + + jwtToken = JWT.create() + .withIssuer(ISSUER) + .withClaim(DATA_CLAIM, DATA) + .withExpiresAt(new Date(System.currentTimeMillis() - 1000L)) + .sign(algorithm); + + assertThrows(TokenExpiredException.class, () -> { + verifyJWT(jwtToken); + }); + } + + @Test + public void givenJWT_whenCreatedWithCustomClaim_thenCheckingForCustomClaim() { + + jwtToken = JWT.create() + .withIssuer(ISSUER) + .withClaim(DATA_CLAIM, DATA) + .withExpiresAt(new Date(System.currentTimeMillis() + 1000L)) + .sign(algorithm); + + DecodedJWT decodedJWT = verifyJWT(jwtToken); + assertNotNull(decodedJWT); + + Claim claim = decodedJWT.getClaim(DATA_CLAIM); + assertEquals(DATA, claim.asString()); + } + + @Test + public void givenJWT_whenCreatedWithNotBefore_thenThrowException() { + + jwtToken = JWT.create() + .withIssuer(ISSUER) + .withClaim(DATA_CLAIM, DATA) + .withNotBefore(new Date(System.currentTimeMillis() + 1000L)) + .sign(algorithm); + + assertThrows(IncorrectClaimException.class, () -> { + verifyJWT(jwtToken); + }); + } + + @Test + public void givenJWT_whenVerifyingUsingDifferentSecret_thenThrowException() { + + jwtToken = JWT.create() + .withIssuer(ISSUER) + .withClaim(DATA_CLAIM, DATA) + .withExpiresAt(new Date(System.currentTimeMillis() + 1000L)) + .sign(algorithmWithDifferentSecret); + + assertThrows(SignatureVerificationException.class, () -> { + verifyJWT(jwtToken); + }); + } +} diff --git a/security-modules/pom.xml b/security-modules/pom.xml index 480ee0819e..1ed081a273 100644 --- a/security-modules/pom.xml +++ b/security-modules/pom.xml @@ -20,8 +20,9 @@ jee-7-security jjwt + jwt oauth2-framework-impl - sql-injection-samples + sql-injection-samples \ No newline at end of file