0

I have a register user form built in react and nextjs. I have applied regex patterns to the password field and set up custom validation using bootstrap. The confirm password pattern is simply set to the value coming from the password field which is updated onChange.

For the most part it works as intended. When the passwords match, it validates correctly. When they don't match, it gives appropriate feedback to the user. However, when there is any of the following symbols...

?*(){}[]/

...in the password entered, the confirm password will validate before I have even entered the entire password. For example:

PASSWORD: Password123*

CONFIRM: Password12

enter image description here

Below is the code for the form:

const Register = () => {
  const [validated, setValidated] = useState(false);
  const [values, setValues] = useState({
    username:"",
    email:"",
    password:"",
    confirmPassword:"",
  });

  const inputs = [
    {
      id: 1,
      name:"username",
      type:"text",
      errorMessage:"Username should be 3-16 characters long, and should not include special characters.",
      label:"Username",
      pattern:"^[A-Za-z0-9]{3,16}$",
      required: true,
    },
    {
      id: 2,
      name:"email",
      type:"email",
      errorMessage:"Please use a valid email address.",
      label:"Email",
      required: true,
    },
    {
      id: 3,
      name:"password",
      type:"password",
      errorMessage:"Password should be minimum 8 characters comprised of upper-case, lower-case, and numerals.",
      label:"Password",
      pattern:"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$",
      required: true,
    },
    {
      id: 4,
      name:"confirmPassword",
      type:"password",
      errorMessage:"Passwords do not match.",
      label:"Confirm Password",
      pattern: values.password,
      required: true,
    },
  ];

  const handleSubmit = (event) => {
    const form = event.currentTarget;
    if (form.checkValidity() === false) {
      event.preventDefault();
      event.stopPropagation();
    }
    setValidated(true);
  };

  const onChange = (e)=>{
    setValues({...values, [e.target.name]: e.target.value });
  };

    return (
        <Form noValidate validated={validated} onSubmit={handleSubmit} className="needs-validation">
          {inputs.map((input) => (
            <FormInput key={input.id} {...input} value={values[input.name]} onChange={onChange} />
          ))}
            
            <div className="d-grid"><hr/>
              <Button className="btn-custom" type="submit">
                Register
              </Button>
            </div>
          </Form>
    )
};

export default Register;

... and in case its relevant, here is the FormInput component:

export default function FormInput(props) {
    
    const { label, errorMessage, onChange, id, ...inputProps } = props;
    return (
        <Form.Group className="mb-3">
              <FloatingLabel label={label} className="mb-3">
                <Form.Control {...inputProps} onChange={onChange} className="form-input" />
                <Form.Control.Feedback type="invalid">
                {errorMessage}
                </Form.Control.Feedback>
              </FloatingLabel>
              
            </Form.Group>
    )
}

Is there something I am missing that would explain why this is happening? Or is there a fix I can apply? My guess is that these symbols are escaping the input in some way but I have no idea how to ensure they remain superficial only. I really do not want to simply bar the user from using certain symbols in their password. React and js beginner here.

Havanapple
  • 35
  • 5
  • 2
    It's not clear what's happening, but your "confirm" field should not be validated with a pattern. It should be compared to the *actual* value entered into the password field. – Pointy Apr 28 '23 at 13:48
  • so rather than simply pass the entered password variable into the pattern field for the confirm password, I should compare the two variables normally? I'll give it a try! – Havanapple Apr 28 '23 at 13:57
  • 1
    Right, because your passwords with regular expression meta-characters like "*" are being interpreted as part of a regex, not as a character as part of a simple string comparison. – Pointy Apr 28 '23 at 14:11
  • Found an alternative fix for this wherein I create a function to escape regex evaluations on the passed variable. After testing, it appears to have solved the problem, and just feels neater than adding additional validation functions. Found the solution here: https://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript ...and flagged my question as a dupe. – Havanapple Apr 29 '23 at 08:18

0 Answers0