Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 36 additions & 7 deletions src/main/java/com/provedcode/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.provedcode.user.mapper.UserInfoMapper;
import com.provedcode.user.repo.UserInfoRepository;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand Down Expand Up @@ -34,6 +37,7 @@
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
Expand All @@ -43,25 +47,50 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
http.authorizeHttpRequests(c -> c
.requestMatchers("/actuator/health").permitAll() // for DevOps
.requestMatchers(antMatcher("/h2/**")).permitAll()
.requestMatchers(antMatcher("/api/talents/login")).permitAll()
//.requestMatchers(antMatcher("/api/talents/login")).permitAll()
.requestMatchers(antMatcher("/api/talents/**")).permitAll()
.requestMatchers(antMatcher("/error")).permitAll()
.anyRequest().authenticated()
);

http.exceptionHandling(c -> c
.authenticationEntryPoint((request, response, authException) -> {
log.info("Authentication failed {}, message:{}",
describe(request),
authException.getMessage());
response.sendError(
HttpStatus.UNAUTHORIZED.value(),
authException.getMessage());
}
)
.accessDeniedHandler((request, response, accessDeniedException) -> {
log.info("Authorization failed {},message: {}",
describe(request),
accessDeniedException.getMessage());
response.sendError(HttpStatus.FORBIDDEN.value(),
accessDeniedException.getMessage());
}
)
);

http.httpBasic(Customizer.withDefaults());
http.csrf().disable().headers().disable();

http.sessionManagement().sessionCreationPolicy(STATELESS);

http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.exceptionHandling(c -> c
.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())
);
.exceptionHandling(c -> c
.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())
);

return http.build();
}

public String describe(HttpServletRequest request) {
return request.getRequestURI();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
Expand Down Expand Up @@ -90,8 +119,8 @@ UserDetailsService userDetailsService(
UserInfoMapper mapper
) {
return login -> repository.findByLogin(login)
.map(mapper::toUserDetails)
.orElseThrow(() -> new UsernameNotFoundException(login + " not found"));
.map(mapper::toUserDetails)
.orElseThrow(() -> new UsernameNotFoundException(login + " not found"));
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public class Authority {
@NotNull
@Column(name = "authority", length = 20)
private String authority;
@ManyToMany(mappedBy = "authorities", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@ManyToMany(fetch = FetchType.EAGER, mappedBy = "authorities", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<UserInfo> userInfoes = new LinkedHashSet<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class UserInfo {
@OneToOne(orphanRemoval = true)
@JoinColumn(name = "talent_id", insertable = false, updatable = false)
private Talent talent;
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "user_authorities",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "authority_id"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.provedcode.talent.repo.TalentRepository;
import com.provedcode.user.model.dto.RegistrationDTO;
import com.provedcode.user.model.dto.SessionInfoDTO;
import com.provedcode.user.model.entity.Authority;
import com.provedcode.user.model.entity.UserInfo;
import com.provedcode.user.repo.AuthorityRepository;
import com.provedcode.user.repo.UserInfoRepository;
Expand Down Expand Up @@ -81,7 +80,7 @@ private String generateJWTToken(String name, Collection<? extends GrantedAuthori
var claims = JwtClaimsSet.builder()
.issuer("self")
.issuedAt(now)
.expiresAt(now.plus(5, MINUTES))
.expiresAt(now.plus(60, MINUTES))
.subject(name)
.claim("scope", authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(" ")))
.build();
Expand Down