fix captchas not being validated properly
This commit is contained in:
parent
18d916391f
commit
25b96b3be9
@ -60,6 +60,7 @@ public class WebSecurityConfig {
|
|||||||
.requestMatchers(AntPathRequestMatcher.antMatcher("/error")).permitAll()
|
.requestMatchers(AntPathRequestMatcher.antMatcher("/error")).permitAll()
|
||||||
.requestMatchers(AntPathRequestMatcher.antMatcher("/v*/auth/register")).permitAll()
|
.requestMatchers(AntPathRequestMatcher.antMatcher("/v*/auth/register")).permitAll()
|
||||||
.requestMatchers(AntPathRequestMatcher.antMatcher("/v*/auth/login")).permitAll()
|
.requestMatchers(AntPathRequestMatcher.antMatcher("/v*/auth/login")).permitAll()
|
||||||
|
.requestMatchers(AntPathRequestMatcher.antMatcher("/v*/user/exists")).permitAll()
|
||||||
.anyRequest().authenticated())
|
.anyRequest().authenticated())
|
||||||
.exceptionHandling(exceptionHandling -> exceptionHandling
|
.exceptionHandling(exceptionHandling -> exceptionHandling
|
||||||
.authenticationEntryPoint((request, response, authException) -> { // Handle invalid access tokens
|
.authenticationEntryPoint((request, response, authException) -> { // Handle invalid access tokens
|
||||||
|
@ -8,6 +8,8 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This controller is responsible for
|
* This controller is responsible for
|
||||||
* handling user authentication requests.
|
* handling user authentication requests.
|
||||||
@ -37,4 +39,9 @@ public final class UserController {
|
|||||||
public ResponseEntity<UserDTO> getUser() {
|
public ResponseEntity<UserDTO> getUser() {
|
||||||
return ResponseEntity.ok(userService.getUser());
|
return ResponseEntity.ok(userService.getUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/exists") @ResponseBody @NonNull
|
||||||
|
public ResponseEntity<Map<String, Object>> doesUserExist(@RequestParam @NonNull String email) {
|
||||||
|
return ResponseEntity.ok(Map.of("exists", userService.doesUserExist(email)));
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,11 +17,6 @@ public final class UserLoginInput {
|
|||||||
*/
|
*/
|
||||||
private final String email;
|
private final String email;
|
||||||
|
|
||||||
/**
|
|
||||||
* The username of the user to login with.
|
|
||||||
*/
|
|
||||||
private final String username;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The password of the user to login with.
|
* The password of the user to login with.
|
||||||
*/
|
*/
|
||||||
@ -38,7 +33,7 @@ public final class UserLoginInput {
|
|||||||
* @return whether this input is valid
|
* @return whether this input is valid
|
||||||
*/
|
*/
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return (email != null && (!email.isBlank()) || username != null && (!username.isBlank()))
|
return email != null && (!email.isBlank())
|
||||||
&& password != null && (!password.isBlank())
|
&& password != null && (!password.isBlank())
|
||||||
&& captchaResponse != null && (!captchaResponse.isBlank());
|
&& captchaResponse != null && (!captchaResponse.isBlank());
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,8 +99,7 @@ public final class AuthService {
|
|||||||
validateLoginInput(input); // Ensure the input is valid
|
validateLoginInput(input); // Ensure the input is valid
|
||||||
|
|
||||||
// Lookup the user by the email or username and ensure the user exists
|
// Lookup the user by the email or username and ensure the user exists
|
||||||
User user = input.getEmail() == null ? userRepository.findByUsernameIgnoreCase(Objects.requireNonNull(input.getUsername()))
|
User user = userRepository.findByEmailIgnoreCase(input.getEmail());
|
||||||
: userRepository.findByEmailIgnoreCase(input.getEmail());
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new BadRequestException(Error.USER_NOT_FOUND);
|
throw new BadRequestException(Error.USER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
@ -197,10 +195,8 @@ public final class AuthService {
|
|||||||
throw new BadRequestException(passwordError);
|
throw new BadRequestException(passwordError);
|
||||||
}
|
}
|
||||||
// Finally validate the captcha
|
// Finally validate the captcha
|
||||||
if (EnvironmentUtils.isProduction()) {
|
|
||||||
captchaService.validateCaptcha(input.getCaptchaResponse());
|
captchaService.validateCaptcha(input.getCaptchaResponse());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the given login input.
|
* Validate the given login input.
|
||||||
@ -217,15 +213,9 @@ public final class AuthService {
|
|||||||
if (input.getEmail() != null && (!StringUtils.isValidEmail(input.getEmail()))) {
|
if (input.getEmail() != null && (!StringUtils.isValidEmail(input.getEmail()))) {
|
||||||
throw new BadRequestException(Error.EMAIL_INVALID);
|
throw new BadRequestException(Error.EMAIL_INVALID);
|
||||||
}
|
}
|
||||||
// Ensure the username is valid
|
|
||||||
if (input.getUsername() != null && (!StringUtils.isValidUsername(input.getUsername()))) {
|
|
||||||
throw new BadRequestException(Error.USERNAME_INVALID);
|
|
||||||
}
|
|
||||||
// Finally validate the captcha
|
// Finally validate the captcha
|
||||||
if (EnvironmentUtils.isProduction()) {
|
|
||||||
captchaService.validateCaptcha(input.getCaptchaResponse());
|
captchaService.validateCaptcha(input.getCaptchaResponse());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private enum Error implements IGenericResponse {
|
private enum Error implements IGenericResponse {
|
||||||
MALFORMED_INPUT,
|
MALFORMED_INPUT,
|
||||||
|
@ -8,6 +8,7 @@ import kong.unirest.core.JsonNode;
|
|||||||
import kong.unirest.core.Unirest;
|
import kong.unirest.core.Unirest;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,7 +29,10 @@ public final class CaptchaService {
|
|||||||
JsonObject body = new JsonObject();
|
JsonObject body = new JsonObject();
|
||||||
body.addProperty("secret", secretKey);
|
body.addProperty("secret", secretKey);
|
||||||
body.addProperty("response", captchaResponse);
|
body.addProperty("response", captchaResponse);
|
||||||
HttpResponse<JsonNode> response = Unirest.post("https://challenges.cloudflare.com/turnstile/v0/siteverify").body(body).asJson();
|
HttpResponse<JsonNode> response = Unirest.post("https://challenges.cloudflare.com/turnstile/v0/siteverify")
|
||||||
|
.header(HttpHeaders.CONTENT_TYPE, "application/json")
|
||||||
|
.body(body)
|
||||||
|
.asJson();
|
||||||
if (!response.getBody().getObject().getBoolean("success")) {
|
if (!response.getBody().getObject().getBoolean("success")) {
|
||||||
throw new BadRequestException(Error.CAPTCHA_INVALID);
|
throw new BadRequestException(Error.CAPTCHA_INVALID);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package cc.pulseapp.api.service;
|
package cc.pulseapp.api.service;
|
||||||
|
|
||||||
|
import cc.pulseapp.api.common.StringUtils;
|
||||||
import cc.pulseapp.api.model.user.User;
|
import cc.pulseapp.api.model.user.User;
|
||||||
import cc.pulseapp.api.model.user.UserDTO;
|
import cc.pulseapp.api.model.user.UserDTO;
|
||||||
|
import cc.pulseapp.api.repository.UserRepository;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -13,6 +15,9 @@ import java.util.Date;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public final class UserService {
|
public final class UserService {
|
||||||
|
/**
|
||||||
|
* The auth service to use.
|
||||||
|
*/
|
||||||
@NonNull private final AuthService authService;
|
@NonNull private final AuthService authService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,15 +25,36 @@ public final class UserService {
|
|||||||
*/
|
*/
|
||||||
@NonNull private final SnowflakeService snowflakeService;
|
@NonNull private final SnowflakeService snowflakeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user repository to use.
|
||||||
|
*/
|
||||||
|
@NonNull private final UserRepository userRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public UserService(@NonNull AuthService authService, @NonNull SnowflakeService snowflakeService) {
|
public UserService(@NonNull AuthService authService, @NonNull SnowflakeService snowflakeService, @NonNull UserRepository userRepository) {
|
||||||
this.authService = authService;
|
this.authService = authService;
|
||||||
this.snowflakeService = snowflakeService;
|
this.snowflakeService = snowflakeService;
|
||||||
|
this.userRepository = userRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently authenticated user.
|
||||||
|
*
|
||||||
|
* @return the authenticated user
|
||||||
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public UserDTO getUser() {
|
public UserDTO getUser() {
|
||||||
User user = authService.getAuthenticatedUser();
|
User user = authService.getAuthenticatedUser();
|
||||||
return UserDTO.asDTO(user, new Date(snowflakeService.extractCreationTime(user.getSnowflake())));
|
return UserDTO.asDTO(user, new Date(snowflakeService.extractCreationTime(user.getSnowflake())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user with the given email exists.
|
||||||
|
*
|
||||||
|
* @param email the email to check
|
||||||
|
* @return whether the user exists
|
||||||
|
*/
|
||||||
|
public boolean doesUserExist(@NonNull String email) {
|
||||||
|
return StringUtils.isValidEmail(email) && userRepository.findByEmailIgnoreCase(email) != null;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user