authentication

This commit is contained in:
2024-11-18 16:26:53 +01:00
parent 576c5155d9
commit a59d438dbb
8 changed files with 327 additions and 40 deletions
@@ -3,15 +3,25 @@ package com.sasiedzi.event.config;
import static org.springframework.security.config.Customizer.withDefaults; import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.PREFERRED_USERNAME; import static org.springframework.security.oauth2.core.oidc.StandardClaimNames.PREFERRED_USERNAME;
import com.sasiedzi.event.domain.CurrentUserHolder;
import com.sasiedzi.event.repository.UserRepository;
import com.sasiedzi.event.security.*; import com.sasiedzi.event.security.*;
import com.sasiedzi.event.security.SecurityUtils; import com.sasiedzi.event.security.SecurityUtils;
import com.sasiedzi.event.security.oauth2.AudienceValidator; import com.sasiedzi.event.security.oauth2.AudienceValidator;
import com.sasiedzi.event.security.oauth2.CustomClaimConverter; import com.sasiedzi.event.security.oauth2.CustomClaimConverter;
import com.sasiedzi.event.service.EventService;
import com.sasiedzi.event.service.UserService;
import com.sasiedzi.event.service.dto.AdminUserDTO;
import com.sasiedzi.event.web.filter.SpaWebFilter; import com.sasiedzi.event.web.filter.SpaWebFilter;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.util.*; import java.util.*;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -21,8 +31,15 @@ import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.FrameOptionsConfig; import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.FrameOptionsConfig;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
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.oauth2.client.oidc.userinfo.OidcUserRequest; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
@@ -35,11 +52,14 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.oauth2.jwt.*; import org.springframework.security.oauth2.jwt.*;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.*; import org.springframework.security.web.csrf.*;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector; import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import tech.jhipster.config.JHipsterProperties; import tech.jhipster.config.JHipsterProperties;
import tech.jhipster.web.filter.CookieCsrfFilter; import tech.jhipster.web.filter.CookieCsrfFilter;
@@ -82,27 +102,140 @@ public class SecurityConfiguration {
.authorizeHttpRequests(authz -> .authorizeHttpRequests(authz ->
// prettier-ignore // prettier-ignore
authz authz
.requestMatchers(mvc.pattern("/index.html"), mvc.pattern("/*.js"), mvc.pattern("/*.txt"), mvc.pattern("/*.json"), mvc.pattern("/*.map"), mvc.pattern("/*.css")).permitAll() // .requestMatchers(mvc.pattern("/index.html"), mvc.pattern("/*.js"), mvc.pattern("/*.txt"), mvc.pattern("/*.json"), mvc.pattern("/*.map"), mvc.pattern("/*.css")).permitAll()
.requestMatchers(mvc.pattern("/*.ico"), mvc.pattern("/*.png"), mvc.pattern("/*.svg"), mvc.pattern("/*.webapp")).permitAll() // .requestMatchers(mvc.pattern("/*.ico"), mvc.pattern("/*.png"), mvc.pattern("/*.svg"), mvc.pattern("/*.webapp")).permitAll()
.requestMatchers(mvc.pattern("/assets/**")).permitAll() // .requestMatchers(mvc.pattern("/assets/**")).permitAll()
.requestMatchers(mvc.pattern("/swagger-ui/**")).permitAll() // .requestMatchers(mvc.pattern("/swagger-ui/**")).permitAll()
.requestMatchers(mvc.pattern("/api/authenticate")).permitAll() // .requestMatchers(mvc.pattern("/api/authenticate")).permitAll()
.requestMatchers(mvc.pattern("/api/auth-info")).permitAll() // .requestMatchers(mvc.pattern("/api/auth-info")).permitAll()
.requestMatchers(mvc.pattern("/logout")).permitAll()
.requestMatchers(mvc.pattern("/api/admin/**")).hasAuthority(AuthoritiesConstants.ADMIN) .requestMatchers(mvc.pattern("/api/admin/**")).hasAuthority(AuthoritiesConstants.ADMIN)
.requestMatchers(mvc.pattern("/api/**")).authenticated() // .requestMatchers(mvc.pattern("/api/**")).authenticated()
.requestMatchers(mvc.pattern("/**")).authenticated()
.requestMatchers(mvc.pattern("/v3/api-docs/**")).hasAuthority(AuthoritiesConstants.ADMIN) .requestMatchers(mvc.pattern("/v3/api-docs/**")).hasAuthority(AuthoritiesConstants.ADMIN)
.requestMatchers(mvc.pattern("/management/health")).permitAll() // .requestMatchers(mvc.pattern("/management/health")).permitAll()
.requestMatchers(mvc.pattern("/management/health/**")).permitAll() // .requestMatchers(mvc.pattern("/management/health/**")).permitAll()
.requestMatchers(mvc.pattern("/management/info")).permitAll() // .requestMatchers(mvc.pattern("/management/info")).permitAll()
.requestMatchers(mvc.pattern("/management/prometheus")).permitAll() // .requestMatchers(mvc.pattern("/management/prometheus")).permitAll()
.requestMatchers(mvc.pattern("/management/**")).hasAuthority(AuthoritiesConstants.ADMIN) .requestMatchers(mvc.pattern("/management/**")).hasAuthority(AuthoritiesConstants.ADMIN)
) )
.oauth2Login(oauth2 -> oauth2.loginPage("/").userInfoEndpoint(userInfo -> userInfo.oidcUserService(this.oidcUserService()))) .rememberMe(
rememberMe -> rememberMe.rememberMeServices(rememberMeServices())
// .key("remember-me-cookie-key32342") // Klucz do szyfrowania tokenu
// .tokenValiditySeconds(60 * 60 * 24 * 7) // 7 dni
)
.oauth2Login(oauth2 ->
oauth2
.defaultSuccessUrl("/", true)
/*.loginPage("/")*/.userInfoEndpoint(userInfo -> userInfo.oidcUserService(this.oidcUserService()))
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(authenticationConverter()))) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(authenticationConverter())))
.oauth2Client(withDefaults()); .oauth2Client(withDefaults());
return http.build(); return http.build();
} }
@Bean
public RememberMeServices rememberMeServices() {
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("remember-me-key", userDetailsService());
rememberMeServices.setTokenValiditySeconds(60 * 60 * 24 * 7);
rememberMeServices.setAlwaysRemember(true);
// Ustawienie czasu ważności tokenu na 7 dni
return rememberMeServices;
}
@Autowired
UserRepository userRepository;
@Bean
public UserDetailsService userDetailsService() {
// Jeśli korzystasz z in-memory użytkowników lub innego źródła, skonfiguruj tutaj.
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String login = extractUsername(username);
// String[] authorities = extractGrantedAuthorities(username);
Map<String, Object> attributes = extractUserAttributes(username);
Optional<com.sasiedzi.event.domain.User> one = userRepository.findOneByLogin(login);
if (one.isPresent()) {
// return new User(one.get().getLogin(), "somepassword", one.get().getAuthorities().stream().map(authority-> new SimpleGrantedAuthority(authority.getName())).collect(Collectors.toSet()));
// return new User(login, "somepassword", Arrays.stream(authorities).map(authority-> new SimpleGrantedAuthority(authority)).collect(Collectors.toSet()));
return new User(username, "somepassword", extractRoles(username));
} else {
throw new UsernameNotFoundException("User not found");
}
}
private static String extractUsername(String input) {
Pattern pattern = Pattern.compile("Name:\\s+\\[([^]]+)]");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
private static String[] extractGrantedAuthorities(String input) {
Pattern pattern = Pattern.compile("Granted Authorities:\\s+\\[([^]]+)]");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
return matcher.group(1).split(", ");
}
return new String[0];
}
private static Set<GrantedAuthority> extractRoles(String input) {
Set<GrantedAuthority> roles = new HashSet<>();
Pattern pattern = Pattern.compile("https://www\\.jhipster\\.tech/roles=\\[([^]]+)]");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
String rolesString = matcher.group(1);
String[] rolesArray = rolesString.split(",\\s*");
for (String role : rolesArray) {
roles.add(new SimpleGrantedAuthority(role));
}
}
return roles;
}
private static Map<String, Object> extractUserAttributes(String input) {
Map<String, Object> attributes = new HashMap<>();
Pattern pattern = Pattern.compile("User Attributes:\\s+\\[\\{([^}]+)\\}\\]");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
String attributesString = matcher.group(1);
String[] attributePairs = attributesString.split(",\\s*");
for (String pair : attributePairs) {
String[] keyValue = pair.split("=");
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
// Tutaj wartość jest zawsze String, ale można by to rozszerzyć by obsługiwało różne typy
attributes.put(key, value);
}
}
}
return attributes;
}
};
}
@Bean
@RequestScope
public CurrentUserHolder currentUser(UserService userService, EventService eventService) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof AbstractAuthenticationToken) {
AbstractAuthenticationToken authToken = (AbstractAuthenticationToken) authentication;
AdminUserDTO userFromAuthentication = userService.getUserFromAuthentication(authToken);
return new CurrentUserHolder(
userFromAuthentication,
eventService.getOrCreateUserAccountForLogin(userFromAuthentication.getLogin()),
authentication
);
}
return new CurrentUserHolder();
}
@Bean @Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
return new MvcRequestMatcher.Builder(introspector); return new MvcRequestMatcher.Builder(introspector);
@@ -0,0 +1,41 @@
package com.sasiedzi.event.domain;
import com.sasiedzi.event.service.dto.AdminUserDTO;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
@Component
@RequestScope
public class CurrentUserHolder {
AdminUserDTO adminUser;
UserAccount userAccount;
Authentication authentication;
public CurrentUserHolder() {}
public AdminUserDTO getAdminUser() {
return adminUser;
}
public UserAccount getUserAccount() {
return userAccount;
}
public Authentication getAuthentication() {
return authentication;
}
public String getLogin() {
if (adminUser == null) return null;
return adminUser.getLogin();
}
public CurrentUserHolder(AdminUserDTO adminUser, UserAccount userAccount, Authentication authentication) {
this.adminUser = adminUser;
this.userAccount = userAccount;
this.authentication = authentication;
}
}
@@ -3,6 +3,7 @@ package com.sasiedzi.event.service;
import com.sasiedzi.event.domain.*; import com.sasiedzi.event.domain.*;
import com.sasiedzi.event.domain.enumeration.TransactionType; import com.sasiedzi.event.domain.enumeration.TransactionType;
import com.sasiedzi.event.repository.*; import com.sasiedzi.event.repository.*;
import com.sasiedzi.event.service.dto.AdminUserDTO;
import com.sasiedzi.event.web.rest.AccountResource; import com.sasiedzi.event.web.rest.AccountResource;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -10,12 +11,16 @@ import java.math.RoundingMode;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.AuthenticatedPrincipal; import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -235,21 +240,36 @@ public class EventService {
return eventRepository.findById(event.getId()); return eventRepository.findById(event.getId());
} }
public String getCurrentAuthenticatedUserAsDTO() { @Autowired
if (SecurityContextHolder.getContext().getAuthentication() == null) { AdminUserDTO currentUser;
// public String getCurrentAuthenticatedUserAsDTO() {
// if (SecurityContextHolder.getContext().getAuthentication() == null) {
// return null;
// }
// if (SecurityContextHolder.getContext() == null) {
// return null;
// }
// Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
// if (principal instanceof AuthenticatedPrincipal) {
// return extractUsername((AuthenticatedPrincipal) principal).getName();
// // return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal);
// } else if (principal instanceof UserDetails) {
// return asdf((UserDetails) principal).getUsername();
// // return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal);
// } else {
// throw new RuntimeException("User could not be found");
// }
// }
private static String extractUsername(String input) {
Pattern pattern = Pattern.compile("Name:\\s+\\[([^]]+)]");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
return matcher.group(1);
}
return null; return null;
} }
if (SecurityContextHolder.getContext() == null) {
return null;
}
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof AuthenticatedPrincipal) {
return ((AuthenticatedPrincipal) principal).getName();
// return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal);
} else {
throw new RuntimeException("User could not be found");
}
}
public UserAccount createNewAccountForLogin(String login) { public UserAccount createNewAccountForLogin(String login) {
UserAccount entity = new UserAccount(); UserAccount entity = new UserAccount();
@@ -264,9 +284,7 @@ public class EventService {
} }
} }
public UserAccount getOrCreateForCurrentUser() { public UserAccount getOrCreateUserAccountForLogin(String username) {
// if (true) return new UserAccount();
String username = getCurrentAuthenticatedUserAsDTO();
if (username != null) { if (username != null) {
// List<UserAccount> userAccounts = userAccountRepository.findByUserLogin(currentAuthenticatedUserAsDTO.getLogin()); // List<UserAccount> userAccounts = userAccountRepository.findByUserLogin(currentAuthenticatedUserAsDTO.getLogin());
List<UserAccount> userAccounts = userAccountRepository List<UserAccount> userAccounts = userAccountRepository
@@ -8,14 +8,20 @@ import com.sasiedzi.event.repository.UserRepository;
import com.sasiedzi.event.security.SecurityUtils; import com.sasiedzi.event.security.SecurityUtils;
import com.sasiedzi.event.service.dto.AdminUserDTO; import com.sasiedzi.event.service.dto.AdminUserDTO;
import com.sasiedzi.event.service.dto.UserDTO; import com.sasiedzi.event.service.dto.UserDTO;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant; import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
@@ -129,6 +135,48 @@ public class UserService {
return user; return user;
} }
private static Map<String, Object> extractUserAttributes(String input) {
Map<String, Object> attributes = new HashMap<>();
Pattern pattern = Pattern.compile("User Attributes:\\s+\\[\\{([^}]+)\\}\\]");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
String attributesString = matcher.group(1);
String[] attributePairs = attributesString.split(",\\s*");
for (String pair : attributePairs) {
String[] keyValue = pair.split("=");
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
// Konwersja wartości "true" i "false" na typ Boolean
if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) {
attributes.put(key, Boolean.parseBoolean(value));
} else {
// Próba sparsowania jako Instant
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
Instant instant = Instant.from(formatter.parse(value));
attributes.put(key, instant);
} catch (Exception e) {
// Jeśli nie jest datą, zostawiamy jako String
attributes.put(key, value);
}
}
}
}
}
return attributes;
}
// private static String extractUsername(String input) {
// Pattern pattern = Pattern.compile("Name:\\s+\\[([^]]+)]");
// Matcher matcher = pattern.matcher(input);
// if (matcher.find()) {
// return matcher.group(1);
// }
// return null;
// }
/** /**
* Returns the user from an OAuth 2.0 login or resource server with JWT. * Returns the user from an OAuth 2.0 login or resource server with JWT.
* Synchronizes the user in the local repository. * Synchronizes the user in the local repository.
@@ -143,6 +191,10 @@ public class UserService {
attributes = ((OAuth2AuthenticationToken) authToken).getPrincipal().getAttributes(); attributes = ((OAuth2AuthenticationToken) authToken).getPrincipal().getAttributes();
} else if (authToken instanceof JwtAuthenticationToken) { } else if (authToken instanceof JwtAuthenticationToken) {
attributes = ((JwtAuthenticationToken) authToken).getTokenAttributes(); attributes = ((JwtAuthenticationToken) authToken).getTokenAttributes();
} else if (authToken instanceof RememberMeAuthenticationToken) {
attributes = extractUserAttributes(authToken.getName());
// attributes = new HashMap<>();
// attributes = ((RememberMeAuthenticationToken) authToken).getTokenAttributes();
} else { } else {
throw new IllegalArgumentException("AuthenticationToken is not OAuth2 or JWT!"); throw new IllegalArgumentException("AuthenticationToken is not OAuth2 or JWT!");
} }
@@ -8,10 +8,14 @@ import java.io.Serializable;
import java.time.Instant; import java.time.Instant;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
/** /**
* A DTO representing a user, with his authorities. * A DTO representing a user, with his authorities.
*/ */
@Component
@RequestScope
public class AdminUserDTO implements Serializable { public class AdminUserDTO implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -1,10 +1,12 @@
package com.sasiedzi.event.web.rest; package com.sasiedzi.event.web.rest;
import com.sasiedzi.event.domain.CurrentUserHolder;
import com.sasiedzi.event.service.UserService; import com.sasiedzi.event.service.UserService;
import com.sasiedzi.event.service.dto.AdminUserDTO; import com.sasiedzi.event.service.dto.AdminUserDTO;
import java.security.Principal; import java.security.Principal;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@@ -44,13 +46,16 @@ public class AccountResource {
*/ */
@GetMapping("/account") @GetMapping("/account")
public AdminUserDTO getAccount(Principal principal) { public AdminUserDTO getAccount(Principal principal) {
if (principal instanceof AbstractAuthenticationToken) { if (currentUser != null) {
return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal); return currentUser.getAdminUser();
} else { } else {
throw new AccountResourceException("User could not be found"); throw new AccountResourceException("User could not be found");
} }
} }
@Autowired
CurrentUserHolder currentUser;
/** /**
* {@code GET /authenticate} : check if the user is authenticated, and return its login. * {@code GET /authenticate} : check if the user is authenticated, and return its login.
* *
@@ -1,13 +1,21 @@
package com.sasiedzi.event.web.rest; package com.sasiedzi.event.web.rest;
import com.sasiedzi.event.domain.CurrentUserHolder;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.core.oidc.OidcIdToken; import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -23,24 +31,47 @@ public class LogoutResource {
this.registration = registrations.findByRegistrationId("oidc"); this.registration = registrations.findByRegistrationId("oidc");
} }
@Autowired
CurrentUserHolder currentUser;
/** /**
* {@code POST /api/logout} : logout the current user. * {@code POST /api/logout} : logout the current user.
* *
* @param request the {@link HttpServletRequest}. * @param request the {@link HttpServletRequest}.
* @param idToken the ID token. * @param principal principal with the ID token.
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and a body with a global logout URL. * @return the {@link ResponseEntity} with status {@code 200 (OK)} and a body with a global logout URL.
*/ */
@PostMapping("/api/logout") @PostMapping("/api/logout")
public ResponseEntity<?> logout(HttpServletRequest request, @AuthenticationPrincipal(expression = "idToken") OidcIdToken idToken) { public ResponseEntity<?> logout(HttpServletRequest request, HttpServletResponse response) {
OidcIdToken idToken = null;
Authentication authentication = currentUser.getAuthentication();
StringBuilder logoutUrl = new StringBuilder(); StringBuilder logoutUrl = new StringBuilder();
String originUrl = request.getHeader(HttpHeaders.ORIGIN);
if (authentication != null && authentication.getPrincipal() instanceof DefaultOAuth2User) {
idToken = ((DefaultOidcUser) authentication.getPrincipal()).getIdToken();
logoutUrl.append(this.registration.getProviderDetails().getConfigurationMetadata().get("end_session_endpoint").toString()); logoutUrl.append(this.registration.getProviderDetails().getConfigurationMetadata().get("end_session_endpoint").toString());
String originUrl = request.getHeader(HttpHeaders.ORIGIN); if (idToken != null) {
logoutUrl.append("?id_token_hint=").append(idToken.getTokenValue()).append("&post_logout_redirect_uri=").append(originUrl); logoutUrl.append("?id_token_hint=").append(idToken.getTokenValue()).append("&post_logout_redirect_uri=").append(originUrl);
}
} else {
logoutUrl.append(originUrl);
}
new SecurityContextLogoutHandler().logout(request, response, null);
// Ręczne usuwanie ciasteczka 'remember-me'
Cookie cookie = new Cookie("remember-me", null);
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
HttpSession existingSession = request.getSession();
if (existingSession != null) {
existingSession.invalidate();
}
request.getSession().invalidate();
return ResponseEntity.ok().body(Map.of("logoutUrl", logoutUrl.toString())); return ResponseEntity.ok().body(Map.of("logoutUrl", logoutUrl.toString()));
} }
} }
@@ -1,5 +1,6 @@
package com.sasiedzi.event.web.rest; package com.sasiedzi.event.web.rest;
import com.sasiedzi.event.domain.CurrentUserHolder;
import com.sasiedzi.event.domain.User; import com.sasiedzi.event.domain.User;
import com.sasiedzi.event.domain.UserAccount; import com.sasiedzi.event.domain.UserAccount;
import com.sasiedzi.event.repository.UserAccountRepository; import com.sasiedzi.event.repository.UserAccountRepository;
@@ -174,10 +175,12 @@ public class UserAccountResource {
@GetMapping("/currentUser") @GetMapping("/currentUser")
public UserAccount getCurrentUserAccount() { public UserAccount getCurrentUserAccount() {
UserAccount userAccount = eventService.getOrCreateForCurrentUser(); return currentUser.getUserAccount();
return userAccount;
} }
@Autowired
CurrentUserHolder currentUser;
/** /**
* {@code DELETE /user-accounts/:id} : delete the "id" userAccount. * {@code DELETE /user-accounts/:id} : delete the "id" userAccount.
* *