Search code examples
javaspringrecaptchainvisible-recaptcharecaptcha-v3

How to bypass reCAPTCHA properly during development in Java


I use reCAPTCHA in my Java application and there is an approach similar to the following code:

LoginRequest:

public class LoginRequest {
    @NotEmpty
    private String token;
    
    @NotEmpty
    private String username;
    @NotEmpty
    private String password;
}

LoginController :




public class LoginController {

    private final Validator validator;

    @Value("${isDevelopment}")
    private boolean isDevelopment;

    public LoginController(Validator validator) {
        this.validator = validator;
    }

    public User login(LoginRequest request) {
        if(isDevelopment || validator.isValid(request.token)) {
            // ...
        }
        throw new InvalidTokenException();
    }
}

In this approach, I thought to bypass validation using the application development environment variable isDevelopment. However, I am not sure if there is a more elegant way. Because reCAPTCHA is used widely and most probably there would be a better standards for this purpose. How can I bypass reCAPTCHA during development?

Update: Here is my Validator class:

@Component
@RequiredArgsConstructor
public class CaptchaValidator {

    private final RecaptchaEnterpriseServiceClient client;

    @Value("${enabled}")
    private boolean isEnabled;

    public boolean isValid(String token) {
      // code omitted
    }
}


Solution

  • Technically, such design is not wrong - this kind of approach is being used widely. It is named Feature Flags and there are 3rd party software solutions that help developers to work with such variables (like e.g. LaunchDarkly).

    From Objective Programming perspective, you can also deal with this situation by creating some wrapper interface (let say UserValidator), injecting this to LoginController...

    public class LoginController {
        private final UserValidator validator;
    
        public LoginController(UserValidator validator) {
            this.validator = validator;
        }
    
        // ... 
    
        public User login(LoginRequest request) {
            if(validator.validate(request.token)) { 
                // ...
    

    ...making your CaptchaValidator implementing this but also creating some dev stub for the interface (let say AlwaysTrueValidator). Then during the development you can use your stub and just change configuration when going live. You can even take some advantage of using Spring profiles.

    @Configuration
    @Profile("production")
    public class ProductionConfiguration {
        @Bean
        public LoginController loginController() {
            return new LoginController(new CaptchaValidator());
        }
    }
    
    // ...
    
    @Configuration
    @Profile("development")
    public class DevelopmentConfiguration {
        @Bean
        public LoginController loginController() {
            return new LoginController(new AlwaysTrueValidator());
        }
    }