Skip to content

resendRegistrationToken always returns 400: it validates the full registration UserDto #361

Description

@devondragon

Summary

POST /user/resendRegistrationToken can never succeed. UserAPI.resendRegistrationToken binds the same UserDto used for full registration, and that DTO carries @NotBlank on firstName, lastName, password, and matchingPassword. A resend request only has an email address to send, so validation always fails and the endpoint returns HTTP 400 without sending mail.

Found in ds-spring-user-framework:5.3.0 while verifying the demo app's Docker stacks against a real mail catcher (devondragon/SpringUserFrameworkDemoApp#87). The flow had gone unexercised because no documented demo run path had working SMTP.

Reproduce

  1. Run the demo app with user.registration.sendVerificationEmail: true and a reachable SMTP server.
  2. Register an account, but do not click the verification link.
  3. Open /user/request-new-verification-email.html, enter that email, submit.

Expected: a new verification email.
Actual: the page shows "Unable to resend verification email." No mail is sent.

Server log

DEBUG ... RequestResponseBodyMethodProcessor : Read "application/json;charset=UTF-8" to
  [UserDto(firstName=null, lastName=null, email=resend-check@example.com, role=null)]
WARN  ... GlobalValidationExceptionHandler : Validation error occurred: Validation failed for
  argument [0] in public ResponseEntity<JSONResponse> UserAPI.resendRegistrationToken(UserDto,
  HttpServletRequest) with 4 errors:
  [Field error in object 'userDto' on field 'matchingPassword': rejected value [null];
    default message [Password confirmation is required]]
  [Field error in object 'userDto' on field 'password': rejected value [null];
    default message [Password is required]]
  [Field error in object 'userDto' on field 'lastName': rejected value [null];
    default message [Last name is required]]
  [Field error in object 'userDto' on field 'firstName': rejected value [null];
    default message [First name is required]]

The client is not at fault: the framework's own resend-verification.js posts { email }, which is the only field a resend needs.

Suggested fix

Bind a request type that carries just the email, e.g. a small ResendVerificationDto/EmailDto with @NotBlank @Email String email, rather than reusing the registration UserDto. POST /user/resetPassword has the same shape and is worth checking for the same problem.

Whatever the shape, the endpoint should keep its existing generic response so it does not leak whether an address is registered.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions