Implementation of login endpoint.
This commit is contained in:
@@ -33,5 +33,9 @@
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -12,6 +12,9 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import static jakarta.servlet.DispatcherType.FORWARD;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -26,7 +29,7 @@ public class SecurityConfiguration {
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.httpBasic(Customizer.withDefaults())
|
||||
.authorizeHttpRequests(requests -> requests
|
||||
.dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
|
||||
.dispatcherTypeMatchers(FORWARD).permitAll()
|
||||
.requestMatchers(
|
||||
HttpMethod.GET,
|
||||
"/api/health/check"
|
||||
@@ -39,10 +42,10 @@ public class SecurityConfiguration {
|
||||
)
|
||||
.exceptionHandling(configurer -> configurer
|
||||
.defaultAuthenticationEntryPointFor(
|
||||
(request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED),
|
||||
(request, response, authException) -> response.sendError(SC_UNAUTHORIZED),
|
||||
new AntPathRequestMatcher("/api/**")
|
||||
).defaultAccessDeniedHandlerFor(
|
||||
(request, response, accessDeniedException) -> response.sendError(HttpServletResponse.SC_FORBIDDEN),
|
||||
(request, response, accessDeniedException) -> response.sendError(SC_FORBIDDEN),
|
||||
new AntPathRequestMatcher("/api/**")
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.sportshub.application.user;
|
||||
package org.sportshub.application.security;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.sportshub.application.security.model.CustomUserDetails;
|
||||
import org.sportshub.application.user.UserUseCases;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.sportshub.application.security;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.sportshub.domain.user.model.User;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
|
||||
@Service
|
||||
public class JwtService {
|
||||
private final Algorithm algorithm;
|
||||
private final JWTVerifier jwtVerifier;
|
||||
|
||||
public JwtService(@Value("${application.security.secretKey}") String secretKey) {
|
||||
algorithm = Algorithm.HMAC512(secretKey);
|
||||
jwtVerifier = JWT.require(algorithm).build();
|
||||
}
|
||||
|
||||
public String createJwt(User user) {
|
||||
ZonedDateTime expirationDate = ZonedDateTime.now().plusMinutes(30);
|
||||
|
||||
return JWT.create()
|
||||
.withSubject(user.id().toString())
|
||||
.withExpiresAt(expirationDate.toInstant())
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
public boolean isValid(String token) {
|
||||
boolean result;
|
||||
try {
|
||||
jwtVerifier.verify(token);
|
||||
result = true;
|
||||
} catch (JWTVerificationException exception) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String extractUsername(String token) {
|
||||
return JWT.decode(token).getSubject();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.sportshub.application.user;
|
||||
package org.sportshub.application.security.model;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import java.util.Collection;
|
||||
@@ -4,15 +4,26 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.sportshub.application.security.JwtService;
|
||||
import org.sportshub.domain.exception.LoginFailureException;
|
||||
import org.sportshub.domain.user.model.User;
|
||||
import org.sportshub.domain.user.port.UserPort;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UserUseCases {
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final JwtService jwtService;
|
||||
private final UserPort userPort;
|
||||
|
||||
public UserUseCases(final UserPort userPort) {
|
||||
public UserUseCases(
|
||||
PasswordEncoder passwordEncoder,
|
||||
JwtService jwtService,
|
||||
UserPort userPort
|
||||
) {
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.jwtService = jwtService;
|
||||
this.userPort = userPort;
|
||||
}
|
||||
|
||||
@@ -23,4 +34,11 @@ public class UserUseCases {
|
||||
public List<User> findAll() {
|
||||
return userPort.findAll();
|
||||
}
|
||||
|
||||
public String authenticate(final UUID id, final String password) {
|
||||
return userPort.findById(id)
|
||||
.filter(user -> passwordEncoder.matches(password, user.password()))
|
||||
.map(jwtService::createJwt)
|
||||
.orElseThrow(LoginFailureException::new);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user