Merge pull request #45 from HideyoshiSolutions/devel
Devel - Initial Auth Service Refactor
This commit is contained in:
12
pom.xml
12
pom.xml
@@ -9,10 +9,10 @@
|
|||||||
<relativePath/> <!-- lookup parent from repository -->
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.hideyoshi</groupId>
|
<groupId>com.hideyoshi</groupId>
|
||||||
<artifactId>backend-api</artifactId>
|
<artifactId>auth-api</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>backend-api</name>
|
<name>auth-api</name>
|
||||||
<description>Backend API</description>
|
<description>Auth API for the Hideyoshi.com Project</description>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -107,7 +107,11 @@
|
|||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
<version>4.5.14</version>
|
<version>4.5.14</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio;
|
package com.hideyoshi.auth;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.api;
|
package com.hideyoshi.auth.base.auth.api;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.model.AuthDTO;
|
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||||
import com.hideyoshi.backendportfolio.base.security.service.AuthService;
|
import com.hideyoshi.auth.base.auth.service.AuthService;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.TokenDTO;
|
import com.hideyoshi.auth.base.auth.model.TokenDTO;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import com.hideyoshi.backendportfolio.base.user.service.UserService;
|
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.enums.FileTypeEnum;
|
import com.hideyoshi.auth.microservice.storageService.enums.FileTypeEnum;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceUploadResponse;
|
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceUploadResponse;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.service.StorageService;
|
import com.hideyoshi.auth.microservice.storageService.service.StorageService;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.BadRequestException;
|
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||||
import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard;
|
import com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||||
import com.hideyoshi.backendportfolio.util.guard.UserResourceGuardEnum;
|
import com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -20,7 +20,6 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -59,9 +58,14 @@ public class UserController {
|
|||||||
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
|
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
|
||||||
public ResponseEntity<AuthDTO> refreshAccessToken(
|
public ResponseEntity<AuthDTO> refreshAccessToken(
|
||||||
@RequestBody @Valid TokenDTO refreshToken,
|
@RequestBody @Valid TokenDTO refreshToken,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request) {
|
||||||
HttpServletResponse response) {
|
return ResponseEntity.ok(this.authService.refreshAccessToken(refreshToken.getToken(), request));
|
||||||
return ResponseEntity.ok(this.authService.refreshAccessToken(refreshToken.getToken(), request, response));
|
}
|
||||||
|
|
||||||
|
@PostMapping("/login/validate")
|
||||||
|
@UserResourceGuard(accessType = UserResourceGuardEnum.USER)
|
||||||
|
public ResponseEntity<AuthDTO> validateAccessToken(HttpServletRequest request) {
|
||||||
|
return ResponseEntity.ok(this.authService.validateAccessToken(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/delete")
|
@DeleteMapping("/delete")
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.config;
|
package com.hideyoshi.auth.base.auth.config;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.config.RestAuthenticationEntryPointConfig;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.hideyoshi.backendportfolio.base.security.filter.CustomAuthenticationFilter;
|
import com.hideyoshi.auth.base.config.RestAuthenticationEntryPointConfig;
|
||||||
import com.hideyoshi.backendportfolio.base.security.filter.CustomAuthorizationFilter;
|
import com.hideyoshi.auth.base.auth.filter.CustomAuthenticationFilter;
|
||||||
import com.hideyoshi.backendportfolio.base.security.oauth.repo.OAuthRequestRepository;
|
import com.hideyoshi.auth.base.auth.filter.CustomAuthorizationFilter;
|
||||||
import com.hideyoshi.backendportfolio.base.security.service.AuthService;
|
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidException;
|
import com.hideyoshi.auth.base.auth.oauth.repo.OAuthRequestRepository;
|
||||||
|
import com.hideyoshi.auth.base.auth.service.AuthService;
|
||||||
|
import com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -27,6 +29,8 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@@ -95,11 +99,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
|
|
||||||
OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
|
OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
|
||||||
|
|
||||||
this.authService.loginOAuthUser(
|
AuthDTO authUser = this.authService.loginOAuthUser(oauthUser, request);
|
||||||
request,
|
|
||||||
response,
|
response.setContentType(APPLICATION_JSON_VALUE);
|
||||||
oauthUser
|
new ObjectMapper()
|
||||||
);
|
.writeValue(response.getOutputStream(), authUser);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.entity;
|
package com.hideyoshi.auth.base.auth.entity;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public enum Provider {
|
public enum Provider {
|
||||||
|
|
||||||
GOOGLE("google"),
|
GOOGLE("google"),
|
||||||
@@ -8,7 +11,7 @@ public enum Provider {
|
|||||||
|
|
||||||
LOCAL("local");
|
LOCAL("local");
|
||||||
|
|
||||||
private String name;
|
private final String name;
|
||||||
|
|
||||||
Provider(String name) {
|
Provider(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -23,8 +26,4 @@ public enum Provider {
|
|||||||
throw new IllegalArgumentException("Argument not valid.");
|
throw new IllegalArgumentException("Argument not valid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.entity;
|
package com.hideyoshi.auth.base.auth.entity;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.entity;
|
package com.hideyoshi.auth.base.auth.entity;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.filter;
|
package com.hideyoshi.auth.base.auth.filter;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.config.RestAuthenticationEntryPointConfig;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.hideyoshi.backendportfolio.base.security.service.AuthService;
|
import com.hideyoshi.auth.base.config.RestAuthenticationEntryPointConfig;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||||
|
import com.hideyoshi.auth.base.auth.service.AuthService;
|
||||||
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
@@ -15,6 +17,8 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||||
|
|
||||||
@@ -50,12 +54,16 @@ public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFi
|
|||||||
@Override
|
@Override
|
||||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException {
|
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException {
|
||||||
|
|
||||||
this.authService.loginUser(
|
AuthDTO authUser = this.authService.loginUser(
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
(UserDTO) authentication.getPrincipal()
|
(UserDTO) authentication.getPrincipal()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
response.setContentType(APPLICATION_JSON_VALUE);
|
||||||
|
new ObjectMapper()
|
||||||
|
.writeValue(response.getOutputStream(), authUser);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.filter;
|
package com.hideyoshi.auth.base.auth.filter;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.hideyoshi.backendportfolio.base.security.service.AuthService;
|
import com.hideyoshi.auth.base.auth.service.AuthService;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidException;
|
import com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidExceptionDetails;
|
import com.hideyoshi.auth.util.exception.AuthenticationInvalidExceptionDetails;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.BadRequestException;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
@@ -78,7 +77,8 @@ public class CustomAuthorizationFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
private UsernamePasswordAuthenticationToken validateUserAccess(String authorizationHeader) {
|
private UsernamePasswordAuthenticationToken validateUserAccess(String authorizationHeader) {
|
||||||
if (Objects.nonNull(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) {
|
if (Objects.nonNull(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) {
|
||||||
return this.authService.verifyAccessToken(authorizationHeader);
|
String accessToken = authorizationHeader.substring(AUTHORIZATION_TYPE_STRING.length());
|
||||||
|
return this.authService.extractAccessTokenInfo(accessToken);
|
||||||
} else {
|
} else {
|
||||||
throw new AuthenticationInvalidException("Access denied");
|
throw new AuthenticationInvalidException("Access denied");
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.interceptor;
|
package com.hideyoshi.auth.base.auth.interceptor;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.interceptor;
|
package com.hideyoshi.auth.base.auth.interceptor;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.hideyoshi.backendportfolio.base.user.service.UserService;
|
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidException;
|
import com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.BadRequestException;
|
import com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||||
import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.model;
|
package com.hideyoshi.auth.base.auth.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.TokenDTO;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.model;
|
package com.hideyoshi.auth.base.auth.model;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.model;
|
package com.hideyoshi.auth.base.auth.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.model;
|
package com.hideyoshi.auth.base.auth.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.User;
|
import com.hideyoshi.auth.base.auth.entity.User;
|
||||||
import com.hideyoshi.backendportfolio.util.validator.email.unique.UniqueEmail;
|
import com.hideyoshi.auth.util.validator.email.unique.UniqueEmail;
|
||||||
import com.hideyoshi.backendportfolio.util.validator.email.valid.ValidEmail;
|
import com.hideyoshi.auth.util.validator.email.valid.ValidEmail;
|
||||||
import com.hideyoshi.backendportfolio.util.validator.password.ValidPassword;
|
import com.hideyoshi.auth.util.validator.password.ValidPassword;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.oauth.mapper;
|
package com.hideyoshi.auth.base.auth.oauth.mapper;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.oauth.mapper;
|
package com.hideyoshi.auth.base.auth.oauth.mapper;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.hideyoshi.auth.base.auth.oauth.mapper;
|
||||||
|
|
||||||
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
|
|
||||||
|
public interface OAuthMap {
|
||||||
|
|
||||||
|
String getPrincipal();
|
||||||
|
|
||||||
|
String getProfilePicture();
|
||||||
|
|
||||||
|
Provider getProvider();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.oauth.mapper;
|
package com.hideyoshi.auth.base.auth.oauth.mapper;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
public enum OAuthMapper {
|
public enum OAuthMapper {
|
||||||
@@ -9,26 +9,26 @@ public enum OAuthMapper {
|
|||||||
|
|
||||||
GITHUB(GithubOAuthMap.class, Provider.GITHUB);
|
GITHUB(GithubOAuthMap.class, Provider.GITHUB);
|
||||||
|
|
||||||
private final Class oAuthMap;
|
private final Class<? extends OAuthMap> oAuthMap;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Provider provider;
|
private final Provider provider;
|
||||||
|
|
||||||
private OAuthMapper(Class oAuthMap, Provider provider) {
|
private OAuthMapper(Class<? extends OAuthMap> oAuthMap, Provider provider) {
|
||||||
this.oAuthMap = oAuthMap;
|
this.oAuthMap = oAuthMap;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OAuthMapper byValue(String name) {
|
public static OAuthMapper byValue(Provider provider) {
|
||||||
for (OAuthMapper e : values()) {
|
for (OAuthMapper e : values()) {
|
||||||
if (e.getProvider().getName().equals(name)) {
|
if (e.getProvider().equals(provider)) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Argument not valid.");
|
throw new IllegalArgumentException("Argument not valid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getMap() {
|
public Class<? extends OAuthMap> getMap() {
|
||||||
return oAuthMap;
|
return oAuthMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.oauth.repo;
|
package com.hideyoshi.auth.base.auth.oauth.repo;
|
||||||
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
|
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.repo;
|
package com.hideyoshi.auth.base.auth.repo;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.User;
|
import com.hideyoshi.auth.base.auth.entity.User;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
package com.hideyoshi.auth.base.auth.service;
|
||||||
|
|
||||||
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.JWTVerifier;
|
||||||
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||||
|
import com.hideyoshi.auth.base.auth.oauth.mapper.OAuthMap;
|
||||||
|
import com.hideyoshi.auth.base.auth.oauth.mapper.OAuthMapper;
|
||||||
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
|
import com.hideyoshi.auth.base.auth.model.TokenDTO;
|
||||||
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
|
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceDownloadResponse;
|
||||||
|
import com.hideyoshi.auth.microservice.storageService.service.StorageService;
|
||||||
|
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.util.Arrays.stream;
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuthService {
|
||||||
|
private static final String AUTHORIZATION_TYPE_STRING = "Bearer ";
|
||||||
|
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
|
private final StorageService storageService;
|
||||||
|
|
||||||
|
@Value("${com.hideyoshi.tokenSecret}")
|
||||||
|
private String TOKEN_SECRET;
|
||||||
|
|
||||||
|
@Value("${com.hideyoshi.accessTokenDuration}")
|
||||||
|
private Integer ACCESS_TOKEN_DURATION;
|
||||||
|
|
||||||
|
@Value("${com.hideyoshi.refreshTokenDuration}")
|
||||||
|
private Integer REFRESH_TOKEN_DURATION;
|
||||||
|
|
||||||
|
public AuthDTO signupUser(@Valid UserDTO user, HttpServletRequest request) {
|
||||||
|
user.setProvider(Provider.LOCAL);
|
||||||
|
|
||||||
|
UserDTO authenticatedUser = this.userService.saveUser(user);
|
||||||
|
authenticatedUser.setProfilePictureUrl(this.extractProfilePictureUrl(authenticatedUser));
|
||||||
|
|
||||||
|
return this.generateNewAuthenticatedUser(
|
||||||
|
authenticatedUser,
|
||||||
|
request
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthDTO loginUser(HttpServletRequest request, HttpServletResponse response, @Valid UserDTO user) throws IOException {
|
||||||
|
user.setProfilePictureUrl(this.extractProfilePictureUrl(user));
|
||||||
|
|
||||||
|
return this.generateNewAuthenticatedUser(
|
||||||
|
user,
|
||||||
|
request
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthDTO loginOAuthUser(OAuth2User oauthUser, HttpServletRequest request) {
|
||||||
|
Provider clientProvider = Provider.byValue(
|
||||||
|
this.getClientFromUrl(request.getRequestURL().toString())
|
||||||
|
);
|
||||||
|
|
||||||
|
OAuthMap oauthMap = this.generateOAuthMap(clientProvider, oauthUser);
|
||||||
|
|
||||||
|
return this.processOAuthPostLogin(
|
||||||
|
this.generateAuthenticatedUserFromOAuth(oauthMap, oauthUser),
|
||||||
|
request
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthDTO refreshAccessToken(String requestToken, HttpServletRequest request) {
|
||||||
|
DecodedJWT decodedJWT = this.decodeToken(requestToken)
|
||||||
|
.orElseThrow(() -> new BadRequestException("Invalid Token"));
|
||||||
|
|
||||||
|
String username = decodedJWT.getSubject();
|
||||||
|
|
||||||
|
UserDTO user = this.userService.getUser(username);
|
||||||
|
user.setProfilePictureUrl(this.extractProfilePictureUrl(user));
|
||||||
|
|
||||||
|
return this.refreshAuthenticatedUser(user, request, new TokenDTO(requestToken, decodedJWT.getExpiresAt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthDTO validateAccessToken(HttpServletRequest request) {
|
||||||
|
UserDTO user = this.getLoggedUser();
|
||||||
|
user.setProfilePictureUrl(this.extractProfilePictureUrl(user));
|
||||||
|
|
||||||
|
return this.generateNewAuthenticatedUser(user, request);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDTO getLoggedUser() {
|
||||||
|
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
|
return userService.getUser(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsernamePasswordAuthenticationToken extractAccessTokenInfo(String accessToken) {
|
||||||
|
DecodedJWT decodedJWT = this.decodeToken(accessToken)
|
||||||
|
.orElseThrow(() -> new BadRequestException("Invalid Token"));
|
||||||
|
|
||||||
|
String username = decodedJWT.getSubject();
|
||||||
|
String[] roles = decodedJWT.getClaim("roles").asArray(String.class);
|
||||||
|
|
||||||
|
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
|
||||||
|
stream(roles).forEach(role -> {
|
||||||
|
authorities.add(new SimpleGrantedAuthority(role));
|
||||||
|
});
|
||||||
|
|
||||||
|
return new UsernamePasswordAuthenticationToken(username, null, authorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<DecodedJWT> decodeToken(String token) {
|
||||||
|
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET.getBytes());
|
||||||
|
JWTVerifier verifier = JWT.require(algorithm).build();
|
||||||
|
try {
|
||||||
|
return Optional.of(verifier.verify(token));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Token verification failed: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthDTO processOAuthPostLogin(@Valid UserDTO user, HttpServletRequest request) {
|
||||||
|
|
||||||
|
if (Objects.nonNull(user.getId())) {
|
||||||
|
this.userService.alterUser(user.getId(), user);
|
||||||
|
} else {
|
||||||
|
this.userService.saveUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.generateNewAuthenticatedUser(user, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getClientFromUrl(String url) {
|
||||||
|
String[] urlPartition = url.split("/");
|
||||||
|
return urlPartition[urlPartition.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private OAuthMap generateOAuthMap(Provider clientProvider, OAuth2User oauthUser) {
|
||||||
|
try {
|
||||||
|
return OAuthMapper.byValue(clientProvider).getMap()
|
||||||
|
.getDeclaredConstructor(OAuth2User.class).newInstance(oauthUser);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BadRequestException("Unsupported OAuth Client.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractProfilePictureUrl(UserDTO user) {
|
||||||
|
return this.storageService.getFileUrl(user.getUsername(), "profile")
|
||||||
|
.map(StorageServiceDownloadResponse::getPresignedUrl)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserDTO generateAuthenticatedUserFromOAuth(OAuthMap oauthMap, OAuth2User oauthUser) {
|
||||||
|
UserDTO user;
|
||||||
|
try {
|
||||||
|
user = this.userService.getUser(oauthMap.getPrincipal());
|
||||||
|
} catch (BadRequestException e) {
|
||||||
|
user = UserDTO.builder()
|
||||||
|
.name(oauthUser.getAttribute("name"))
|
||||||
|
.username(oauthMap.getPrincipal())
|
||||||
|
.email(oauthUser.getAttribute("email"))
|
||||||
|
.roles(List.of(Role.USER))
|
||||||
|
.provider(oauthMap.getProvider())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
user.setProfilePictureUrl(oauthMap.getProfilePicture());
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthDTO generateNewAuthenticatedUser(UserDTO user, HttpServletRequest request) {
|
||||||
|
HttpSession httpSession = request.getSession();
|
||||||
|
AuthDTO authObject = new AuthDTO(
|
||||||
|
user,
|
||||||
|
this.generateToken(user, request, ACCESS_TOKEN_DURATION),
|
||||||
|
this.generateToken(user, request, REFRESH_TOKEN_DURATION)
|
||||||
|
);
|
||||||
|
|
||||||
|
httpSession.setAttribute("user", authObject);
|
||||||
|
|
||||||
|
return authObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthDTO refreshAuthenticatedUser(UserDTO user, HttpServletRequest request, TokenDTO refreshToken) {
|
||||||
|
HttpSession httpSession = request.getSession();
|
||||||
|
AuthDTO authObject = new AuthDTO(
|
||||||
|
user,
|
||||||
|
this.generateToken(user, request, ACCESS_TOKEN_DURATION),
|
||||||
|
refreshToken
|
||||||
|
);
|
||||||
|
|
||||||
|
httpSession.setAttribute("user", authObject);
|
||||||
|
|
||||||
|
return authObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TokenDTO generateToken(@Valid UserDTO user, HttpServletRequest request, Integer duration) {
|
||||||
|
|
||||||
|
Date expirationDate = new Date(System.currentTimeMillis() + duration);
|
||||||
|
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET.getBytes());
|
||||||
|
|
||||||
|
String token = JWT.create()
|
||||||
|
.withSubject(user.getUsername())
|
||||||
|
.withExpiresAt(expirationDate)
|
||||||
|
.withIssuer(request.getRequestURL().toString())
|
||||||
|
.withClaim("roles", user.getAuthorities()
|
||||||
|
.stream().map(GrantedAuthority::getAuthority)
|
||||||
|
.collect(Collectors.toList()))
|
||||||
|
.sign(algorithm);
|
||||||
|
|
||||||
|
return new TokenDTO(token, expirationDate);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.service;
|
package com.hideyoshi.auth.base.auth.service;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.User;
|
import com.hideyoshi.auth.base.auth.entity.User;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import com.hideyoshi.backendportfolio.base.user.repo.UserRepository;
|
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.BadRequestException;
|
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -22,13 +23,12 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UserServiceImpl implements UserService {
|
public class UserService implements UserDetailsService {
|
||||||
|
|
||||||
private final UserRepository userRepo;
|
private final UserRepository userRepo;
|
||||||
|
|
||||||
private final PasswordEncoder passwordEncoder;
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDTO saveUser(@Valid UserDTO user) {
|
public UserDTO saveUser(@Valid UserDTO user) {
|
||||||
|
|
||||||
this.userRepo.findByUsername(user.getUsername()).ifPresent(userOnDB -> {
|
this.userRepo.findByUsername(user.getUsername()).ifPresent(userOnDB -> {
|
||||||
@@ -45,7 +45,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
return userSaved;
|
return userSaved;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void alterUser(Long id, @Valid UserDTO user) {
|
public void alterUser(Long id, @Valid UserDTO user) {
|
||||||
|
|
||||||
this.userRepo.findById(id).ifPresentOrElse(userOnDB -> {
|
this.userRepo.findById(id).ifPresentOrElse(userOnDB -> {
|
||||||
@@ -57,7 +56,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteUser(Long id) {
|
public void deleteUser(Long id) {
|
||||||
|
|
||||||
this.userRepo.findById(id).ifPresentOrElse(userOnDB -> {
|
this.userRepo.findById(id).ifPresentOrElse(userOnDB -> {
|
||||||
@@ -68,7 +66,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addRoleToUser(Long id, String roleName) {
|
public void addRoleToUser(Long id, String roleName) {
|
||||||
|
|
||||||
UserDTO userOnDB = this.getUser(id);
|
UserDTO userOnDB = this.getUser(id);
|
||||||
@@ -89,7 +86,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeRoleFromUser(Long id, String roleName) {
|
public void removeRoleFromUser(Long id, String roleName) {
|
||||||
|
|
||||||
UserDTO userOnDB = this.getUser(id);
|
UserDTO userOnDB = this.getUser(id);
|
||||||
@@ -109,7 +105,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDTO getUser(Long id) {
|
public UserDTO getUser(Long id) {
|
||||||
log.info(String.format("Fetching user with id: %o", id));
|
log.info(String.format("Fetching user with id: %o", id));
|
||||||
|
|
||||||
@@ -119,7 +114,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDTO getUser(String username) {
|
public UserDTO getUser(String username) {
|
||||||
log.info(String.format("Fetching user: %s", username));
|
log.info(String.format("Fetching user: %s", username));
|
||||||
|
|
||||||
@@ -129,7 +123,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<UserDTO> getUsers() {
|
public List<UserDTO> getUsers() {
|
||||||
log.info("Fetching all users.");
|
log.info("Fetching all users.");
|
||||||
|
|
||||||
@@ -138,7 +131,6 @@ public class UserServiceImpl implements UserService {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDetails loadUserByUsername(String username) {
|
public UserDetails loadUserByUsername(String username) {
|
||||||
return this.getUser(username);
|
return this.getUser(username);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.config;
|
package com.hideyoshi.auth.base.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.config;
|
package com.hideyoshi.auth.base.config;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import com.hideyoshi.backendportfolio.base.user.repo.UserRepository;
|
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||||
import com.hideyoshi.backendportfolio.base.user.service.UserService;
|
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.CommandLineRunner;
|
import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.config;
|
package com.hideyoshi.auth.base.config;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidException;
|
import com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.config;
|
package com.hideyoshi.auth.base.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.session.api;
|
package com.hideyoshi.auth.base.session.api;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.model.AuthDTO;
|
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||||
import com.hideyoshi.backendportfolio.base.session.service.SessionManagerService;
|
import com.hideyoshi.auth.base.session.service.SessionManagerService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.session.service;
|
package com.hideyoshi.auth.base.session.service;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.model.AuthDTO;
|
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.session.service;
|
package com.hideyoshi.auth.base.session.service;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.model.AuthDTO;
|
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.hideyoshi.backendportfolio.healthChecker.api;
|
package com.hideyoshi.auth.healthChecker.api;
|
||||||
|
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard;
|
import com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||||
import com.hideyoshi.backendportfolio.util.guard.UserResourceGuardEnum;
|
import com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.microservice.storageService.config;
|
package com.hideyoshi.auth.microservice.storageService.config;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.hideyoshi.backendportfolio.microservice.storageService.enums;
|
package com.hideyoshi.auth.microservice.storageService.enums;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.BadRequestException;
|
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.microservice.storageService.enums;
|
package com.hideyoshi.auth.microservice.storageService.enums;
|
||||||
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.microservice.storageService.model;
|
package com.hideyoshi.auth.microservice.storageService.model;
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.microservice.storageService.model;
|
package com.hideyoshi.auth.microservice.storageService.model;
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.hideyoshi.backendportfolio.microservice.storageService.service;
|
package com.hideyoshi.auth.microservice.storageService.service;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.config.StorageServiceConfig;
|
import com.hideyoshi.auth.microservice.storageService.config.StorageServiceConfig;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.enums.FileTypeEnum;
|
import com.hideyoshi.auth.microservice.storageService.enums.FileTypeEnum;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceDownloadResponse;
|
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceDownloadResponse;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceUploadResponse;
|
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceUploadResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.apache.http.client.methods.HttpDelete;
|
import org.apache.http.client.methods.HttpDelete;
|
||||||
@@ -63,7 +63,7 @@ public class StorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Optional<StorageServiceDownloadResponse> getFileUrl(String username, String filePostfix) {
|
public Optional<StorageServiceDownloadResponse> getFileUrl(String username, String filePostfix) {
|
||||||
URI uri = null;
|
URI uri;
|
||||||
try {
|
try {
|
||||||
uri = new URIBuilder(storageServiceConfig.getFileServicePath() + "/file")
|
uri = new URIBuilder(storageServiceConfig.getFileServicePath() + "/file")
|
||||||
.addParameter(PARAMETER_USERNAME, username)
|
.addParameter(PARAMETER_USERNAME, username)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.exception;
|
package com.hideyoshi.auth.util.exception;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.exception;
|
package com.hideyoshi.auth.util.exception;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.exception;
|
package com.hideyoshi.auth.util.exception;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.exception;
|
package com.hideyoshi.auth.util.exception;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.exception;
|
package com.hideyoshi.auth.util.exception;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.exception;
|
package com.hideyoshi.auth.util.exception;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.guard;
|
package com.hideyoshi.auth.util.guard;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.guard;
|
package com.hideyoshi.auth.util.guard;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import com.hideyoshi.backendportfolio.base.user.service.UserService;
|
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.guard;
|
package com.hideyoshi.auth.util.guard;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.handler;
|
package com.hideyoshi.auth.util.handler;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.util.exception.*;
|
import com.hideyoshi.auth.util.exception.*;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.validator.email.unique;
|
package com.hideyoshi.auth.util.validator.email.unique;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.repo.UserRepository;
|
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.validator.email.unique;
|
package com.hideyoshi.auth.util.validator.email.unique;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import javax.validation.Constraint;
|
||||||
import javax.validation.Payload;
|
import javax.validation.Payload;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.validator.email.valid;
|
package com.hideyoshi.auth.util.validator.email.valid;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.validator.email.valid;
|
package com.hideyoshi.auth.util.validator.email.valid;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import javax.validation.Constraint;
|
||||||
import javax.validation.Payload;
|
import javax.validation.Payload;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.validator.password;
|
package com.hideyoshi.auth.util.validator.password;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.hideyoshi.backendportfolio.util.validator.password;
|
package com.hideyoshi.auth.util.validator.password;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import javax.validation.Constraint;
|
||||||
import javax.validation.Payload;
|
import javax.validation.Payload;
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.oauth.mapper;
|
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
|
||||||
|
|
||||||
public interface OAuthMap {
|
|
||||||
|
|
||||||
String getPrincipal();
|
|
||||||
|
|
||||||
String getProfilePicture();
|
|
||||||
|
|
||||||
Provider getProvider();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.service;
|
|
||||||
|
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.model.AuthDTO;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.TokenDTO;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
public interface AuthService {
|
|
||||||
|
|
||||||
TokenDTO generateAccessToken(@Valid UserDTO user, Algorithm algorithm, HttpServletRequest request);
|
|
||||||
|
|
||||||
TokenDTO generateRefreshToken(@Valid UserDTO user, Algorithm algorithm, HttpServletRequest request);
|
|
||||||
|
|
||||||
HashMap<String, TokenDTO> generateTokens(@Valid UserDTO user, Algorithm algorithm, HttpServletRequest request);
|
|
||||||
|
|
||||||
UsernamePasswordAuthenticationToken verifyAccessToken(String authorizationHeader);
|
|
||||||
|
|
||||||
AuthDTO refreshAccessToken(String refreshToken, HttpServletRequest request, HttpServletResponse response);
|
|
||||||
|
|
||||||
AuthDTO signupUser(@Valid UserDTO user, HttpServletRequest request);
|
|
||||||
|
|
||||||
AuthDTO generateUserWithTokens(UserDTO user, HttpServletRequest request);
|
|
||||||
|
|
||||||
AuthDTO processOAuthPostLogin(@Valid UserDTO user, HttpServletRequest request);
|
|
||||||
|
|
||||||
void loginUser(HttpServletRequest request, HttpServletResponse response, @Valid UserDTO user) throws IOException;
|
|
||||||
|
|
||||||
void loginOAuthUser(HttpServletRequest request, HttpServletResponse response, OAuth2User user) throws IOException;
|
|
||||||
|
|
||||||
UserDTO getLoggedUser();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.security.service;
|
|
||||||
|
|
||||||
import com.auth0.jwt.JWT;
|
|
||||||
import com.auth0.jwt.JWTVerifier;
|
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.model.AuthDTO;
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.oauth.mapper.OAuthMap;
|
|
||||||
import com.hideyoshi.backendportfolio.base.security.oauth.mapper.OAuthMapper;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.TokenDTO;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.service.UserService;
|
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.service.StorageService;
|
|
||||||
import com.hideyoshi.backendportfolio.util.exception.BadRequestException;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static java.util.Arrays.stream;
|
|
||||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
|
||||||
|
|
||||||
@Log4j2
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AuthServiceImpl implements AuthService {
|
|
||||||
|
|
||||||
|
|
||||||
private static final String AUTHORIZATION_TYPE_STRING = "Bearer ";
|
|
||||||
private final UserService userService;
|
|
||||||
private final StorageService storageService;
|
|
||||||
@Value("${com.hideyoshi.tokenSecret}")
|
|
||||||
private String TOKEN_SECRET;
|
|
||||||
@Value("${com.hideyoshi.accessTokenDuration}")
|
|
||||||
private Integer ACCESS_TOKEN_DURATION;
|
|
||||||
@Value("${com.hideyoshi.refreshTokenDuration}")
|
|
||||||
private Integer REFRESH_TOKEN_DURATION;
|
|
||||||
@Autowired
|
|
||||||
@Qualifier("handlerExceptionResolver")
|
|
||||||
private HandlerExceptionResolver resolver;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TokenDTO generateAccessToken(@Valid UserDTO user, Algorithm algorithm, HttpServletRequest request) {
|
|
||||||
|
|
||||||
Date expirationDate = new Date(System.currentTimeMillis() + ACCESS_TOKEN_DURATION);
|
|
||||||
|
|
||||||
String accessToken = JWT.create()
|
|
||||||
.withSubject(user.getUsername())
|
|
||||||
.withExpiresAt(expirationDate)
|
|
||||||
.withIssuer(request.getRequestURL().toString())
|
|
||||||
.withClaim("roles", user.getAuthorities()
|
|
||||||
.stream().map(GrantedAuthority::getAuthority)
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.sign(algorithm);
|
|
||||||
|
|
||||||
return new TokenDTO(accessToken, expirationDate);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TokenDTO generateRefreshToken(@Valid UserDTO user, Algorithm algorithm, HttpServletRequest request) {
|
|
||||||
|
|
||||||
Date expirationDate = new Date(System.currentTimeMillis() + REFRESH_TOKEN_DURATION);
|
|
||||||
|
|
||||||
String refreshToken = JWT.create()
|
|
||||||
.withSubject(user.getUsername())
|
|
||||||
.withExpiresAt(expirationDate)
|
|
||||||
.withIssuer(request.getRequestURL().toString())
|
|
||||||
.sign(algorithm);
|
|
||||||
|
|
||||||
return new TokenDTO(refreshToken, expirationDate);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HashMap<String, TokenDTO> generateTokens(@Valid UserDTO user, Algorithm algorithm, HttpServletRequest request) {
|
|
||||||
|
|
||||||
TokenDTO accessToken = generateAccessToken(user, algorithm, request);
|
|
||||||
TokenDTO refreshToken = generateRefreshToken(user, algorithm, request);
|
|
||||||
|
|
||||||
HashMap<String, TokenDTO> tokens = new HashMap<>();
|
|
||||||
tokens.put("accessToken", accessToken);
|
|
||||||
tokens.put("refreshToken", refreshToken);
|
|
||||||
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UsernamePasswordAuthenticationToken verifyAccessToken(String authorizationHeader) {
|
|
||||||
|
|
||||||
if (!authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String authorizationToken = authorizationHeader.substring(AUTHORIZATION_TYPE_STRING.length());
|
|
||||||
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET.getBytes());
|
|
||||||
|
|
||||||
JWTVerifier verifier = JWT.require(algorithm).build();
|
|
||||||
DecodedJWT decodedJWT = verifier.verify(authorizationToken);
|
|
||||||
|
|
||||||
String username = decodedJWT.getSubject();
|
|
||||||
String[] roles = decodedJWT.getClaim("roles").asArray(String.class);
|
|
||||||
|
|
||||||
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
|
|
||||||
stream(roles).forEach(role -> {
|
|
||||||
authorities.add(new SimpleGrantedAuthority(role));
|
|
||||||
});
|
|
||||||
|
|
||||||
return new UsernamePasswordAuthenticationToken(username, null, authorities);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthDTO generateUserWithTokens(UserDTO user, HttpServletRequest request) {
|
|
||||||
|
|
||||||
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET.getBytes());
|
|
||||||
|
|
||||||
HashMap<String, TokenDTO> tokens = this.generateTokens(user, algorithm, request);
|
|
||||||
|
|
||||||
HttpSession httpSession = request.getSession();
|
|
||||||
AuthDTO authObject = new AuthDTO(user, tokens.get("accessToken"), tokens.get("refreshToken"));
|
|
||||||
|
|
||||||
httpSession.setAttribute("user", authObject);
|
|
||||||
|
|
||||||
return authObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthDTO signupUser(@Valid UserDTO user, HttpServletRequest request) {
|
|
||||||
|
|
||||||
user.setProvider(Provider.LOCAL);
|
|
||||||
|
|
||||||
UserDTO authenticatedUser = this.userService.saveUser(user);
|
|
||||||
|
|
||||||
var profilePicture = this.storageService.getFileUrl(authenticatedUser.getUsername(), "profile");
|
|
||||||
profilePicture.ifPresent(
|
|
||||||
storageServiceDownloadResponse -> authenticatedUser.setProfilePictureUrl(storageServiceDownloadResponse.getPresignedUrl())
|
|
||||||
);
|
|
||||||
|
|
||||||
return this.generateUserWithTokens(
|
|
||||||
authenticatedUser,
|
|
||||||
request
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loginUser(HttpServletRequest request, HttpServletResponse response, @Valid UserDTO user) throws IOException {
|
|
||||||
var profilePicture = this.storageService.getFileUrl(user.getUsername(), "profile");
|
|
||||||
profilePicture.ifPresent(
|
|
||||||
storageServiceDownloadResponse -> user.setProfilePictureUrl(storageServiceDownloadResponse.getPresignedUrl())
|
|
||||||
);
|
|
||||||
|
|
||||||
AuthDTO authObject = this.generateUserWithTokens(
|
|
||||||
user,
|
|
||||||
request
|
|
||||||
);
|
|
||||||
|
|
||||||
response.setContentType(APPLICATION_JSON_VALUE);
|
|
||||||
new ObjectMapper()
|
|
||||||
.writeValue(response.getOutputStream(), authObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthDTO refreshAccessToken(String refreshToken, HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
|
|
||||||
if (!Objects.nonNull(refreshToken)) {
|
|
||||||
resolver.resolveException(
|
|
||||||
request,
|
|
||||||
response,
|
|
||||||
null,
|
|
||||||
new BadRequestException("Invalid Refresh Token. Please authenticate first.")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET.getBytes());
|
|
||||||
|
|
||||||
JWTVerifier verifier = JWT.require(algorithm).build();
|
|
||||||
DecodedJWT decodedJWT = verifier.verify(refreshToken);
|
|
||||||
|
|
||||||
UserDTO user = this.userService.getUser(decodedJWT.getSubject());
|
|
||||||
|
|
||||||
var profilePicture = this.storageService.getFileUrl(user.getUsername(), "profile");
|
|
||||||
profilePicture.ifPresent(
|
|
||||||
storageServiceDownloadResponse -> user.setProfilePictureUrl(storageServiceDownloadResponse.getPresignedUrl())
|
|
||||||
);
|
|
||||||
|
|
||||||
HttpSession httpSession = request.getSession();
|
|
||||||
AuthDTO authenticatedUser = new AuthDTO(
|
|
||||||
user,
|
|
||||||
this.generateAccessToken(user, algorithm, request),
|
|
||||||
new TokenDTO(
|
|
||||||
refreshToken,
|
|
||||||
decodedJWT.getExpiresAt()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
httpSession.setAttribute("user", authenticatedUser);
|
|
||||||
|
|
||||||
return authenticatedUser;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthDTO processOAuthPostLogin(@Valid UserDTO user, HttpServletRequest request) {
|
|
||||||
|
|
||||||
if (Objects.nonNull(user.getId())) {
|
|
||||||
this.userService.alterUser(user.getId(), user);
|
|
||||||
} else {
|
|
||||||
this.userService.saveUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.generateUserWithTokens(user, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loginOAuthUser(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
OAuth2User oauthUser) throws IOException {
|
|
||||||
|
|
||||||
String clientId = this.getClientFromUrl(request.getRequestURL().toString());
|
|
||||||
|
|
||||||
OAuthMap oauthMap = this.generateOAuthMap(clientId, oauthUser);
|
|
||||||
|
|
||||||
AuthDTO authObject = this.processOAuthPostLogin(
|
|
||||||
this.generateUserFromAuthUser(oauthMap, oauthUser),
|
|
||||||
request
|
|
||||||
);
|
|
||||||
|
|
||||||
response.setContentType(APPLICATION_JSON_VALUE);
|
|
||||||
new ObjectMapper()
|
|
||||||
.writeValue(response.getOutputStream(), authObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDTO getLoggedUser() {
|
|
||||||
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
|
||||||
return userService.getUser(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getClientFromUrl(String url) {
|
|
||||||
String[] urlPartition = url.split("/");
|
|
||||||
return urlPartition[urlPartition.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
private OAuthMap generateOAuthMap(String clientId, OAuth2User oauthUser) {
|
|
||||||
try {
|
|
||||||
return (OAuthMap) OAuthMapper.byValue(clientId).getMap()
|
|
||||||
.getDeclaredConstructor(OAuth2User.class).newInstance(oauthUser);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new BadRequestException("Unsupported OAuth Client.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserDTO generateUserFromAuthUser(OAuthMap oauthMap, OAuth2User oauthUser) {
|
|
||||||
UserDTO user = null;
|
|
||||||
try {
|
|
||||||
user = this.userService.getUser(oauthMap.getPrincipal());
|
|
||||||
} catch (BadRequestException e) {
|
|
||||||
user = UserDTO.builder()
|
|
||||||
.name(oauthUser.getAttribute("name"))
|
|
||||||
.username(oauthMap.getPrincipal())
|
|
||||||
.email(oauthUser.getAttribute("email"))
|
|
||||||
.roles(Arrays.asList(Role.USER))
|
|
||||||
.provider(oauthMap.getProvider())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
user.setProfilePictureUrl(oauthMap.getProfilePicture());
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.service;
|
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface UserService extends UserDetailsService {
|
|
||||||
|
|
||||||
UserDTO saveUser(@Valid UserDTO user);
|
|
||||||
|
|
||||||
void alterUser(Long id, @Valid UserDTO user);
|
|
||||||
|
|
||||||
void deleteUser(Long id);
|
|
||||||
|
|
||||||
void addRoleToUser(Long id, String roleName);
|
|
||||||
|
|
||||||
void removeRoleFromUser(Long id, String roleName);
|
|
||||||
|
|
||||||
UserDTO getUser(Long id);
|
|
||||||
|
|
||||||
UserDTO getUser(String username);
|
|
||||||
|
|
||||||
List<UserDTO> getUsers();
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.hideyoshi.backendportfolio;
|
package com.hideyoshi.auth;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.repo;
|
package com.hideyoshi.auth.base.user.repo;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.User;
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.entity.User;
|
||||||
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.hideyoshi.backendportfolio.base.user.service;
|
package com.hideyoshi.auth.base.user.service;
|
||||||
|
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Provider;
|
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.Role;
|
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||||
import com.hideyoshi.backendportfolio.base.user.entity.User;
|
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||||
import com.hideyoshi.backendportfolio.base.user.model.UserDTO;
|
import com.hideyoshi.auth.base.auth.entity.User;
|
||||||
import com.hideyoshi.backendportfolio.base.user.repo.UserRepository;
|
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||||
import com.hideyoshi.backendportfolio.util.exception.BadRequestException;
|
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||||
|
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -31,9 +32,9 @@ import static org.mockito.Mockito.verify;
|
|||||||
@DataJpaTest
|
@DataJpaTest
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
|
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
|
||||||
class UserServiceImplTest {
|
class UserServiceTest {
|
||||||
|
|
||||||
private UserServiceImpl underTest;
|
private UserService underTest;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private UserRepository userRepository;
|
private UserRepository userRepository;
|
||||||
@@ -42,7 +43,7 @@ class UserServiceImplTest {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
this.underTest = new UserServiceImpl(userRepository, passwordEncoder);
|
this.underTest = new UserService(userRepository, passwordEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.hideyoshi.backendportfolio.microservice.storageService.service;
|
package com.hideyoshi.auth.microservice.storageService.service;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.config.StorageServiceConfig;
|
import com.hideyoshi.auth.microservice.storageService.config.StorageServiceConfig;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.enums.FileTypeEnum;
|
import com.hideyoshi.auth.microservice.storageService.enums.FileTypeEnum;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceDownloadResponse;
|
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceDownloadResponse;
|
||||||
import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceUploadResponse;
|
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceUploadResponse;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
Reference in New Issue
Block a user