diff --git a/pom.xml b/pom.xml
index fde6856..d27284f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,18 +28,71 @@
GitHub Actions
https://github.com/ilyalisov/jwt/actions
-
scm:git:git://github.com/ilyalisov/jwt.git
scm:git:ssh://github.com:ilyalisov/jwt.git
https://github.com/ilyalisov/jwt/tree/main
-
17
17
17
UTF-8
+ 0.12.2
+ 1.18.30
+ 3.2.2
-
+
+
+ org.projectlombok
+ lombok
+ true
+ ${lombok.version}
+
+
+ io.jsonwebtoken
+ jjwt-api
+ ${jjwt.version}
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ ${jjwt.version}
+ runtime
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ ${jjwt.version}
+ runtime
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${checkstyle.version}
+
+ sun_checks.xml
+ true
+ true
+ false
+
+
+
+ validate
+ validate
+
+ check
+
+
+ suppressions.xml
+ suppressions.xml
+
+
+
+
+
+
diff --git a/src/main/java/TokenParameters.java b/src/main/java/TokenParameters.java
new file mode 100644
index 0000000..5934e55
--- /dev/null
+++ b/src/main/java/TokenParameters.java
@@ -0,0 +1,145 @@
+import lombok.AccessLevel;
+import lombok.Builder;
+import lombok.Getter;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Builder(
+ builderMethodName = "hiddenBuilder",
+ access = AccessLevel.PRIVATE
+)
+@Getter
+public class TokenParameters {
+
+ /**
+ * A map of claims to be put in JWT token.
+ */
+ private Map claims;
+
+ /**
+ * The "sub" of JWT token.
+ */
+ private String subject;
+
+ /**
+ * Date when JWT token was issued.
+ */
+ private Date issuedAt;
+
+ /**
+ * Date when JWT token will be expired.
+ */
+ private Date expiredAt;
+
+ /**
+ * Creates a builder for TokenParameters.
+ *
+ * @param subject sub of JWT token
+ * @param duration duration between token issuing and expiration date
+ * @return TokenParametersBuilder
+ */
+ public static TokenParametersBuilder builder(
+ final String subject,
+ final Duration duration
+ ) {
+ Date issuedAt = new Date();
+ return hiddenBuilder()
+ .claims(new HashMap<>())
+ .issuedAt(issuedAt)
+ .subject(subject)
+ .expiredAt(new Date(
+ issuedAt.getTime()
+ + 1000 * duration.get(ChronoUnit.SECONDS)
+ ));
+ }
+
+ public static class TokenParametersBuilder {
+
+ /**
+ * Add claims to parameters.
+ *
+ * @param key the key of claim
+ * @param value the value of claim
+ * @return TokenParametersBuilder
+ */
+ public TokenParametersBuilder claim(
+ final String key,
+ final Object value
+ ) {
+ this.claims.put(key, value);
+ return this;
+ }
+
+ /**
+ * Adds claims to parameters.
+ *
+ * @param claims a map of claims
+ * @return TokenParametersBuilder
+ */
+ public TokenParametersBuilder claims(
+ final Map claims
+ ) {
+ this.claims.putAll(claims);
+ return this;
+ }
+
+ /**
+ * Sets issued date for JWT token.
+ *
+ * @param issuedAt date of issuing
+ * @return TokenParametersBuilder
+ */
+ public TokenParametersBuilder issuedAt(
+ final Date issuedAt
+ ) {
+ this.issuedAt = issuedAt;
+ return this;
+ }
+
+ /**
+ * Sets expiration date for JWT token.
+ *
+ * @param expiredAt date of expiration
+ * @return TokenParametersBuilder
+ */
+ public TokenParametersBuilder expiredAt(
+ final Date expiredAt
+ ) {
+ this.expiredAt = expiredAt;
+ return this;
+ }
+
+ /**
+ * Sets subject to parameters.
+ *
+ * @param subject subject of JWT token
+ * @return TokenParametersBuilder
+ */
+ public TokenParametersBuilder subject(
+ final String subject
+ ) {
+ this.subject = subject;
+ return this;
+ }
+
+ /**
+ * Builds final object.
+ *
+ * @return TokenParameters object
+ */
+ public TokenParameters build() {
+ return new TokenParameters(
+ claims,
+ subject,
+ issuedAt,
+ expiredAt
+ );
+ }
+
+ }
+
+}
diff --git a/src/main/java/TokenService.java b/src/main/java/TokenService.java
new file mode 100644
index 0000000..395d7c3
--- /dev/null
+++ b/src/main/java/TokenService.java
@@ -0,0 +1,60 @@
+import java.util.Map;
+
+public interface TokenService {
+
+ /**
+ * Creates JWT token by provided parameters.
+ *
+ * @param params parameters for JWT token
+ * @return JWT token
+ */
+ String create(
+ TokenParameters params
+ );
+
+ /**
+ * Checks whether JWT token is expired by current time.
+ *
+ * @param token JWT token to be checked
+ * @return true - if JWT token expired, false - otherwise
+ */
+ boolean isExpired(
+ String token
+ );
+
+ /**
+ * Checks whether JWT token has a key-value pair in payload.
+ *
+ * @param token JWT token
+ * @param key key of payload
+ * @param value value of payload
+ * @return true - if JWT token has a provided key-value pair in payload,
+ * false - otherwise
+ */
+ boolean has(
+ String token,
+ String key,
+ Object value
+ );
+
+ /**
+ * Returns "sub" of JWT token.
+ *
+ * @param token JWT token
+ * @return "sub" of JWT token
+ */
+ String getSubject(
+ String token
+ );
+
+ /**
+ * Returns payload of JWT token as a Map.
+ *
+ * @param token JWT token
+ * @return a map of key-value pairs from payload
+ */
+ Map claims(
+ String token
+ );
+
+}
diff --git a/src/main/java/TokenServiceImpl.java b/src/main/java/TokenServiceImpl.java
new file mode 100644
index 0000000..766709e
--- /dev/null
+++ b/src/main/java/TokenServiceImpl.java
@@ -0,0 +1,97 @@
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jws;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.security.Keys;
+
+import javax.crypto.SecretKey;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TokenServiceImpl implements TokenService {
+
+ private final SecretKey key;
+
+ /**
+ * Creates TokenServiceImpl object.
+ *
+ * @param secret secret of key for JWT token generation
+ */
+ public TokenServiceImpl(
+ final String secret
+ ) {
+ this.key = Keys.hmacShaKeyFor(secret.getBytes());
+ }
+
+ @Override
+ public String create(
+ final TokenParameters params
+ ) {
+ Claims claims = Jwts.claims()
+ .subject(params.getSubject())
+ .add(params.getClaims())
+ .build();
+ return Jwts.builder()
+ .claims(claims)
+ .issuedAt(params.getIssuedAt())
+ .expiration(params.getExpiredAt())
+ .signWith(key)
+ .compact();
+ }
+
+ @Override
+ public boolean isExpired(
+ final String token
+ ) {
+ Jws claims = Jwts
+ .parser()
+ .verifyWith(key)
+ .build()
+ .parseSignedClaims(token);
+ return claims.getPayload()
+ .getExpiration()
+ .before(new Date());
+ }
+
+ @Override
+ public boolean has(
+ final String token,
+ final String key,
+ final Object value
+ ) {
+ Jws claims = Jwts
+ .parser()
+ .verifyWith(this.key)
+ .build()
+ .parseSignedClaims(token);
+ return claims.getPayload()
+ .get(key)
+ .equals(value);
+ }
+
+ @Override
+ public String getSubject(
+ final String token
+ ) {
+ return Jwts
+ .parser()
+ .verifyWith(key)
+ .build()
+ .parseSignedClaims(token)
+ .getPayload()
+ .getSubject();
+ }
+
+ @Override
+ public Map claims(
+ final String token
+ ) {
+ Jws claims = Jwts
+ .parser()
+ .verifyWith(key)
+ .build()
+ .parseSignedClaims(token);
+ return new HashMap<>(claims.getPayload());
+ }
+
+}
diff --git a/suppressions.xml b/suppressions.xml
new file mode 100644
index 0000000..53fa695
--- /dev/null
+++ b/suppressions.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file