Refactor and restructure - No API Breakage (#49)
* Renames Project GroupId * Correcting Naming Conventions * Initial Restructuring * Altera Formato Application Config * Removes Auth for ReImplementation * Changes Project Structure * Restructure Microservice * Fixes Tests * Initial Authentication and Authorization ReImplementation * Optimize Imports and Reformats Code * Implements ResourceGuard Mapping and Automatic Security Configuration * First Refactored Feature Complete Version - OAuth2 Implementation * Moves All Enums to the Correct Dir * Reimplements Authentication with Providers and JWTFilters
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package br.com.hideyoshi.auth;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class AuthServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AuthServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.hideyoshi.auth.base.config;
|
||||
package br.com.hideyoshi.auth.config;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.repository.UserRepository;
|
||||
import br.com.hideyoshi.auth.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -15,16 +15,16 @@ import java.util.ArrayList;
|
||||
@Configuration
|
||||
public class DefaultUserConfig {
|
||||
|
||||
@Value("${com.hideyoshi.defaultUser.fullName}")
|
||||
@Value("${br.com.hideyoshi.defaultUser.fullName}")
|
||||
private String ADMIN_NAME;
|
||||
|
||||
@Value("${com.hideyoshi.defaultUser.email}")
|
||||
@Value("${br.com.hideyoshi.defaultUser.email}")
|
||||
private String ADMIN_EMAIL;
|
||||
|
||||
@Value("${com.hideyoshi.defaultUser.username}")
|
||||
@Value("${br.com.hideyoshi.defaultUser.username}")
|
||||
private String ADMIN_USERNAME;
|
||||
|
||||
@Value("${com.hideyoshi.defaultUser.password}")
|
||||
@Value("${br.com.hideyoshi.defaultUser.password}")
|
||||
private String ADMIN_PASSWORD;
|
||||
|
||||
@Bean
|
||||
@@ -53,4 +53,4 @@ public class DefaultUserConfig {
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.microservice.storageService.config;
|
||||
package br.com.hideyoshi.auth.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -8,6 +8,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Getter
|
||||
@Configuration
|
||||
public class StorageServiceConfig {
|
||||
@Value("${com.hideyoshi.microservice.storageServicePath}")
|
||||
@Value("${br.com.hideyoshi.microservice.storageServicePath}")
|
||||
private String fileServicePath;
|
||||
}
|
||||
@@ -1,23 +1,18 @@
|
||||
package com.hideyoshi.auth.healthChecker.api;
|
||||
package br.com.hideyoshi.auth.controller;
|
||||
|
||||
|
||||
import com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||
import com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
@Log4j2
|
||||
@Controller
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/health")
|
||||
public class HealthCheckerController {
|
||||
@RequestMapping
|
||||
@RequestMapping("/health")
|
||||
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
|
||||
public ResponseEntity<String> healthCheck() {
|
||||
log.info("Health check requested");
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.hideyoshi.auth.base.session.api;
|
||||
package br.com.hideyoshi.auth.controller;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||
import com.hideyoshi.auth.base.session.service.SessionManagerService;
|
||||
import br.com.hideyoshi.auth.model.UserAuthDTO;
|
||||
import br.com.hideyoshi.auth.service.SessionManagerService;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -16,17 +18,19 @@ import javax.servlet.http.HttpSession;
|
||||
@Controller
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping(path = "/session")
|
||||
@RequestMapping("/session")
|
||||
public class SessionController {
|
||||
|
||||
private final SessionManagerService sessionManagerService;
|
||||
|
||||
@GetMapping(path = "/validate")
|
||||
public ResponseEntity<AuthDTO> validateCurrentSession(HttpSession session) {
|
||||
@GetMapping("/validate")
|
||||
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
|
||||
public ResponseEntity<UserAuthDTO> validateCurrentSession(HttpSession session) {
|
||||
return ResponseEntity.ok(this.sessionManagerService.validateSession(session));
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/destroy")
|
||||
@DeleteMapping("/destroy")
|
||||
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
|
||||
public ResponseEntity<Void> destroyCurrentSession(HttpSession session) {
|
||||
this.sessionManagerService.destroySession(session);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
@@ -1,16 +1,17 @@
|
||||
package com.hideyoshi.auth.base.auth.api;
|
||||
package br.com.hideyoshi.auth.controller;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||
import com.hideyoshi.auth.base.auth.service.AuthService;
|
||||
import com.hideyoshi.auth.base.auth.model.TokenDTO;
|
||||
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||
import com.hideyoshi.auth.microservice.storageService.enums.FileTypeEnum;
|
||||
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceUploadResponse;
|
||||
import com.hideyoshi.auth.microservice.storageService.service.StorageService;
|
||||
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||
import com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
|
||||
import br.com.hideyoshi.auth.enums.FileTypeEnum;
|
||||
import br.com.hideyoshi.auth.model.UserAuthDTO;
|
||||
import br.com.hideyoshi.auth.model.TokenDTO;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.model.microservice.StorageServiceUploadResponse;
|
||||
import br.com.hideyoshi.auth.security.service.AuthService;
|
||||
import br.com.hideyoshi.auth.service.UserService;
|
||||
import br.com.hideyoshi.auth.service.microservice.StorageService;
|
||||
import br.com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||
import br.com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -20,13 +21,14 @@ import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
@Log4j2
|
||||
@Controller
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
@RequiredArgsConstructor
|
||||
public class UserController {
|
||||
@@ -45,7 +47,7 @@ public class UserController {
|
||||
|
||||
@PostMapping("/signup")
|
||||
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
|
||||
public ResponseEntity<AuthDTO> signupUser(@RequestBody @Valid UserDTO user, HttpServletRequest request) {
|
||||
public ResponseEntity<UserAuthDTO> signupUser(@RequestBody @Valid UserDTO user, HttpServletRequest request) {
|
||||
URI uri = URI.create(
|
||||
ServletUriComponentsBuilder
|
||||
.fromCurrentContextPath()
|
||||
@@ -56,7 +58,7 @@ public class UserController {
|
||||
|
||||
@PostMapping("/login/refresh")
|
||||
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
|
||||
public ResponseEntity<AuthDTO> refreshAccessToken(
|
||||
public ResponseEntity<UserAuthDTO> refreshAccessToken(
|
||||
@RequestBody @Valid TokenDTO refreshToken,
|
||||
HttpServletRequest request) {
|
||||
return ResponseEntity.ok(this.authService.refreshAccessToken(refreshToken.getToken(), request));
|
||||
@@ -64,7 +66,7 @@ public class UserController {
|
||||
|
||||
@PostMapping("/login/validate")
|
||||
@UserResourceGuard(accessType = UserResourceGuardEnum.USER)
|
||||
public ResponseEntity<AuthDTO> validateAccessToken(HttpServletRequest request) {
|
||||
public ResponseEntity<UserAuthDTO> validateAccessToken(HttpServletRequest request) {
|
||||
return ResponseEntity.ok(this.authService.validateAccessToken(request));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.hideyoshi.auth.base.auth.entity;
|
||||
package br.com.hideyoshi.auth.entity;
|
||||
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.hideyoshi.auth.microservice.storageService.enums;
|
||||
package br.com.hideyoshi.auth.enums;
|
||||
|
||||
import br.com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.microservice.storageService.enums;
|
||||
package br.com.hideyoshi.auth.enums;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.base.auth.entity;
|
||||
package br.com.hideyoshi.auth.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.base.auth.entity;
|
||||
package br.com.hideyoshi.auth.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.base.auth.model;
|
||||
package br.com.hideyoshi.auth.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.base.auth.model;
|
||||
package br.com.hideyoshi.auth.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.hideyoshi.auth.base.auth.model;
|
||||
package br.com.hideyoshi.auth.model;
|
||||
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AuthDTO implements Serializable {
|
||||
public class UserAuthDTO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
@@ -36,7 +36,7 @@ public class AuthDTO implements Serializable {
|
||||
|
||||
private TokenDTO refreshToken;
|
||||
|
||||
public AuthDTO(UserDTO user, TokenDTO accessToken, TokenDTO refreshToken) {
|
||||
public UserAuthDTO(UserDTO user, TokenDTO accessToken, TokenDTO refreshToken) {
|
||||
this.id = user.getId();
|
||||
this.name = user.getName();
|
||||
this.email = user.getEmail();
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.hideyoshi.auth.base.auth.model;
|
||||
package br.com.hideyoshi.auth.model;
|
||||
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import br.com.hideyoshi.auth.entity.User;
|
||||
import br.com.hideyoshi.auth.util.validator.email.unique.UniqueEmail;
|
||||
import br.com.hideyoshi.auth.util.validator.email.valid.ValidEmail;
|
||||
import br.com.hideyoshi.auth.util.validator.password.ValidPassword;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||
import com.hideyoshi.auth.base.auth.entity.User;
|
||||
import com.hideyoshi.auth.util.validator.email.unique.UniqueEmail;
|
||||
import com.hideyoshi.auth.util.validator.email.valid.ValidEmail;
|
||||
import com.hideyoshi.auth.util.validator.password.ValidPassword;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.microservice.storageService.model;
|
||||
package br.com.hideyoshi.auth.model.microservice;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.microservice.storageService.model;
|
||||
package br.com.hideyoshi.auth.model.microservice;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.hideyoshi.auth.base.auth.repo;
|
||||
package br.com.hideyoshi.auth.repository;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.User;
|
||||
import br.com.hideyoshi.auth.entity.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.base.config;
|
||||
package br.com.hideyoshi.auth.security.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -14,7 +14,7 @@ import java.util.List;
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
|
||||
@Value("${com.hideyoshi.frontendPath}")
|
||||
@Value("${br.com.hideyoshi.frontendPath}")
|
||||
private String FRONTEND_PATH;
|
||||
|
||||
@Bean
|
||||
@@ -35,4 +35,4 @@ public class CorsConfig {
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package br.com.hideyoshi.auth.security.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
public class PasswordEncoderConfig {
|
||||
|
||||
@Bean
|
||||
PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package br.com.hideyoshi.auth.security.config;
|
||||
|
||||
import br.com.hideyoshi.auth.model.UserAuthDTO;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.security.filter.JWTAuthenticationFilter;
|
||||
import br.com.hideyoshi.auth.security.oauth2.repository.OAuthRequestRepository;
|
||||
import br.com.hideyoshi.auth.security.service.AuthService;
|
||||
import br.com.hideyoshi.auth.service.UserService;
|
||||
import br.com.hideyoshi.auth.util.exception.AuthenticationInvalidExceptionDetails;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceHandler;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityConfig {
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final AuthService authService;
|
||||
private final UserService userService;
|
||||
private final OAuthRequestRepository oAuthRequestRepository;
|
||||
private final UserResourceHandler userResourceHandler;
|
||||
|
||||
@Bean
|
||||
public AuthenticationProvider authenticationProvider() {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
|
||||
provider.setUserDetailsService(this.userService);
|
||||
provider.setPasswordEncoder(this.passwordEncoder);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.httpBasic().disable()
|
||||
.cors().and().csrf().disable();
|
||||
|
||||
this.addEndpointSecurityToHttp(http);
|
||||
this.addOAuthSecurityToHttp(http);
|
||||
|
||||
this.configureEndpoints(http);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
private void configureEndpoints(HttpSecurity http) throws Exception {
|
||||
for (String endpoint : this.userResourceHandler.getOpenPaths()) {
|
||||
http.authorizeRequests().antMatchers(endpoint).permitAll();
|
||||
}
|
||||
|
||||
for (String endpoint : this.userResourceHandler.getGuardedPaths()) {
|
||||
http.authorizeRequests().antMatchers(endpoint).hasAnyAuthority("ROLE_USER", "ROLE_ADMIN");
|
||||
}
|
||||
|
||||
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
|
||||
http.addFilterBefore(
|
||||
new JWTAuthenticationFilter(this.authService),
|
||||
UsernamePasswordAuthenticationFilter.class
|
||||
);
|
||||
}
|
||||
|
||||
private void addEndpointSecurityToHttp(HttpSecurity http) throws Exception {
|
||||
http.formLogin(form -> form
|
||||
.loginProcessingUrl("/user/login")
|
||||
.successHandler(this::successFormHandler)
|
||||
.failureHandler(this::failureHandler)
|
||||
);
|
||||
|
||||
http.authorizeRequests().antMatchers("/login").denyAll();
|
||||
}
|
||||
|
||||
private void addOAuthSecurityToHttp(HttpSecurity http) throws Exception {
|
||||
|
||||
http.oauth2Login()
|
||||
.authorizationEndpoint()
|
||||
.authorizationRequestRepository(this.oAuthRequestRepository)
|
||||
.and().successHandler(this::successOAuth2Handler)
|
||||
.failureHandler(this::failureHandler);
|
||||
}
|
||||
|
||||
private void successFormHandler(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Authentication authentication) throws IOException {
|
||||
UserAuthDTO authUser = this.authService.loginUser(
|
||||
request,
|
||||
(UserDTO) authentication.getPrincipal()
|
||||
);
|
||||
|
||||
response.setContentType(APPLICATION_JSON_VALUE);
|
||||
new ObjectMapper()
|
||||
.writeValue(response.getOutputStream(), authUser);
|
||||
}
|
||||
|
||||
private void successOAuth2Handler(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Authentication authentication) throws IOException {
|
||||
UserAuthDTO authUser = this.authService.loginOAuthUser(
|
||||
request,
|
||||
(OAuth2User) authentication.getPrincipal()
|
||||
);
|
||||
|
||||
response.setContentType(APPLICATION_JSON_VALUE);
|
||||
new ObjectMapper()
|
||||
.writeValue(response.getOutputStream(), authUser);
|
||||
|
||||
}
|
||||
|
||||
private void failureHandler(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException e) throws IOException {
|
||||
response.setHeader("error", e.getMessage());
|
||||
response.setStatus(FORBIDDEN.value());
|
||||
|
||||
AuthenticationInvalidExceptionDetails error = new AuthenticationInvalidExceptionDetails("Authentication Failed. Check your credentials.",
|
||||
HttpStatus.FORBIDDEN.value(), e.getMessage(),
|
||||
e.getClass().getName(), LocalDateTime.now());
|
||||
|
||||
response.setContentType(APPLICATION_JSON_VALUE);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
|
||||
mapper.writeValue(response.getOutputStream(), error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package br.com.hideyoshi.auth.security.filter;
|
||||
|
||||
import br.com.hideyoshi.auth.security.service.AuthService;
|
||||
import br.com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
|
||||
|
||||
public class JWTAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final String AUTHORIZATION_TYPE_STRING = "Bearer ";
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
public JWTAuthenticationFilter(AuthService authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
try {
|
||||
this.setUserContext(request);
|
||||
} catch (Exception ignored) {
|
||||
// ignored
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private void setUserContext(HttpServletRequest request) {
|
||||
if (SecurityContextHolder.getContext().getAuthentication() != null) {
|
||||
return;
|
||||
}
|
||||
String authorizationHeader = request.getHeader(AUTHORIZATION);
|
||||
Authentication loggedUserInfo = this.validateUserAccess(authorizationHeader);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(loggedUserInfo);
|
||||
}
|
||||
|
||||
private Authentication validateUserAccess(String authorizationHeader) {
|
||||
if (Objects.nonNull(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) {
|
||||
String accessToken = authorizationHeader.substring(AUTHORIZATION_TYPE_STRING.length());
|
||||
return this.authService.extractAccessTokenInfo(accessToken);
|
||||
} else {
|
||||
throw new AuthenticationInvalidException("Access denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.base.auth.interceptor;
|
||||
package br.com.hideyoshi.auth.security.interceptor;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -7,12 +7,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ConfigInterceptor implements WebMvcConfigurer {
|
||||
public class InterceptorConfigurer implements WebMvcConfigurer {
|
||||
|
||||
private final UserResourceAccessInterceptor userResourceAccessInterceptor;
|
||||
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(userResourceAccessInterceptor);
|
||||
registry.addInterceptor(this.userResourceAccessInterceptor);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.hideyoshi.auth.base.auth.interceptor;
|
||||
package br.com.hideyoshi.auth.security.interceptor;
|
||||
|
||||
import br.com.hideyoshi.auth.service.UserService;
|
||||
import br.com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||
import br.com.hideyoshi.auth.util.exception.AuthorizationException;
|
||||
import br.com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||
import com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||
import com.hideyoshi.auth.util.guard.UserResourceGuard;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -21,8 +22,6 @@ public class UserResourceAccessInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) {
|
||||
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
@@ -34,12 +33,12 @@ public class UserResourceAccessInterceptor implements HandlerInterceptor {
|
||||
|
||||
if (Objects.nonNull(annotation)) {
|
||||
Boolean accessPermission =
|
||||
annotation.accessType().hasAccess(this.userService, this.objectMapper, request);
|
||||
annotation.accessType().hasAccess(this.userService, request);
|
||||
if (!accessPermission) {
|
||||
throw new AuthenticationInvalidException(annotation.denialMessage());
|
||||
throw new AuthorizationException(annotation.denialMessage());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package br.com.hideyoshi.auth.security.oauth2.handler;
|
||||
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.security.oauth2.model.OAuthDTO;
|
||||
import br.com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class OAuthHandler {
|
||||
public Provider getProviderFromURL(String url) {
|
||||
String[] urlPartition = url.split("/");
|
||||
return Provider.byValue(urlPartition[urlPartition.length - 1]);
|
||||
}
|
||||
|
||||
public OAuthDTO parseOAuth2User(OAuth2User user, Provider provider) {
|
||||
return switch (provider) {
|
||||
case GITHUB -> parseFromGithub(user);
|
||||
case GOOGLE -> parseFromGoogle(user);
|
||||
default -> throw new BadRequestException("Provider not supported.");
|
||||
};
|
||||
}
|
||||
|
||||
private OAuthDTO parseFromGithub(OAuth2User user) {
|
||||
return new OAuthDTO(
|
||||
user.getAttribute("name"),
|
||||
user.getAttribute("login"),
|
||||
user.getAttribute("email"),
|
||||
user.getAttribute("avatar_url"),
|
||||
Provider.GITHUB
|
||||
);
|
||||
}
|
||||
|
||||
private OAuthDTO parseFromGoogle(OAuth2User user) {
|
||||
return new OAuthDTO(
|
||||
user.getAttribute("name"),
|
||||
user.getAttribute("given_name"),
|
||||
user.getAttribute("email"),
|
||||
user.getAttribute("picture"),
|
||||
Provider.GOOGLE
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package br.com.hideyoshi.auth.security.oauth2.model;
|
||||
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class OAuthDTO {
|
||||
private String name;
|
||||
|
||||
private String username;
|
||||
|
||||
private String email;
|
||||
|
||||
private String profilePictureUrl;
|
||||
|
||||
private Provider provider;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.base.auth.oauth.repo;
|
||||
package br.com.hideyoshi.auth.security.oauth2.repository;
|
||||
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
|
||||
@@ -64,4 +64,4 @@ public class OAuthRequestRepository implements AuthorizationRequestRepository<OA
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,25 @@
|
||||
package com.hideyoshi.auth.base.auth.service;
|
||||
package br.com.hideyoshi.auth.security.service;
|
||||
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import br.com.hideyoshi.auth.model.UserAuthDTO;
|
||||
import br.com.hideyoshi.auth.model.TokenDTO;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.model.microservice.StorageServiceDownloadResponse;
|
||||
import br.com.hideyoshi.auth.security.oauth2.handler.OAuthHandler;
|
||||
import br.com.hideyoshi.auth.security.oauth2.model.OAuthDTO;
|
||||
import br.com.hideyoshi.auth.service.UserService;
|
||||
import br.com.hideyoshi.auth.service.microservice.StorageService;
|
||||
import br.com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
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.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -44,16 +46,18 @@ public class AuthService {
|
||||
|
||||
private final StorageService storageService;
|
||||
|
||||
@Value("${com.hideyoshi.tokenSecret}")
|
||||
private final OAuthHandler oAuthHandler;
|
||||
|
||||
@Value("${br.com.hideyoshi.tokenSecret}")
|
||||
private String TOKEN_SECRET;
|
||||
|
||||
@Value("${com.hideyoshi.accessTokenDuration}")
|
||||
@Value("${br.com.hideyoshi.accessTokenDuration}")
|
||||
private Integer ACCESS_TOKEN_DURATION;
|
||||
|
||||
@Value("${com.hideyoshi.refreshTokenDuration}")
|
||||
@Value("${br.com.hideyoshi.refreshTokenDuration}")
|
||||
private Integer REFRESH_TOKEN_DURATION;
|
||||
|
||||
public AuthDTO signupUser(@Valid UserDTO user, HttpServletRequest request) {
|
||||
public UserAuthDTO signupUser(@Valid UserDTO user, HttpServletRequest request) {
|
||||
user.setProvider(Provider.LOCAL);
|
||||
|
||||
UserDTO authenticatedUser = this.userService.saveUser(user);
|
||||
@@ -66,7 +70,7 @@ public class AuthService {
|
||||
|
||||
}
|
||||
|
||||
public AuthDTO loginUser(HttpServletRequest request, HttpServletResponse response, @Valid UserDTO user) throws IOException {
|
||||
public UserAuthDTO loginUser(HttpServletRequest request, @Valid UserDTO user) throws IOException {
|
||||
user.setProfilePictureUrl(this.extractProfilePictureUrl(user));
|
||||
|
||||
return this.generateNewAuthenticatedUser(
|
||||
@@ -75,20 +79,16 @@ public class AuthService {
|
||||
);
|
||||
}
|
||||
|
||||
public AuthDTO loginOAuthUser(OAuth2User oauthUser, HttpServletRequest request) {
|
||||
Provider clientProvider = Provider.byValue(
|
||||
this.getClientFromUrl(request.getRequestURL().toString())
|
||||
);
|
||||
public UserAuthDTO loginOAuthUser(HttpServletRequest request, OAuth2User oAuth2User) {
|
||||
Provider provider = this.oAuthHandler.getProviderFromURL(request.getRequestURL().toString());
|
||||
OAuthDTO oAuthDTO = this.oAuthHandler.parseOAuth2User(oAuth2User, provider);
|
||||
|
||||
OAuthMap oauthMap = this.generateOAuthMap(clientProvider, oauthUser);
|
||||
UserDTO user = this.getUserFromOAuth2User(oAuthDTO);
|
||||
|
||||
return this.processOAuthPostLogin(
|
||||
this.generateAuthenticatedUserFromOAuth(oauthMap, oauthUser),
|
||||
request
|
||||
);
|
||||
return this.processOAuthPostLogin(user, request);
|
||||
}
|
||||
|
||||
public AuthDTO refreshAccessToken(String requestToken, HttpServletRequest request) {
|
||||
public UserAuthDTO refreshAccessToken(String requestToken, HttpServletRequest request) {
|
||||
DecodedJWT decodedJWT = this.decodeToken(requestToken)
|
||||
.orElseThrow(() -> new BadRequestException("Invalid Token"));
|
||||
|
||||
@@ -100,7 +100,7 @@ public class AuthService {
|
||||
return this.refreshAuthenticatedUser(user, request, new TokenDTO(requestToken, decodedJWT.getExpiresAt()));
|
||||
}
|
||||
|
||||
public AuthDTO validateAccessToken(HttpServletRequest request) {
|
||||
public UserAuthDTO validateAccessToken(HttpServletRequest request) {
|
||||
UserDTO user = this.getLoggedUser();
|
||||
user.setProfilePictureUrl(this.extractProfilePictureUrl(user));
|
||||
|
||||
@@ -109,23 +109,20 @@ public class AuthService {
|
||||
}
|
||||
|
||||
public UserDTO getLoggedUser() {
|
||||
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
return userService.getUser(username);
|
||||
return (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
}
|
||||
|
||||
public UsernamePasswordAuthenticationToken extractAccessTokenInfo(String accessToken) {
|
||||
public Authentication 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);
|
||||
return new UsernamePasswordAuthenticationToken(
|
||||
this.userService.getUser(decodedJWT.getSubject()),
|
||||
null,
|
||||
stream(decodedJWT.getClaim("roles").asArray(String.class))
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
private Optional<DecodedJWT> decodeToken(String token) {
|
||||
@@ -139,7 +136,26 @@ public class AuthService {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private AuthDTO processOAuthPostLogin(@Valid UserDTO user, HttpServletRequest request) {
|
||||
private UserDTO getUserFromOAuth2User(OAuthDTO oAuth2User) {
|
||||
UserDTO user;
|
||||
|
||||
try {
|
||||
user = this.userService.getUser(oAuth2User.getUsername());
|
||||
} catch (BadRequestException e) {
|
||||
user = UserDTO.builder()
|
||||
.name(oAuth2User.getName())
|
||||
.username(oAuth2User.getUsername())
|
||||
.email(oAuth2User.getEmail())
|
||||
.roles(List.of(Role.USER))
|
||||
.provider(oAuth2User.getProvider())
|
||||
.profilePictureUrl(oAuth2User.getProfilePictureUrl())
|
||||
.build();
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
private UserAuthDTO processOAuthPostLogin(@Valid UserDTO user, HttpServletRequest request) {
|
||||
|
||||
if (Objects.nonNull(user.getId())) {
|
||||
this.userService.alterUser(user.getId(), user);
|
||||
@@ -150,47 +166,15 @@ public class AuthService {
|
||||
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) {
|
||||
private UserAuthDTO generateNewAuthenticatedUser(UserDTO user, HttpServletRequest request) {
|
||||
HttpSession httpSession = request.getSession();
|
||||
AuthDTO authObject = new AuthDTO(
|
||||
UserAuthDTO authObject = new UserAuthDTO(
|
||||
user,
|
||||
this.generateToken(user, request, ACCESS_TOKEN_DURATION),
|
||||
this.generateToken(user, request, REFRESH_TOKEN_DURATION)
|
||||
@@ -201,9 +185,9 @@ public class AuthService {
|
||||
return authObject;
|
||||
}
|
||||
|
||||
private AuthDTO refreshAuthenticatedUser(UserDTO user, HttpServletRequest request, TokenDTO refreshToken) {
|
||||
private UserAuthDTO refreshAuthenticatedUser(UserDTO user, HttpServletRequest request, TokenDTO refreshToken) {
|
||||
HttpSession httpSession = request.getSession();
|
||||
AuthDTO authObject = new AuthDTO(
|
||||
UserAuthDTO authObject = new UserAuthDTO(
|
||||
user,
|
||||
this.generateToken(user, request, ACCESS_TOKEN_DURATION),
|
||||
refreshToken
|
||||
@@ -0,0 +1,21 @@
|
||||
package br.com.hideyoshi.auth.service;
|
||||
|
||||
import br.com.hideyoshi.auth.model.UserAuthDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SessionManagerService {
|
||||
|
||||
public UserAuthDTO validateSession(HttpSession session) {
|
||||
return (UserAuthDTO) session.getAttribute("user");
|
||||
}
|
||||
|
||||
public void destroySession(HttpSession session) {
|
||||
session.invalidate();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
package com.hideyoshi.auth.base.auth.service;
|
||||
package br.com.hideyoshi.auth.service;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||
import com.hideyoshi.auth.base.auth.entity.User;
|
||||
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import br.com.hideyoshi.auth.entity.User;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.repository.UserRepository;
|
||||
import br.com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -132,7 +133,11 @@ public class UserService implements UserDetailsService {
|
||||
}
|
||||
|
||||
public UserDetails loadUserByUsername(String username) {
|
||||
return this.getUser(username);
|
||||
try {
|
||||
return this.getUser(username);
|
||||
} catch (BadRequestException e) {
|
||||
throw new UsernameNotFoundException("User not found.");
|
||||
}
|
||||
}
|
||||
|
||||
private String validatePassword(UserDTO user) {
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.hideyoshi.auth.microservice.storageService.service;
|
||||
package br.com.hideyoshi.auth.service.microservice;
|
||||
|
||||
import br.com.hideyoshi.auth.config.StorageServiceConfig;
|
||||
import br.com.hideyoshi.auth.enums.FileTypeEnum;
|
||||
import br.com.hideyoshi.auth.model.microservice.StorageServiceDownloadResponse;
|
||||
import br.com.hideyoshi.auth.model.microservice.StorageServiceUploadResponse;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hideyoshi.auth.microservice.storageService.config.StorageServiceConfig;
|
||||
import com.hideyoshi.auth.microservice.storageService.enums.FileTypeEnum;
|
||||
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceDownloadResponse;
|
||||
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceUploadResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
@@ -20,9 +20,9 @@ import org.apache.http.util.EntityUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -137,11 +137,7 @@ public class StorageService {
|
||||
HttpPost request = new HttpPost(requestURI);
|
||||
request.setHeader("Content-Type", "application/json");
|
||||
|
||||
try {
|
||||
request.setEntity(new ByteArrayEntity(requestBody.getBytes("UTF-8")));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
request.setEntity(new ByteArrayEntity(requestBody.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
CloseableHttpClient httpClient = HttpClientBuilder.create()
|
||||
.setRedirectStrategy(new LaxRedirectStrategy()).build();
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.exception;
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.exception;
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public class AuthorizationException extends RuntimeException {
|
||||
|
||||
public AuthorizationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class AuthorizationExceptionDetails extends ExceptionDetails {
|
||||
public AuthorizationExceptionDetails(String title, Integer status, String details, String developerMessage, LocalDateTime timestamp) {
|
||||
super(title, status, details, developerMessage, timestamp);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.exception;
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.exception;
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.exception;
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.exception;
|
||||
package br.com.hideyoshi.auth.util.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.guard;
|
||||
package br.com.hideyoshi.auth.util.guard;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.hideyoshi.auth.util.guard;
|
||||
package br.com.hideyoshi.auth.util.guard;
|
||||
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.service.UserService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||
import lombok.Getter;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -19,9 +19,8 @@ public enum UserResourceGuardEnum {
|
||||
@Override
|
||||
public Boolean hasAccess(
|
||||
UserService userService,
|
||||
ObjectMapper objectMapper,
|
||||
HttpServletRequest request) {
|
||||
return justUser(userService, objectMapper, request);
|
||||
return UserResourceGuardEnum.justUser(userService, request);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -29,9 +28,8 @@ public enum UserResourceGuardEnum {
|
||||
@Override
|
||||
public Boolean hasAccess(
|
||||
UserService userService,
|
||||
ObjectMapper objectMapper,
|
||||
HttpServletRequest request) {
|
||||
return sameUser(userService, objectMapper, request);
|
||||
return UserResourceGuardEnum.sameUser(userService, request);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -39,9 +37,8 @@ public enum UserResourceGuardEnum {
|
||||
@Override
|
||||
public Boolean hasAccess(
|
||||
UserService userService,
|
||||
ObjectMapper objectMapper,
|
||||
HttpServletRequest request) {
|
||||
return adminUser(userService, objectMapper, request);
|
||||
return UserResourceGuardEnum.adminUser(userService, request);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -49,9 +46,8 @@ public enum UserResourceGuardEnum {
|
||||
@Override
|
||||
public Boolean hasAccess(
|
||||
UserService userService,
|
||||
ObjectMapper objectMapper,
|
||||
HttpServletRequest request) {
|
||||
return openAccess(userService, objectMapper, request);
|
||||
return openAccess(userService, request);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,19 +66,18 @@ public enum UserResourceGuardEnum {
|
||||
throw new IllegalArgumentException("Argument not valid.");
|
||||
}
|
||||
|
||||
private static boolean justUser(UserService userService, ObjectMapper objectMapper, HttpServletRequest request) {
|
||||
|
||||
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
UserDTO userLogged = userService.getUser(username);
|
||||
private static boolean justUser(UserService userService, HttpServletRequest request) {
|
||||
UserDTO userLogged = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
|
||||
return userLogged.getAuthorities().contains(new SimpleGrantedAuthority(Role.USER.getDescription()));
|
||||
}
|
||||
|
||||
private static boolean sameUser(UserService userService, ObjectMapper objectMapper, HttpServletRequest request) {
|
||||
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
UserDTO userLogged = userService.getUser(username);
|
||||
private static boolean sameUser(UserService userService, HttpServletRequest request) {
|
||||
UserDTO userLogged = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
|
||||
Object requestPathVariable = request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
HashMap<String, String> pathVariable = objectMapper.convertValue(requestPathVariable, HashMap.class);
|
||||
UserDTO userInfo = userService.getUser(Long.parseLong(pathVariable.get("id")));
|
||||
|
||||
@@ -90,20 +85,17 @@ public enum UserResourceGuardEnum {
|
||||
|
||||
}
|
||||
|
||||
private static boolean adminUser(UserService userService, ObjectMapper objectMapper, HttpServletRequest request) {
|
||||
String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
UserDTO userLogged = userService.getUser(username);
|
||||
|
||||
private static boolean adminUser(UserService userService, HttpServletRequest request) {
|
||||
UserDTO userLogged = (UserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
return userLogged.getAuthorities().contains(new SimpleGrantedAuthority(Role.ADMIN.getDescription()));
|
||||
}
|
||||
|
||||
private static Boolean openAccess(UserService userService, ObjectMapper objectMapper, HttpServletRequest request) {
|
||||
private static Boolean openAccess(UserService userService, HttpServletRequest request) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract Boolean hasAccess(
|
||||
UserService userService,
|
||||
ObjectMapper objectMapper,
|
||||
HttpServletRequest request);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package br.com.hideyoshi.auth.util.guard;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class UserResourceHandler {
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
public List<String> getGuardedPaths() {
|
||||
return this.extractPathsFromMethods(this.getGuardedResources());
|
||||
}
|
||||
|
||||
public List<String> getOpenPaths() {
|
||||
return this.extractPathsFromMethods(this.getOpenResources());
|
||||
}
|
||||
|
||||
private List<String> extractPathsFromMethods(List<Method> methods) {
|
||||
final List<String> paths = new ArrayList<>();
|
||||
for (final Method method : methods) {
|
||||
String[] parentPath = new String[0];
|
||||
|
||||
RequestMapping classAnnotation = method.getDeclaringClass().getAnnotation(RequestMapping.class);
|
||||
if (classAnnotation != null) {
|
||||
parentPath = this.getPathFromAnnotation(classAnnotation);
|
||||
}
|
||||
|
||||
List<Annotation> annotations = List.of(method.getAnnotations());
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
final String[] path = this.getPathFromAnnotation(annotation);
|
||||
|
||||
if (path != null)
|
||||
paths.add(String.join("/", parentPath) + String.join("/", path));
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
private List<Method> getGuardedResources() {
|
||||
final List<UserResourceGuardEnum> guardedAccessTypes = Arrays.asList(
|
||||
UserResourceGuardEnum.USER,
|
||||
UserResourceGuardEnum.SAME_USER,
|
||||
UserResourceGuardEnum.ADMIN_USER
|
||||
);
|
||||
final List<Method> methods = new ArrayList<>();
|
||||
|
||||
for (final Class<?> controllerClass : this.getControllerClasses()) {
|
||||
methods.addAll(this.getMethodsByAccessType(controllerClass, guardedAccessTypes));
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
private List<Method> getOpenResources() {
|
||||
final List<UserResourceGuardEnum> openAccessTypes = List.of(UserResourceGuardEnum.OPEN);
|
||||
final List<Method> methods = new ArrayList<>();
|
||||
|
||||
for (final Class<?> controllerClass : this.getControllerClasses()) {
|
||||
methods.addAll(this.getMethodsByAccessType(controllerClass, openAccessTypes));
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
private List<Method> getMethodsByAccessType(final Class<?> controllerClass, List<UserResourceGuardEnum> accessTypes) {
|
||||
final List<Method> methods = new ArrayList<>();
|
||||
for (final Method method : controllerClass.getDeclaredMethods()) {
|
||||
if (!method.isAnnotationPresent(UserResourceGuard.class)) {
|
||||
continue;
|
||||
}
|
||||
UserResourceGuard annotation = method.getAnnotation(UserResourceGuard.class);
|
||||
if (!accessTypes.contains(annotation.accessType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
methods.add(method);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
private List<Class<?>> getControllerClasses() {
|
||||
final List<Class<?>> controllerClasses = new ArrayList<>();
|
||||
for (final String beanName : this.beanFactory.getBeanNamesForAnnotation(Controller.class)) {
|
||||
controllerClasses.add(this.beanFactory.getType(beanName));
|
||||
}
|
||||
return controllerClasses;
|
||||
}
|
||||
|
||||
private String[] getPathFromAnnotation(Annotation annotation) {
|
||||
String[] path; String[] value;
|
||||
|
||||
try {
|
||||
value = (String[]) annotation.annotationType().getMethod("value").invoke(annotation);
|
||||
path = (String[]) annotation.annotationType().getMethod("path").invoke(annotation);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return value.length > 0 ? value : path;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.hideyoshi.auth.util.guard;
|
||||
package br.com.hideyoshi.auth.util.guard;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.hideyoshi.auth.util.handler;
|
||||
package br.com.hideyoshi.auth.util.handler;
|
||||
|
||||
import com.hideyoshi.auth.util.exception.*;
|
||||
import br.com.hideyoshi.auth.util.exception.*;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -40,6 +40,15 @@ public class RestExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
@ExceptionHandler(AuthorizationException.class)
|
||||
public ResponseEntity<AuthorizationExceptionDetails> handleBadRequest(final AuthorizationException exception) {
|
||||
return new ResponseEntity<>(
|
||||
new AuthorizationExceptionDetails("Authorization Failed. Check your permissions.",
|
||||
HttpStatus.FORBIDDEN.value(), exception.getMessage(),
|
||||
exception.getClass().getName(), LocalDateTime.now()),
|
||||
HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResponseEntity<Object> handleMethodArgumentNotValid(
|
||||
final MethodArgumentNotValidException exception, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.hideyoshi.auth.util.validator.email.unique;
|
||||
package br.com.hideyoshi.auth.util.validator.email.unique;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||
import br.com.hideyoshi.auth.repository.UserRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.validator.email.unique;
|
||||
package br.com.hideyoshi.auth.util.validator.email.unique;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.validator.email.valid;
|
||||
package br.com.hideyoshi.auth.util.validator.email.valid;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth.util.validator.email.valid;
|
||||
package br.com.hideyoshi.auth.util.validator.email.valid;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.hideyoshi.auth.util.validator.password;
|
||||
package br.com.hideyoshi.auth.util.validator.password;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.hideyoshi.auth.util.validator.password;
|
||||
package br.com.hideyoshi.auth.util.validator.password;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.hideyoshi.auth;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@SpringBootApplication
|
||||
public class AuthServiceApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AuthServiceApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
package com.hideyoshi.auth.base.auth.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hideyoshi.auth.base.config.RestAuthenticationEntryPointConfig;
|
||||
import com.hideyoshi.auth.base.auth.filter.CustomAuthenticationFilter;
|
||||
import com.hideyoshi.auth.base.auth.filter.CustomAuthorizationFilter;
|
||||
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||
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.extern.log4j.Log4j2;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
@Log4j2
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
private final UserDetailsService userDetailsService;
|
||||
|
||||
private final BCryptPasswordEncoder passwordEncoder;
|
||||
|
||||
private final OAuthRequestRepository oAuthRequestRepository;
|
||||
|
||||
private final RestAuthenticationEntryPointConfig restAuthenticationEntryPointConfig;
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService)
|
||||
.passwordEncoder(passwordEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http.cors().and().csrf().disable();
|
||||
|
||||
this.addSecurityToHttp(http);
|
||||
this.addOAuthSecurityToHttp(http);
|
||||
}
|
||||
|
||||
private void addSecurityToHttp(HttpSecurity http) throws Exception {
|
||||
|
||||
CustomAuthenticationFilter customAuthenticationFilter =
|
||||
new CustomAuthenticationFilter(this.authenticationManager(), this.authService, this.restAuthenticationEntryPointConfig);
|
||||
|
||||
customAuthenticationFilter.setFilterProcessesUrl("/user/login");
|
||||
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/session/**").permitAll()
|
||||
.and().authorizeRequests().antMatchers("/health").permitAll()
|
||||
.and().authorizeRequests().antMatchers("/user/signup").permitAll()
|
||||
.and().authorizeRequests().antMatchers("/user/oauth/**").permitAll()
|
||||
.and().authorizeRequests().antMatchers("/user/login/**").permitAll()
|
||||
.and().authorizeRequests().antMatchers("/**").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
|
||||
|
||||
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
|
||||
.and().addFilter(customAuthenticationFilter)
|
||||
|
||||
.addFilterBefore(new CustomAuthorizationFilter(this.authService), UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
}
|
||||
|
||||
private void addOAuthSecurityToHttp(HttpSecurity http) throws Exception {
|
||||
|
||||
http.oauth2Login()
|
||||
.authorizationEndpoint()
|
||||
.authorizationRequestRepository(this.oAuthRequestRepository)
|
||||
.and().successHandler(this::successHandler)
|
||||
.failureHandler(this::failureHandler);
|
||||
}
|
||||
|
||||
private void successHandler(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Authentication authentication) throws IOException {
|
||||
|
||||
OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
|
||||
|
||||
AuthDTO authUser = this.authService.loginOAuthUser(oauthUser, request);
|
||||
|
||||
response.setContentType(APPLICATION_JSON_VALUE);
|
||||
new ObjectMapper()
|
||||
.writeValue(response.getOutputStream(), authUser);
|
||||
|
||||
}
|
||||
|
||||
private void failureHandler(
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException e) {
|
||||
throw new AuthenticationInvalidException("Invalid Authentication Attempt.");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.hideyoshi.auth.base.auth.filter;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hideyoshi.auth.base.config.RestAuthenticationEntryPointConfig;
|
||||
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 org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
@Log4j2
|
||||
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
private final RestAuthenticationEntryPointConfig restAuthenticationEntryPointConfig;
|
||||
|
||||
public CustomAuthenticationFilter(AuthenticationManager authenticationManager, AuthService authService, RestAuthenticationEntryPointConfig restAuthenticationEntryPointConfig) {
|
||||
this.authService = authService;
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.restAuthenticationEntryPointConfig = restAuthenticationEntryPointConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
|
||||
|
||||
String username = request.getParameter("username");
|
||||
String password = request.getParameter("password");
|
||||
|
||||
Authentication userAuthentication = null;
|
||||
try {
|
||||
userAuthentication = authenticationManager.authenticate(
|
||||
new UsernamePasswordAuthenticationToken(username, password)
|
||||
);
|
||||
} catch (AuthenticationException e) {
|
||||
restAuthenticationEntryPointConfig.commence(request, response, e);
|
||||
}
|
||||
return userAuthentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException {
|
||||
|
||||
AuthDTO authUser = this.authService.loginUser(
|
||||
request,
|
||||
response,
|
||||
(UserDTO) authentication.getPrincipal()
|
||||
);
|
||||
|
||||
response.setContentType(APPLICATION_JSON_VALUE);
|
||||
new ObjectMapper()
|
||||
.writeValue(response.getOutputStream(), authUser);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package com.hideyoshi.auth.base.auth.filter;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hideyoshi.auth.base.auth.service.AuthService;
|
||||
import com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||
import com.hideyoshi.auth.util.exception.AuthenticationInvalidExceptionDetails;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
public class CustomAuthorizationFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final List<String> notProtectedPaths = Arrays.asList(
|
||||
"/health",
|
||||
"/user/login",
|
||||
"/user/signup",
|
||||
"/user/login/refresh",
|
||||
"/session/validate",
|
||||
"/session/destroy"
|
||||
);
|
||||
|
||||
private static final String AUTHORIZATION_TYPE_STRING = "Bearer ";
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
public CustomAuthorizationFilter(AuthService authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
if (this.isPathNotProtected(request.getServletPath())) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String authorizationHeader = request.getHeader(AUTHORIZATION);
|
||||
|
||||
try {
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
this.validateUserAccess(authorizationHeader);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
filterChain.doFilter(request, response);
|
||||
|
||||
} catch (Exception e) {
|
||||
response.setHeader("error", e.getMessage());
|
||||
response.setStatus(FORBIDDEN.value());
|
||||
|
||||
AuthenticationInvalidExceptionDetails error = new AuthenticationInvalidExceptionDetails("Authentication Failed. Check your credentials.",
|
||||
HttpStatus.FORBIDDEN.value(), e.getMessage(),
|
||||
e.getClass().getName(), LocalDateTime.now());
|
||||
|
||||
response.setContentType(APPLICATION_JSON_VALUE);
|
||||
new ObjectMapper()
|
||||
.writeValue(response.getOutputStream(), error);
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean isPathNotProtected(String path) {
|
||||
return notProtectedPaths.contains(path);
|
||||
}
|
||||
|
||||
private UsernamePasswordAuthenticationToken validateUserAccess(String authorizationHeader) {
|
||||
if (Objects.nonNull(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) {
|
||||
String accessToken = authorizationHeader.substring(AUTHORIZATION_TYPE_STRING.length());
|
||||
return this.authService.extractAccessTokenInfo(accessToken);
|
||||
} else {
|
||||
throw new AuthenticationInvalidException("Access denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.hideyoshi.auth.base.auth.oauth.mapper;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GithubOAuthMap implements OAuthMap {
|
||||
|
||||
private OAuth2User oAuth2User;
|
||||
|
||||
@Override
|
||||
public String getPrincipal() {
|
||||
return oAuth2User.getAttribute("login");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProfilePicture() {
|
||||
return this.oAuth2User.getAttribute("avatar_url");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Provider getProvider() {
|
||||
return Provider.GITHUB;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.hideyoshi.auth.base.auth.oauth.mapper;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class GoogleOAuthMap implements OAuthMap {
|
||||
|
||||
private OAuth2User oAuth2User;
|
||||
|
||||
@Override
|
||||
public String getPrincipal() {
|
||||
return this.oAuth2User.getAttribute("given_name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProfilePicture() {
|
||||
return this.oAuth2User.getAttribute("picture");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Provider getProvider() {
|
||||
return Provider.GOOGLE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
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,35 +0,0 @@
|
||||
package com.hideyoshi.auth.base.auth.oauth.mapper;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import lombok.Getter;
|
||||
|
||||
public enum OAuthMapper {
|
||||
|
||||
GOOGLE(GoogleOAuthMap.class, Provider.GOOGLE),
|
||||
|
||||
GITHUB(GithubOAuthMap.class, Provider.GITHUB);
|
||||
|
||||
private final Class<? extends OAuthMap> oAuthMap;
|
||||
|
||||
@Getter
|
||||
private final Provider provider;
|
||||
|
||||
private OAuthMapper(Class<? extends OAuthMap> oAuthMap, Provider provider) {
|
||||
this.oAuthMap = oAuthMap;
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public static OAuthMapper byValue(Provider provider) {
|
||||
for (OAuthMapper e : values()) {
|
||||
if (e.getProvider().equals(provider)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Argument not valid.");
|
||||
}
|
||||
|
||||
public Class<? extends OAuthMap> getMap() {
|
||||
return oAuthMap;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.hideyoshi.auth.base.config;
|
||||
|
||||
import com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Log4j2
|
||||
@Component("restAuthenticationEntryPoint")
|
||||
public class RestAuthenticationEntryPointConfig implements AuthenticationEntryPoint {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("handlerExceptionResolver")
|
||||
private HandlerExceptionResolver resolver;
|
||||
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) {
|
||||
|
||||
resolver.resolveException(
|
||||
request,
|
||||
response,
|
||||
null,
|
||||
new AuthenticationInvalidException("Authentication Failed. Check your credentials.")
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.hideyoshi.auth.base.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.session.web.http.CookieSerializer;
|
||||
import org.springframework.session.web.http.DefaultCookieSerializer;
|
||||
|
||||
public class SessionConfig {
|
||||
|
||||
@Value("${com.hideyoshi.frontEndPath}")
|
||||
private String frontEndPath;
|
||||
|
||||
@Bean
|
||||
public CookieSerializer cookieSerializer() {
|
||||
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
|
||||
serializer.setCookieName("SESSION");
|
||||
serializer.setCookiePath("/");
|
||||
serializer.setDomainNamePattern("(^.+)?(\\.)?(" + frontEndPath + ")((/#!)?(/\\w+)+)?");
|
||||
return serializer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.hideyoshi.auth.base.session.service;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
public interface SessionManagerService {
|
||||
|
||||
AuthDTO validateSession(HttpSession session);
|
||||
|
||||
void destroySession(HttpSession session);
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.hideyoshi.auth.base.session.service;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.model.AuthDTO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SessionManagerServiceImpl implements SessionManagerService {
|
||||
|
||||
@Override
|
||||
public AuthDTO validateSession(HttpSession session) {
|
||||
return (AuthDTO) session.getAttribute("user");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroySession(HttpSession session) {
|
||||
session.invalidate();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
com:
|
||||
hideyoshi:
|
||||
frontendPath: ${FRONTEND_PATH}
|
||||
tokenSecret: ${TOKEN_SECRET}
|
||||
accessTokenDuration: ${ACCESS_TOKEN_DURATION}
|
||||
refreshTokenDuration: ${REFRESH_TOKEN_DURATION}
|
||||
defaultUser:
|
||||
fullName: ${DEFAULT_USER_FULLNAME}
|
||||
email: ${DEFAULT_USER_EMAIL}
|
||||
username: ${DEFAULT_USER_USERNAME}
|
||||
password: ${DEFAULT_USER_PASSWORD}
|
||||
br:
|
||||
com:
|
||||
hideyoshi:
|
||||
frontendPath: ${FRONTEND_PATH}
|
||||
tokenSecret: ${TOKEN_SECRET}
|
||||
accessTokenDuration: ${ACCESS_TOKEN_DURATION}
|
||||
refreshTokenDuration: ${REFRESH_TOKEN_DURATION}
|
||||
defaultUser:
|
||||
fullName: ${DEFAULT_USER_FULLNAME}
|
||||
email: ${DEFAULT_USER_EMAIL}
|
||||
username: ${DEFAULT_USER_USERNAME}
|
||||
password: ${DEFAULT_USER_PASSWORD}
|
||||
|
||||
microservice:
|
||||
storageServicePath: ${STORAGE_SERVICE_PATH}
|
||||
microservice:
|
||||
storageServicePath: ${STORAGE_SERVICE_PATH}
|
||||
|
||||
|
||||
server:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.hideyoshi.auth;
|
||||
package br.com.hideyoshi.auth;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.hideyoshi.auth.base.user.repo;
|
||||
package br.com.hideyoshi.auth.repository;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||
import com.hideyoshi.auth.base.auth.entity.User;
|
||||
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import br.com.hideyoshi.auth.entity.User;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.hideyoshi.auth.base.user.service;
|
||||
package br.com.hideyoshi.auth.service;
|
||||
|
||||
import com.hideyoshi.auth.base.auth.service.UserService;
|
||||
import com.hideyoshi.auth.base.auth.entity.Provider;
|
||||
import com.hideyoshi.auth.base.auth.entity.Role;
|
||||
import com.hideyoshi.auth.base.auth.entity.User;
|
||||
import com.hideyoshi.auth.base.auth.model.UserDTO;
|
||||
import com.hideyoshi.auth.base.auth.repo.UserRepository;
|
||||
import com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import br.com.hideyoshi.auth.enums.Provider;
|
||||
import br.com.hideyoshi.auth.enums.Role;
|
||||
import br.com.hideyoshi.auth.entity.User;
|
||||
import br.com.hideyoshi.auth.model.UserDTO;
|
||||
import br.com.hideyoshi.auth.repository.UserRepository;
|
||||
import br.com.hideyoshi.auth.util.exception.BadRequestException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -17,6 +16,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
@@ -387,7 +387,7 @@ class UserServiceTest {
|
||||
// When
|
||||
//Then
|
||||
assertThrows(
|
||||
BadRequestException.class,
|
||||
UsernameNotFoundException.class,
|
||||
() -> {
|
||||
this.underTest.loadUserByUsername(user.getUsername());
|
||||
},
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.hideyoshi.auth.microservice.storageService.service;
|
||||
package br.com.hideyoshi.auth.service.microservice;
|
||||
|
||||
import br.com.hideyoshi.auth.config.StorageServiceConfig;
|
||||
import br.com.hideyoshi.auth.enums.FileTypeEnum;
|
||||
import br.com.hideyoshi.auth.model.microservice.StorageServiceDownloadResponse;
|
||||
import br.com.hideyoshi.auth.model.microservice.StorageServiceUploadResponse;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.hideyoshi.auth.microservice.storageService.config.StorageServiceConfig;
|
||||
import com.hideyoshi.auth.microservice.storageService.enums.FileTypeEnum;
|
||||
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceDownloadResponse;
|
||||
import com.hideyoshi.auth.microservice.storageService.model.StorageServiceUploadResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
Reference in New Issue
Block a user