node-redis icon indicating copy to clipboard operation
node-redis copied to clipboard

Handle enabling/changing redis password without application restart

Open epoberezkin opened this issue 9 years ago • 4 comments

It seems to be not possible to enable or change redis password without application restart.

Even in case when I want to enable password and I supply password to the driver (it logs warning that the password is not required), when the password is enabled in redis, the driver returns error "not authenticated"; it doesn't try to authenticate using password that was passed in config.

For changing password there is no option. It would not be required if redis supported user accounts - you'd be able to simply create another account, switch application to use it and then remove the old account. Redis doesn't and apparently will not have accounts.

Of course the issue can be resolved by creating a wrapper around redis driver that would create a new client when authentication fails, but it seems as either too much of a change in applications or too much of an effort to make the wrapper that behaves exactly as the driver...

Maybe there is a simpler solution to this problem, like subscribing to some event, authenticating and replaying the last command when authentication fails? Please let me know if there is.

Otherwise it would be nice to have these two features inside driver:

  1. Handle enabling password:
    1. If the password is passed
    2. and it was not required by redis
    3. and at some later time some command was rejected as not authenticated
    4. driver will try authenticating again using the passed password
    5. if authentication is successful, it will resend command
    6. if authentication failed it would return error
  2. Support feature of password change using new_password option (or something like this). In this case when authentication fails, the driver will try authenticating using the new password and if it was successful the driver will use it afterwards in case of re-connects.

If you are OK with these features I could implement.

Please let me know. Thank you.

epoberezkin avatar Sep 04 '15 09:09 epoberezkin

This feature, or something similar, is required in order to support temporary refreshable credentials, such as AWS IAM authentication. In that authentication mechanism, the user creates a token that's valid for 15 minutes, which is used as the password in the AUTH command. As the token is only valid for 15 minutes, the client needs to be able to pick up a new token for then next authentication request. Furthermore, the client needs to periodically reauthenticate by sending a new AUTH request - however, I suspect this can be accomplished on the application layer.

Rather than passing some new_password property, I would suggest making the password option be:

type Provider<T> = () => T | Promise<T>
type password = string | Provider<string>

And have the driver look up the password on every auth command. This is similar to how it is implemented in the java redis client Lettuce, for example.

Nevon avatar Jan 16 '24 09:01 Nevon

@Nevon good idea! but maybe instead of doing it for password only we should do it for the whole options object? i.e.

// keep the current API
createClient({
  // ...
});

// add an option to send a "factory function" instead of an object
createClient(() => {
  return {
    // ...
  };
});

BTW, you can use this as a workaround for now:

const client = createClient({
  username: '...',
  password: '...'
});

function onPasswordChange(newPassword) {
  client.options.password = newPassword;  
}

leibale avatar Jan 16 '24 18:01 leibale

I would lean towards the credentials (i.e. user / password) like other client implementations.

devonhumes avatar Jun 14 '24 13:06 devonhumes