Skip to content

Commit

Permalink
#2 Implement service
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaLisov committed Jan 17, 2024
1 parent 4a08b32 commit e0ece6c
Show file tree
Hide file tree
Showing 5 changed files with 364 additions and 3 deletions.
59 changes: 56 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,71 @@
<system>GitHub Actions</system>
<url>https://github.com/ilyalisov/jwt/actions</url>
</ciManagement>

<scm>
<connection>scm:git:git://github.com/ilyalisov/jwt.git</connection>
<developerConnection>scm:git:ssh://github.com:ilyalisov/jwt.git</developerConnection>
<url>https://github.com/ilyalisov/jwt/tree/main</url>
</scm>

<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jjwt.version>0.12.2</jjwt.version>
<lombok.version>1.18.30</lombok.version>
<checkstyle.version>3.2.2</checkstyle.version>
</properties>

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jjwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>${jjwt.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${checkstyle.version}</version>
<configuration>
<configLocation>sun_checks.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<linkXRef>false</linkXRef>
</configuration>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<suppressionsFileExpression>suppressions.xml</suppressionsFileExpression>
<suppressionsLocation>suppressions.xml</suppressionsLocation>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
145 changes: 145 additions & 0 deletions src/main/java/TokenParameters.java
Original file line number Diff line number Diff line change
@@ -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<String, Object> 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<String, Object> 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
);
}

}

}
60 changes: 60 additions & 0 deletions src/main/java/TokenService.java
Original file line number Diff line number Diff line change
@@ -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<String, Object> claims(
String token
);

}
97 changes: 97 additions & 0 deletions src/main/java/TokenServiceImpl.java
Original file line number Diff line number Diff line change
@@ -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> 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> 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<String, Object> claims(
final String token
) {
Jws<Claims> claims = Jwts
.parser()
.verifyWith(key)
.build()
.parseSignedClaims(token);
return new HashMap<>(claims.getPayload());
}

}
6 changes: 6 additions & 0 deletions suppressions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN" "https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<suppress checks="JavadocPackage"/>
<suppress checks="MagicNumber"/>
</suppressions>

0 comments on commit e0ece6c

Please sign in to comment.