Best Practices Application User Management

Hi everyone, i’m looking for the best practices about manage the application User. In particular would like to give the opportunity to the user to change itself username, name and password and to the admin to create and modify the users data.

I don’t know if there is something already done about a application user management (maybe there is a offical way??). I’m using hilla and this is how i thought to implement the change password:
i had create a new field (password) to help to send iinfromation from front end to backend methods to get new password and encrypt it

User.js

....
 private String password;

@JsonIgnore
private String hashedPassword;
....

 public void setPassword(String password) {
        if (!Objects.isNull(password) && !password.isEmpty() && !password.isBlank()) {
            var bc = new BCryptPasswordEncoder();
            var newHashedPwd = bc.encode(password);
            setHashedPassword(newHashedPwd);
        }
    }

to edit and create user I use standard Userservice.java

public User update(User entity) {
        return repository.save(entity);
    }

in the front end i use useForm hook to manage an edit form with a modal

const { model, submit, field, read, value, setValue, clear } = useForm(UserModel, {
    onSubmit: async (data) => {
      console.log("Saving user: ", data )
        await UserService.update(data).then(() => {clear();setVisibleEdit(false)});
      }
    });

this scenario works but i have a problem with hashedPassword, because hashedPassword is ingnored by @Jsonignore so in my User model there isn’t hashed password field so repository.save(entity); set hashed password field to null.

There is a way to prevent to set null unsetted field or i should create a custom method?

The same is for new User, thats give me an error becuuse id and version si unsetted

function createNewUser() {
    const newUser: User = UserModel.createEmptyValue();
    newUser.id=-1;
    newUser.version=-1
    read(newUser)
    setVisibleEdit(true);
  }

Thanks

Hi,
I would create an Endpoint with a method changeUserPassword(User entity, String newPassword).
There you can call setPassword and save the user.

Also you could double check if the user that is logged in and the user to change the password are the same (if you need that).
Further I would recommend to secure the Endpoint at least with @PermitAll.

1 Like

Yep is a good choice, but what about my principal problem: how to prevent that when i save user (that hasn’t hashed password because is @Jsonignore) whit JPA ?

interface User extends AbstractEntity_1 {
    username: string;
    name: string;
    password: string;
    roles: Array<Role_1>;
    profilePicture: Array<number>;
}

This method update hashedpassword to null because user hasn’t hashed password field

repository.save(user);

I should delete hashed password setter?

Principal security consideration:

  • A) Should you pass the whole user object from client → server → database

or

  • B) Should you read the current user from the database, modifier only the changed / allowed fields to be changed from the client and store the entity you have gotten from the database

(Option B is the preferred version)

1 Like

My goal would be to have the password information on server side but not on the client side.
I am not very familiar with JPA, but I think you may have to remove the @JsonIgnore on the hashedPassword.

To not get security issues I would clear the password field when passing the user into the client.
Or maybe you can create the two Beans ServerUser, that has the password, and a ClientUser, that does not have it.

Then you go for Christians options B.
When calling the Endpoint you load the ServerUser from repository by the user id and set the password.

1 Like

Actually i use User objet directly from server (because hilla gives my user object), about user i’m using default authentication system maybe i should use USerDTO to optimize and implement single field setter instead to use repository.save(user) like this:
https://medium.com/@vishamberlal/understanding-data-transfer-objects-dto-in-spring-boot-ac06b575a1d5