feat(simple-jwt-jjwt): Complete the implementation with io.jsonwebtoken:jjwt-api
This commit is contained in:
@@ -22,6 +22,7 @@
|
|||||||
<module>guid</module>
|
<module>guid</module>
|
||||||
<module>simple-jwt-facade</module>
|
<module>simple-jwt-facade</module>
|
||||||
<module>simple-jwt-authzero</module>
|
<module>simple-jwt-authzero</module>
|
||||||
|
<module>simple-jwt-jjwt</module>
|
||||||
<module>simple-jwt-spring-boot-starter</module>
|
<module>simple-jwt-spring-boot-starter</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
@@ -70,7 +71,9 @@
|
|||||||
<junit.version>5.10.0</junit.version>
|
<junit.version>5.10.0</junit.version>
|
||||||
<slf4j-api.version>2.0.7</slf4j-api.version>
|
<slf4j-api.version>2.0.7</slf4j-api.version>
|
||||||
<lombok.version>1.18.28</lombok.version>
|
<lombok.version>1.18.28</lombok.version>
|
||||||
|
<jackson.version>2.15.2</jackson.version>
|
||||||
<auth0-jwt.version>4.4.0</auth0-jwt.version>
|
<auth0-jwt.version>4.4.0</auth0-jwt.version>
|
||||||
|
<jjwt-jwt.version>0.11.5</jjwt-jwt.version>
|
||||||
|
|
||||||
<spring.version>x.x.x</spring.version>
|
<spring.version>x.x.x</spring.version>
|
||||||
<spring-boot.version>3.1.0</spring-boot.version>
|
<spring-boot.version>3.1.0</spring-boot.version>
|
||||||
@@ -103,12 +106,44 @@
|
|||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>${jackson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.auth0</groupId>
|
<groupId>com.auth0</groupId>
|
||||||
<artifactId>java-jwt</artifactId>
|
<artifactId>java-jwt</artifactId>
|
||||||
<version>${auth0-jwt.version}</version>
|
<version>${auth0-jwt.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
<version>${jjwt-jwt.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<version>${jjwt-jwt.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<version>${jjwt-jwt.version}</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.org.codecrafters</groupId>
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
<artifactId>devkit-core</artifactId>
|
<artifactId>devkit-core</artifactId>
|
||||||
@@ -121,6 +156,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
|
<artifactId>devkit-utils</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.org.codecrafters</groupId>
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
<artifactId>simple-jwt-facade</artifactId>
|
<artifactId>simple-jwt-facade</artifactId>
|
||||||
@@ -133,6 +174,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
|
<artifactId>simple-jwt-jjwt</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
+7
-4
@@ -23,6 +23,7 @@ import cn.org.codecrafters.simplejwt.TokenPayload;
|
|||||||
import cn.org.codecrafters.simplejwt.TokenResolver;
|
import cn.org.codecrafters.simplejwt.TokenResolver;
|
||||||
import cn.org.codecrafters.simplejwt.annotations.ExcludeFromPayload;
|
import cn.org.codecrafters.simplejwt.annotations.ExcludeFromPayload;
|
||||||
import cn.org.codecrafters.simplejwt.authzero.config.AuthzeroTokenResolverConfig;
|
import cn.org.codecrafters.simplejwt.authzero.config.AuthzeroTokenResolverConfig;
|
||||||
|
import cn.org.codecrafters.simplejwt.config.TokenResolverConfig;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
||||||
import com.auth0.jwt.JWT;
|
import com.auth0.jwt.JWT;
|
||||||
import com.auth0.jwt.JWTCreator;
|
import com.auth0.jwt.JWTCreator;
|
||||||
@@ -124,6 +125,8 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
*/
|
*/
|
||||||
private final JWTVerifier verifier;
|
private final JWTVerifier verifier;
|
||||||
|
|
||||||
|
private final AuthzeroTokenResolverConfig config = AuthzeroTokenResolverConfig.getInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of AuthzeroTokenResolver with the provided
|
* Creates a new instance of AuthzeroTokenResolver with the provided
|
||||||
* configurations.
|
* configurations.
|
||||||
@@ -146,7 +149,7 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.jtiCreator = jtiCreator;
|
this.jtiCreator = jtiCreator;
|
||||||
this.algorithm = AuthzeroTokenResolverConfig.getInstance()
|
this.algorithm = config
|
||||||
.getAlgorithm(algorithm)
|
.getAlgorithm(algorithm)
|
||||||
.apply(secret);
|
.apply(secret);
|
||||||
this.issuer = issuer;
|
this.issuer = issuer;
|
||||||
@@ -172,7 +175,7 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.jtiCreator = (GuidCreator<UUID>) UUID::randomUUID;
|
this.jtiCreator = (GuidCreator<UUID>) UUID::randomUUID;
|
||||||
this.algorithm = AuthzeroTokenResolverConfig.getInstance()
|
this.algorithm = config
|
||||||
.getAlgorithm(algorithm)
|
.getAlgorithm(algorithm)
|
||||||
.apply(secret);
|
.apply(secret);
|
||||||
this.issuer = issuer;
|
this.issuer = issuer;
|
||||||
@@ -197,7 +200,7 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.jtiCreator = (GuidCreator<UUID>) UUID::randomUUID;
|
this.jtiCreator = (GuidCreator<UUID>) UUID::randomUUID;
|
||||||
this.algorithm = AuthzeroTokenResolverConfig.getInstance()
|
this.algorithm = config
|
||||||
.getAlgorithm(TokenAlgorithm.HS256)
|
.getAlgorithm(TokenAlgorithm.HS256)
|
||||||
.apply(secret);
|
.apply(secret);
|
||||||
this.issuer = issuer;
|
this.issuer = issuer;
|
||||||
@@ -214,7 +217,7 @@ public class AuthzeroTokenResolver implements TokenResolver<DecodedJWT> {
|
|||||||
var secret = SecretCreator.createSecret(32, true, true, true);
|
var secret = SecretCreator.createSecret(32, true, true, true);
|
||||||
|
|
||||||
this.jtiCreator = (GuidCreator<UUID>) UUID::randomUUID;
|
this.jtiCreator = (GuidCreator<UUID>) UUID::randomUUID;
|
||||||
this.algorithm = AuthzeroTokenResolverConfig.getInstance()
|
this.algorithm = config
|
||||||
.getAlgorithm(TokenAlgorithm.HS256)
|
.getAlgorithm(TokenAlgorithm.HS256)
|
||||||
.apply(secret);
|
.apply(secret);
|
||||||
this.issuer = issuer;
|
this.issuer = issuer;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package cn.org.codecrafters.simplejwt;
|
package cn.org.codecrafters.simplejwt;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ import java.util.Map;
|
|||||||
* The {@code TokenResolver} interface defines methods for creating,
|
* The {@code TokenResolver} interface defines methods for creating,
|
||||||
* extracting, and renewing tokens, particularly JSON Web Tokens (JWTs). It
|
* extracting, and renewing tokens, particularly JSON Web Tokens (JWTs). It
|
||||||
* provides a set of methods to generate tokens with various payload
|
* provides a set of methods to generate tokens with various payload
|
||||||
* configurations, extract payloads from tokens, and renew expired tokens.
|
* configurations, extract payload from tokens, and renew expired tokens.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <b>Token Creation:</b>
|
* <b>Token Creation:</b>
|
||||||
@@ -72,10 +73,10 @@ public interface TokenResolver<ResolvedTokenType> {
|
|||||||
* @param expireAfter the duration after which the token will expire
|
* @param expireAfter the duration after which the token will expire
|
||||||
* @param subject the subject of the token
|
* @param subject the subject of the token
|
||||||
* @param audience the audience for which the token is intended
|
* @param audience the audience for which the token is intended
|
||||||
* @param payloads the custom payload data to be included in the token
|
* @param payload the custom payload data to be included in the token
|
||||||
* @return the generated token as a {@code String}
|
* @return the generated token as a {@code String}
|
||||||
*/
|
*/
|
||||||
String createToken(Duration expireAfter, String audience, String subject, Map<String, Object> payloads);
|
String createToken(Duration expireAfter, String audience, String subject, Map<String, Object> payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new token with the specified expiration time, subject,
|
* Creates a new token with the specified expiration time, subject,
|
||||||
@@ -113,16 +114,6 @@ public interface TokenResolver<ResolvedTokenType> {
|
|||||||
*/
|
*/
|
||||||
<T extends TokenPayload> T extract(String token, Class<T> targetType);
|
<T extends TokenPayload> T extract(String token, Class<T> targetType);
|
||||||
|
|
||||||
/**
|
|
||||||
* Renews the given expired token with the specified custom payload data.
|
|
||||||
*
|
|
||||||
* @param oldToken the expired token to be renewed
|
|
||||||
* @param payload the custom payload data to be included in the renewed
|
|
||||||
* token
|
|
||||||
* @return the renewed token as a {@code String}
|
|
||||||
*/
|
|
||||||
String renew(String oldToken, Map<String, Object> payload);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renews the given expired token with the specified custom payload data.
|
* Renews the given expired token with the specified custom payload data.
|
||||||
*
|
*
|
||||||
@@ -134,6 +125,16 @@ public interface TokenResolver<ResolvedTokenType> {
|
|||||||
*/
|
*/
|
||||||
String renew(String oldToken, Duration expireAfter, Map<String, Object> payload);
|
String renew(String oldToken, Duration expireAfter, Map<String, Object> payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews the given expired token with the specified custom payload data.
|
||||||
|
*
|
||||||
|
* @param oldToken the expired token to be renewed
|
||||||
|
* @param payload the custom payload data to be included in the renewed
|
||||||
|
* token
|
||||||
|
* @return the renewed token as a {@code String}
|
||||||
|
*/
|
||||||
|
String renew(String oldToken, Map<String, Object> payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renews the given expired token with the specified strongly-typed
|
* Renews the given expired token with the specified strongly-typed
|
||||||
* payload data.
|
* payload data.
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2023 CodeCraftersCN.
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
|
<artifactId>jdevkit</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>simple-jwt-jjwt</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
|
<artifactId>devkit-utils</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
|
<artifactId>simple-jwt-facade</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
+313
@@ -0,0 +1,313 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 CodeCraftersCN.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.org.codecrafters.simplejwt.jjwt;
|
||||||
|
|
||||||
|
import cn.org.codecrafters.devkit.utils.MapUtil;
|
||||||
|
import cn.org.codecrafters.guid.GuidCreator;
|
||||||
|
import cn.org.codecrafters.simplejwt.SecretCreator;
|
||||||
|
import cn.org.codecrafters.simplejwt.TokenPayload;
|
||||||
|
import cn.org.codecrafters.simplejwt.TokenResolver;
|
||||||
|
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
||||||
|
import cn.org.codecrafters.simplejwt.exceptions.WeakSecretException;
|
||||||
|
import cn.org.codecrafters.simplejwt.jjwt.config.JjwtTokenResolverConfig;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jws;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JjwtTokenResolver
|
||||||
|
*
|
||||||
|
* @author Zihlu Wang
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
|
||||||
|
|
||||||
|
private final GuidCreator<?> jtiCreator;
|
||||||
|
|
||||||
|
private final SignatureAlgorithm algorithm;
|
||||||
|
|
||||||
|
private final String issuer;
|
||||||
|
|
||||||
|
private final Key key;
|
||||||
|
|
||||||
|
private final JjwtTokenResolverConfig config = JjwtTokenResolverConfig.getInstance();
|
||||||
|
|
||||||
|
public JjwtTokenResolver(GuidCreator<?> jtiCreator, TokenAlgorithm algorithm, String issuer, String secret) {
|
||||||
|
if (secret == null || secret.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("A secret is required to build a JSON Web Token.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secret.length() <= 32) {
|
||||||
|
log.error("""
|
||||||
|
The provided secret which owns {} characters is too weak. Please replace it with a stronger one.
|
||||||
|
""", secret.length());
|
||||||
|
throw new WeakSecretException("""
|
||||||
|
The provided secret which owns %s characters is too weak. Please replace it with a stronger one.
|
||||||
|
""".formatted(secret.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.jtiCreator = jtiCreator;
|
||||||
|
this.algorithm = config.getAlgorithm(algorithm);
|
||||||
|
this.issuer = issuer;
|
||||||
|
this.key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JjwtTokenResolver(TokenAlgorithm algorithm, String issuer, String secret) {
|
||||||
|
if (secret == null || secret.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("A secret is required to build a JSON Web Token.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secret.length() <= 32) {
|
||||||
|
log.error("""
|
||||||
|
The provided secret which owns {} characters is too weak. Please replace it with a stronger one.
|
||||||
|
""", secret.length());
|
||||||
|
throw new WeakSecretException("""
|
||||||
|
The provided secret which owns %s characters is too weak. Please replace it with a stronger one.
|
||||||
|
""".formatted(secret.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.jtiCreator = UUID::randomUUID;
|
||||||
|
this.algorithm = config.getAlgorithm(algorithm);
|
||||||
|
this.issuer = issuer;
|
||||||
|
this.key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JjwtTokenResolver(String issuer, String secret) {
|
||||||
|
if (secret == null || secret.isBlank()) {
|
||||||
|
throw new IllegalArgumentException("A secret is required to build a JSON Web Token.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secret.length() <= 32) {
|
||||||
|
log.error("""
|
||||||
|
The provided secret which owns {} characters is too weak. Please replace it with a stronger one.
|
||||||
|
""", secret.length());
|
||||||
|
throw new WeakSecretException("""
|
||||||
|
The provided secret which owns %s characters is too weak. Please replace it with a stronger one.
|
||||||
|
""".formatted(secret.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.jtiCreator = UUID::randomUUID;
|
||||||
|
this.algorithm = config.getAlgorithm(TokenAlgorithm.HS256);
|
||||||
|
this.issuer = issuer;
|
||||||
|
this.key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JjwtTokenResolver(String issuer) {
|
||||||
|
this.jtiCreator = UUID::randomUUID;
|
||||||
|
this.algorithm = config.getAlgorithm(TokenAlgorithm.HS256);
|
||||||
|
this.issuer = issuer;
|
||||||
|
this.key = Keys.hmacShaKeyFor(SecretCreator.createSecret(32, true, true, true).getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildToken(Duration expireAfter, String audience, String subject, LocalDateTime now, Map<String, Object> claims) {
|
||||||
|
var builder = Jwts.builder()
|
||||||
|
.setHeaderParam("typ", "JWT")
|
||||||
|
.setIssuedAt(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()))
|
||||||
|
.setNotBefore(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()))
|
||||||
|
.setExpiration(Date.from(now.plus(expireAfter).atZone(ZoneId.systemDefault()).toInstant()))
|
||||||
|
.setSubject(subject)
|
||||||
|
.setAudience(audience)
|
||||||
|
.setIssuer(this.issuer)
|
||||||
|
.setId(jtiCreator.nextId().toString());
|
||||||
|
|
||||||
|
if (claims != null && !claims.isEmpty()) {
|
||||||
|
builder.setClaims(claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.signWith(key, algorithm)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new token with the specified expiration time, subject, and
|
||||||
|
* audience.
|
||||||
|
*
|
||||||
|
* @param expireAfter the duration after which the token will expire
|
||||||
|
* @param audience the audience for which the token is intended
|
||||||
|
* @param subject the subject of the token
|
||||||
|
* @return the generated token as a {@code String}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String createToken(Duration expireAfter, String audience, String subject) {
|
||||||
|
var now = LocalDateTime.now();
|
||||||
|
return buildToken(expireAfter, audience, subject, now, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new token with the specified expiration time, subject,
|
||||||
|
* audience, and custom payload data.
|
||||||
|
*
|
||||||
|
* @param expireAfter the duration after which the token will expire
|
||||||
|
* @param audience the audience for which the token is intended
|
||||||
|
* @param subject the subject of the token
|
||||||
|
* @param payload the custom payload data to be included in the token
|
||||||
|
* @return the generated token as a {@code String}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String createToken(Duration expireAfter, String audience, String subject, Map<String, Object> payload) {
|
||||||
|
var now = LocalDateTime.now();
|
||||||
|
return buildToken(expireAfter, audience, subject, now, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new token with the specified expiration time, subject,
|
||||||
|
* audience, and strongly-typed payload data.
|
||||||
|
*
|
||||||
|
* @param expireAfter the duration after which the token will expire
|
||||||
|
* @param audience the audience for which the token is intended
|
||||||
|
* @param subject the subject of the token
|
||||||
|
* @param payload the strongly-typed payload data to be included in the
|
||||||
|
* token
|
||||||
|
* @return the generated token as a {@code String} or {@code null} if
|
||||||
|
* creation fails
|
||||||
|
* @see MapUtil#objectToMap(Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <T extends TokenPayload> String createToken(Duration expireAfter, String audience, String subject, T payload) {
|
||||||
|
var now = LocalDateTime.now();
|
||||||
|
try {
|
||||||
|
var claims = MapUtil.objectToMap(payload);
|
||||||
|
return buildToken(expireAfter, audience, subject, now, claims);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error("An error occurs while accessing the fields of the object");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the given token into a ResolvedTokenType object.
|
||||||
|
*
|
||||||
|
* @param token the token to be resolved
|
||||||
|
* @return a ResolvedTokenType object
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Jws<Claims> resolve(String token) {
|
||||||
|
return Jwts.parserBuilder()
|
||||||
|
.setSigningKey(key)
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the payload information from the given token and maps it to the
|
||||||
|
* specified target type.
|
||||||
|
*
|
||||||
|
* @param token the token from which to extract the payload
|
||||||
|
* @param targetType the target class representing the payload data type
|
||||||
|
* @return an instance of the specified target type with the extracted
|
||||||
|
* payload data, or {@code null} if extraction fails.
|
||||||
|
* @see MapUtil#mapToObject(Map, Class)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <T extends TokenPayload> T extract(String token, Class<T> targetType) {
|
||||||
|
var resolvedToken = resolve(token);
|
||||||
|
|
||||||
|
var claims = resolvedToken.getBody();
|
||||||
|
try {
|
||||||
|
return MapUtil.mapToObject(claims, targetType);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
log.info("An error occurs while invoking the constructor of type {}.", targetType.getCanonicalName());
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
log.error("The constructor of the required type {} is not found.", targetType.getCanonicalName());
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
log.error("The required type {} is abstract or an interface.", targetType.getCanonicalName());
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error("An error occurs while accessing the fields of the object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews the given expired token with the specified custom payload data.
|
||||||
|
*
|
||||||
|
* @param oldToken the expired token to be renewed
|
||||||
|
* @param expireAfter specify when does the new token invalid
|
||||||
|
* @param payload the custom payload data to be included in the renewed
|
||||||
|
* token
|
||||||
|
* @return the renewed token as a {@code String}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String renew(String oldToken, Duration expireAfter, Map<String, Object> payload) {
|
||||||
|
var resolvedTokenClaims = resolve(oldToken).getBody();
|
||||||
|
var audience = resolvedTokenClaims.getAudience();
|
||||||
|
var subject = resolvedTokenClaims.getSubject();
|
||||||
|
|
||||||
|
return createToken(expireAfter, audience, subject, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews the given expired token with the specified custom payload data.
|
||||||
|
*
|
||||||
|
* @param oldToken the expired token to be renewed
|
||||||
|
* @param payload the custom payload data to be included in the renewed
|
||||||
|
* token
|
||||||
|
* @return the renewed token as a {@code String}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String renew(String oldToken, Map<String, Object> payload) {
|
||||||
|
return renew(oldToken, Duration.ofMinutes(30), payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews the given expired token with the specified strongly-typed
|
||||||
|
* payload data.
|
||||||
|
*
|
||||||
|
* @param oldToken the expired token to be renewed
|
||||||
|
* @param expireAfter specify when does the new token invalid
|
||||||
|
* @param payload the strongly-typed payload data to be included in the
|
||||||
|
* renewed token
|
||||||
|
* @return the renewed token as a {@code String}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <T extends TokenPayload> String renew(String oldToken, Duration expireAfter, T payload) {
|
||||||
|
var resolvedTokenClaims = resolve(oldToken).getBody();
|
||||||
|
var audience = resolvedTokenClaims.getAudience();
|
||||||
|
var subject = resolvedTokenClaims.getSubject();
|
||||||
|
|
||||||
|
return createToken(expireAfter, audience, subject, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews the given expired token with the specified strongly-typed
|
||||||
|
* payload data.
|
||||||
|
*
|
||||||
|
* @param oldToken the expired token to be renewed
|
||||||
|
* @param payload the strongly-typed payload data to be included in the
|
||||||
|
* renewed token
|
||||||
|
* @return the renewed token as a {@code String}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <T extends TokenPayload> String renew(String oldToken, T payload) {
|
||||||
|
return renew(oldToken, Duration.ofMinutes(30), payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 CodeCraftersCN.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.org.codecrafters.simplejwt.jjwt.config;
|
||||||
|
|
||||||
|
import cn.org.codecrafters.simplejwt.config.TokenResolverConfig;
|
||||||
|
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
||||||
|
import cn.org.codecrafters.simplejwt.exceptions.UnsupportedAlgorithmException;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JjwtTokenResolverConfig
|
||||||
|
*
|
||||||
|
* @author Zihlu Wang
|
||||||
|
*/
|
||||||
|
public final class JjwtTokenResolverConfig implements TokenResolverConfig<SignatureAlgorithm> {
|
||||||
|
|
||||||
|
private JjwtTokenResolverConfig() {}
|
||||||
|
|
||||||
|
private static final Map<TokenAlgorithm, SignatureAlgorithm> SUPPORTED_ALGORITHMS = new HashMap<>() {{
|
||||||
|
put(TokenAlgorithm.HS256, SignatureAlgorithm.HS256);
|
||||||
|
put(TokenAlgorithm.HS384, SignatureAlgorithm.HS384);
|
||||||
|
put(TokenAlgorithm.HS512, SignatureAlgorithm.HS512);
|
||||||
|
}};
|
||||||
|
|
||||||
|
private static JjwtTokenResolverConfig instance;
|
||||||
|
|
||||||
|
public static JjwtTokenResolverConfig getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new JjwtTokenResolverConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the algorithm function corresponding to the specified
|
||||||
|
* TokenAlgorithm.
|
||||||
|
* <p>
|
||||||
|
* This method returns the algorithm function associated with the given
|
||||||
|
* TokenAlgorithm. The provided TokenAlgorithm represents the specific
|
||||||
|
* algorithm for which the corresponding algorithm function is required.
|
||||||
|
* The returned AlgorithmFunction represents the function implementation
|
||||||
|
* that can be used by the TokenResolver to handle the specific algorithm.
|
||||||
|
*
|
||||||
|
* @param algorithm the TokenAlgorithm for which the algorithm function is
|
||||||
|
* required
|
||||||
|
* @return the algorithm function associated with the given TokenAlgorithm
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SignatureAlgorithm getAlgorithm(TokenAlgorithm algorithm) {
|
||||||
|
if (!SUPPORTED_ALGORITHMS.containsKey(algorithm)) {
|
||||||
|
throw new UnsupportedAlgorithmException("""
|
||||||
|
The request algorithm is not supported by our system yet. Please change to supported ones.
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
return SUPPORTED_ALGORITHMS.get(algorithm);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,12 +40,42 @@
|
|||||||
<artifactId>simple-jwt-facade</artifactId>
|
<artifactId>simple-jwt-facade</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.auth0</groupId>
|
||||||
|
<artifactId>java-jwt</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.org.codecrafters</groupId>
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
<artifactId>simple-jwt-authzero</artifactId>
|
<artifactId>simple-jwt-authzero</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.org.codecrafters</groupId>
|
||||||
|
<artifactId>simple-jwt-jjwt</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
|
|||||||
+11
-11
@@ -34,10 +34,9 @@ import org.springframework.context.annotation.Bean;
|
|||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* SimpleJwtAutoConfiguration is responsible for automatically configuring the
|
* SimpleJwtAutoConfiguration is responsible for automatically configuring the
|
||||||
* Simple JWT library when used in a Spring Boot application. It provides
|
* Simple JWT library with {@code com.auth0:java-jwt} when used in a Spring
|
||||||
* default settings and configurations to ensure that the library works
|
* Boot application. It provides default settings and configurations to ensure
|
||||||
* smoothly without requiring manual configuration.
|
* that the library works smoothly without requiring manual configuration.
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This auto-configuration class sets up the necessary beans and components
|
* This auto-configuration class sets up the necessary beans and components
|
||||||
@@ -45,7 +44,6 @@ import org.springframework.context.annotation.Bean;
|
|||||||
* configures the {@link TokenResolver} bean based on the available options and
|
* configures the {@link TokenResolver} bean based on the available options and
|
||||||
* properties.
|
* properties.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* <p>
|
* <p>
|
||||||
* Developers using the Simple JWT library with Spring Boot do not need to
|
* Developers using the Simple JWT library with Spring Boot do not need to
|
||||||
* explicitly configure the library, as the auto-configuration takes care of
|
* explicitly configure the library, as the auto-configuration takes care of
|
||||||
@@ -61,7 +59,9 @@ import org.springframework.context.annotation.Bean;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
@EnableConfigurationProperties(value = {SimpleJwtProperties.class})
|
@EnableConfigurationProperties(value = {SimpleJwtProperties.class})
|
||||||
public class SimpleJwtAutoConfiguration {
|
@ConditionalOnClass({DecodedJWT.class, AuthzeroTokenResolver.class})
|
||||||
|
@ConditionalOnMissingBean({TokenResolver.class})
|
||||||
|
public class AuthzeroTokenResolverAutoConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GuidCreator instance to be used for generating JWT IDs (JTI).
|
* The GuidCreator instance to be used for generating JWT IDs (JTI).
|
||||||
@@ -81,7 +81,7 @@ public class SimpleJwtAutoConfiguration {
|
|||||||
* @param simpleJwtProperties the SimpleJwtProperties instance
|
* @param simpleJwtProperties the SimpleJwtProperties instance
|
||||||
*/
|
*/
|
||||||
@Autowired
|
@Autowired
|
||||||
public SimpleJwtAutoConfiguration(SimpleJwtProperties simpleJwtProperties, GuidCreator<?> jtiCreator) {
|
public AuthzeroTokenResolverAutoConfiguration(SimpleJwtProperties simpleJwtProperties, GuidCreator<?> jtiCreator) {
|
||||||
this.jtiCreator = jtiCreator;
|
this.jtiCreator = jtiCreator;
|
||||||
this.simpleJwtProperties = simpleJwtProperties;
|
this.simpleJwtProperties = simpleJwtProperties;
|
||||||
}
|
}
|
||||||
@@ -96,14 +96,14 @@ public class SimpleJwtAutoConfiguration {
|
|||||||
* @return the {@link TokenResolver} instance
|
* @return the {@link TokenResolver} instance
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnClass({DecodedJWT.class, AuthzeroTokenResolver.class})
|
|
||||||
@ConditionalOnMissingBean({TokenResolver.class})
|
|
||||||
@ConditionalOnBean(value = {GuidCreator.class}, name = "jtiCreator")
|
@ConditionalOnBean(value = {GuidCreator.class}, name = "jtiCreator")
|
||||||
public TokenResolver<DecodedJWT> tokenResolver() {
|
public TokenResolver<DecodedJWT> tokenResolver() {
|
||||||
return new AuthzeroTokenResolver(this.jtiCreator,
|
return new AuthzeroTokenResolver(
|
||||||
|
jtiCreator,
|
||||||
simpleJwtProperties.algorithm(),
|
simpleJwtProperties.algorithm(),
|
||||||
simpleJwtProperties.issuer(),
|
simpleJwtProperties.issuer(),
|
||||||
simpleJwtProperties.secret());
|
simpleJwtProperties.secret()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 CodeCraftersCN.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cn.org.codecrafters.simplejwt.autoconfiguration;
|
||||||
|
|
||||||
|
import cn.org.codecrafters.guid.GuidCreator;
|
||||||
|
import cn.org.codecrafters.simplejwt.TokenResolver;
|
||||||
|
import cn.org.codecrafters.simplejwt.authzero.AuthzeroTokenResolver;
|
||||||
|
import cn.org.codecrafters.simplejwt.autoconfiguration.properties.SimpleJwtProperties;
|
||||||
|
import cn.org.codecrafters.simplejwt.jjwt.JjwtTokenResolver;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jws;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* JjwtTokenResolverAutoConfiguration is responsible for automatically
|
||||||
|
* configuring the Simple JWT library with {@code io.jsonwebtoken:jjwt-api}
|
||||||
|
* when used in a Spring Boot application. It provides default settings and
|
||||||
|
* configurations to ensure that the library works smoothly without requiring
|
||||||
|
* manual configuration.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This auto-configuration class sets up the necessary beans and components
|
||||||
|
* required for JWT generation and validation. It automatically creates and
|
||||||
|
* configures the {@link TokenResolver} bean based on the available options and
|
||||||
|
* properties.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Developers using the Simple JWT library with Spring Boot do not need to
|
||||||
|
* explicitly configure the library, as the auto-configuration takes care of
|
||||||
|
* setting up the necessary components and configurations automatically.
|
||||||
|
* However, developers still have the flexibility to customize the behavior of
|
||||||
|
* the library by providing their own configurations and properties.
|
||||||
|
*
|
||||||
|
* @author Zihlu Wang
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@AutoConfiguration
|
||||||
|
@EnableConfigurationProperties(value = {SimpleJwtProperties.class})
|
||||||
|
@ConditionalOnClass({Jws.class, Claims.class, JjwtTokenResolver.class})
|
||||||
|
@ConditionalOnMissingBean({TokenResolver.class})
|
||||||
|
public class JjwtTokenResolverAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GuidCreator instance to be used for generating JWT IDs (JTI).
|
||||||
|
*/
|
||||||
|
private final GuidCreator<?> jtiCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code SimpleJwtProperties} instance containing the configuration
|
||||||
|
* properties for Simple JWT.
|
||||||
|
*/
|
||||||
|
private final SimpleJwtProperties simpleJwtProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@code SimpleJwtAutoConfiguration} instance with the
|
||||||
|
* provided SimpleJwtProperties.
|
||||||
|
*
|
||||||
|
* @param simpleJwtProperties the SimpleJwtProperties instance
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
public JjwtTokenResolverAutoConfiguration(SimpleJwtProperties simpleJwtProperties, GuidCreator<?> jtiCreator) {
|
||||||
|
this.jtiCreator = jtiCreator;
|
||||||
|
this.simpleJwtProperties = simpleJwtProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link TokenResolver} bean using {@link
|
||||||
|
* JjwtTokenResolver} if no existing {@link TokenResolver} bean is
|
||||||
|
* found. The {@link JjwtTokenResolver} is configured with the
|
||||||
|
* provided {@link GuidCreator}, {@code algorithm}, {@code issuer}, and
|
||||||
|
* {@code secret} properties from {@link SimpleJwtProperties}.
|
||||||
|
*
|
||||||
|
* @return the {@link TokenResolver} instance
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(value = {GuidCreator.class}, name = "jtiCreator")
|
||||||
|
public TokenResolver<Jws<Claims>> tokenResolver() {
|
||||||
|
return new JjwtTokenResolver(
|
||||||
|
jtiCreator,
|
||||||
|
simpleJwtProperties.algorithm(),
|
||||||
|
simpleJwtProperties.issuer(),
|
||||||
|
simpleJwtProperties.secret()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+13
-7
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package cn.org.codecrafters.simplejwt.autoconfiguration.properties;
|
package cn.org.codecrafters.simplejwt.autoconfiguration.properties;
|
||||||
|
|
||||||
|
import cn.org.codecrafters.simplejwt.SecretCreator;
|
||||||
|
import cn.org.codecrafters.simplejwt.autoconfiguration.AuthzeroTokenResolverAutoConfiguration;
|
||||||
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
import cn.org.codecrafters.simplejwt.constants.TokenAlgorithm;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
@@ -32,7 +34,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
* <p>
|
* <p>
|
||||||
* SimpleJwtProperties provides configuration options for the JWT algorithm,
|
* SimpleJwtProperties provides configuration options for the JWT algorithm,
|
||||||
* issuer, and secret. The properties are used by the {@link
|
* issuer, and secret. The properties are used by the {@link
|
||||||
* cn.org.codecrafters.simplejwt.autoconfiguration.SimpleJwtAutoConfiguration}
|
* AuthzeroTokenResolverAutoConfiguration}
|
||||||
* class to set up the necessary configurations for JWT generation and
|
* class to set up the necessary configurations for JWT generation and
|
||||||
* validation.
|
* validation.
|
||||||
*
|
*
|
||||||
@@ -51,19 +53,23 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
public class SimpleJwtProperties {
|
public class SimpleJwtProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The algorithm used for JWT generation and validation.
|
* The algorithm used for JWT generation and validation. Default value is
|
||||||
|
* {@link TokenAlgorithm#HS256}
|
||||||
*/
|
*/
|
||||||
private TokenAlgorithm algorithm;
|
private TokenAlgorithm algorithm = TokenAlgorithm.HS256;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The issuer value to be included in the generated JWT.
|
* The issuer value to be included in the generated JWT. Default value is
|
||||||
|
* an empty String.
|
||||||
*/
|
*/
|
||||||
private String issuer;
|
private String issuer = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The secret key used for JWT generation and validation.
|
* The secret key used for JWT generation and validation. Default value is
|
||||||
|
* the result of call to {@link
|
||||||
|
* SecretCreator#createSecret(int, boolean, boolean, boolean)}.
|
||||||
*/
|
*/
|
||||||
private String secret;
|
private String secret = SecretCreator.createSecret(32, true, true, true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the JWT algorithm configured in the properties.
|
* Returns the JWT algorithm configured in the properties.
|
||||||
|
|||||||
+2
-1
@@ -1,2 +1,3 @@
|
|||||||
cn.org.codecrafters.simplejwt.autoconfiguration.GuidAutoConfiguration
|
cn.org.codecrafters.simplejwt.autoconfiguration.GuidAutoConfiguration
|
||||||
cn.org.codecrafters.simplejwt.autoconfiguration.SimpleJwtAutoConfiguration
|
cn.org.codecrafters.simplejwt.autoconfiguration.AuthzeroTokenResolverAutoConfiguration
|
||||||
|
cn.org.codecrafters.simplejwt.autoconfiguration.JjwtTokenResolverAutoConfiguration
|
||||||
Reference in New Issue
Block a user