wip
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
package com.ddf.vodsystem;
|
package com.ddf.vodsystem;
|
||||||
|
|
||||||
|
import com.ddf.vodsystem.dto.properties.AuthProperties;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
|
@EnableConfigurationProperties(AuthProperties.class)
|
||||||
public class VodSystemApplication {
|
public class VodSystemApplication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.util.Optional;
|
|||||||
public class UserController {
|
public class UserController {
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
@Value("${jwt.expiration}")
|
@Value("${app.security.expiration.jwt}")
|
||||||
private long jwtExpiration;
|
private long jwtExpiration;
|
||||||
private static final String SUCCESS = "success";
|
private static final String SUCCESS = "success";
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.ddf.vodsystem.dto.properties;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
@Validated
|
||||||
|
@ConfigurationProperties(prefix = "app.security")
|
||||||
|
public record AuthProperties (
|
||||||
|
@NotBlank @Size(min = 32) String jwtSecret,
|
||||||
|
@Valid @NotNull Expiration expiration
|
||||||
|
) {
|
||||||
|
public record Expiration (
|
||||||
|
@NotNull Duration jwt,
|
||||||
|
@NotNull Duration refreshToken,
|
||||||
|
@NotNull Duration tokenFamily
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.ddf.vodsystem.security;
|
||||||
|
|
||||||
|
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
|
||||||
|
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||||
|
import com.google.api.client.json.gson.GsonFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class GoogleAuthConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the verifier used to validate Google ID tokens issued for this application's client ID.
|
||||||
|
*
|
||||||
|
* @param googleClientId the OAuth client ID that tokens must be issued for
|
||||||
|
* @return the configured {@link GoogleIdTokenVerifier}
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public GoogleIdTokenVerifier googleIdTokenVerifier(
|
||||||
|
@Value("${spring.security.oauth2.client.registration.google.client-id}") String googleClientId) {
|
||||||
|
return new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new GsonFactory())
|
||||||
|
.setAudience(Collections.singletonList(googleClientId))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import com.auth0.jwt.algorithms.Algorithm;
|
|||||||
import com.auth0.jwt.exceptions.JWTDecodeException;
|
import com.auth0.jwt.exceptions.JWTDecodeException;
|
||||||
import com.auth0.jwt.exceptions.TokenExpiredException;
|
import com.auth0.jwt.exceptions.TokenExpiredException;
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
import com.ddf.vodsystem.dto.properties.AuthProperties;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.security.oauth2.jwt.JwtException;
|
import org.springframework.security.oauth2.jwt.JwtException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -20,10 +21,9 @@ public class JwtService {
|
|||||||
private static final String USER_ID_CLAIM = "userId";
|
private static final String USER_ID_CLAIM = "userId";
|
||||||
private static final String ISSUER = "vodsystem";
|
private static final String ISSUER = "vodsystem";
|
||||||
|
|
||||||
public JwtService(@Value("${jwt.secret.key}") String jwtSecretKey,
|
public JwtService(AuthProperties props) {
|
||||||
@Value("${jwt.expiration}") long jwtExpiration) {
|
this.jwtExpiration = props.expiration().jwt().toMillis();
|
||||||
this.jwtExpiration = jwtExpiration;
|
this.algorithm = Algorithm.HMAC256(props.jwtSecret());
|
||||||
this.algorithm = Algorithm.HMAC256(jwtSecretKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.ddf.vodsystem.services;
|
package com.ddf.vodsystem.services;
|
||||||
|
|
||||||
import com.ddf.vodsystem.dto.TokenPackage;
|
import com.ddf.vodsystem.dto.TokenPackage;
|
||||||
|
import com.ddf.vodsystem.dto.properties.AuthProperties;
|
||||||
import com.ddf.vodsystem.entities.RefreshToken;
|
import com.ddf.vodsystem.entities.RefreshToken;
|
||||||
import com.ddf.vodsystem.entities.TokenFamily;
|
import com.ddf.vodsystem.entities.TokenFamily;
|
||||||
import com.ddf.vodsystem.entities.User;
|
import com.ddf.vodsystem.entities.User;
|
||||||
@@ -9,11 +10,7 @@ import com.ddf.vodsystem.repositories.UserRepository;
|
|||||||
import com.ddf.vodsystem.security.JwtService;
|
import com.ddf.vodsystem.security.JwtService;
|
||||||
import com.ddf.vodsystem.security.TokenService;
|
import com.ddf.vodsystem.security.TokenService;
|
||||||
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
|
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
|
||||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
|
||||||
import com.google.api.client.json.JsonFactory;
|
|
||||||
import com.google.api.client.json.gson.GsonFactory;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
|
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
|
||||||
@@ -24,7 +21,6 @@ import java.security.GeneralSecurityException;
|
|||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HexFormat;
|
import java.util.HexFormat;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -34,11 +30,8 @@ public class UserService {
|
|||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final JwtService jwtService;
|
private final JwtService jwtService;
|
||||||
|
|
||||||
@Value("token-family.expiration")
|
private final long tokenFamilyExpirationMs;
|
||||||
private long tokenFamilyExpirationMs;
|
private final long refreshTokenExpirationMs;
|
||||||
|
|
||||||
@Value("refresh-token.expiration")
|
|
||||||
private long refreshTokenExpirationMs;
|
|
||||||
|
|
||||||
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
|
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
|
||||||
private static final int REFRESH_GRACE_PERIOD_SECONDS = 5;
|
private static final int REFRESH_GRACE_PERIOD_SECONDS = 5;
|
||||||
@@ -46,18 +39,16 @@ public class UserService {
|
|||||||
|
|
||||||
public UserService(UserRepository userRepository,
|
public UserService(UserRepository userRepository,
|
||||||
JwtService jwtService,
|
JwtService jwtService,
|
||||||
@Value("${google.client.id}") String googleClientId,
|
GoogleIdTokenVerifier verifier,
|
||||||
|
AuthProperties props,
|
||||||
TokenService tokenService) {
|
TokenService tokenService) {
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
|
this.verifier = verifier;
|
||||||
NetHttpTransport transport = new NetHttpTransport();
|
|
||||||
JsonFactory jsonFactory = new GsonFactory();
|
|
||||||
|
|
||||||
this.verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
|
|
||||||
.setAudience(Collections.singletonList(googleClientId))
|
|
||||||
.build();
|
|
||||||
this.jwtService = jwtService;
|
this.jwtService = jwtService;
|
||||||
this.tokenService = tokenService;
|
this.tokenService = tokenService;
|
||||||
|
|
||||||
|
this.refreshTokenExpirationMs = props.expiration().refreshToken().toMillis();
|
||||||
|
this.tokenFamilyExpirationMs = props.expiration().tokenFamily().toMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ spring.flyway.locations=classpath:db/migrations
|
|||||||
spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID}
|
spring.security.oauth2.client.registration.google.client-id=${GOOGLE_CLIENT_ID}
|
||||||
spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET}
|
spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET}
|
||||||
spring.security.oauth2.client.registration.google.scope=profile,email
|
spring.security.oauth2.client.registration.google.scope=profile,email
|
||||||
jwt.secret.key=${JWT_SECRET_KEY}
|
app.security.jwt-secret=${JWT_SECRET_KEY}
|
||||||
# 1 Hour
|
# 1 Hour
|
||||||
jwt.expiration=3600000
|
app.security.expiration.jwt=3600000
|
||||||
# 7 days
|
# 7 days
|
||||||
refresh-token.expiration=604800000
|
app.security.expiration.refresh-token=604800000
|
||||||
# 90 days
|
# 90 days
|
||||||
token-family.expiration=7776000000
|
app.security.expiration.token-family=7776000000
|
||||||
|
|
||||||
# Frontend
|
# Frontend
|
||||||
frontend.url=${FRONTEND_URL}
|
frontend.url=${FRONTEND_URL}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.ddf.vodsystem.services;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class UserServiceTest {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user