Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Redis 6 auth pass [user] #1508

Merged
merged 15 commits into from Mar 17, 2021
3 changes: 2 additions & 1 deletion index.js
Expand Up @@ -109,6 +109,7 @@ function RedisClient (options, stream) {
this.closing = false;
this.server_info = {};
this.auth_pass = options.auth_pass || options.password;
this.auth_user = options.auth_user || options.user;
this.selected_db = options.db; // Save the selected db here, used when reconnecting
this.fire_strings = true; // Determine if strings or buffers should be written to the stream
this.pipeline = false;
Expand Down Expand Up @@ -240,7 +241,7 @@ RedisClient.prototype.create_stream = function () {
if (this.auth_pass !== undefined) {
this.ready = true;
// Fail silently as we might not be able to connect
this.auth(this.auth_pass, function (err) {
this.auth(this.auth_user, this.auth_pass, function (err) {
if (err && err.code !== 'UNCERTAIN_STATE') {
self.emit('error', err);
}
Expand Down
6 changes: 5 additions & 1 deletion lib/createClient.js
Expand Up @@ -29,7 +29,11 @@ module.exports = function createClient (port_arg, host_arg, options) {
// [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
if (parsed.slashes) { // We require slashes
if (parsed.auth) {
options.password = parsed.auth.slice(parsed.auth.indexOf(':') + 1);
var columnIndex = parsed.auth.indexOf(':');
options.password = parsed.auth.slice(columnIndex + 1);
if (columnIndex > 0) {
options.user = parsed.auth.slice(0, columnIndex);
}
}
if (parsed.protocol) {
if (parsed.protocol === 'rediss:') {
Expand Down
38 changes: 32 additions & 6 deletions lib/individualCommands.js
Expand Up @@ -180,7 +180,12 @@ Multi.prototype.info = Multi.prototype.INFO = function info (section, callback)
return this;
};

function auth_callback (self, pass, callback) {
function auth_callback (self, user, pass, callback) {
// Backward compatibility support for auth with password only
leibale marked this conversation as resolved.
Show resolved Hide resolved
if (user instanceof Function) {
callback = user;
user = null;
}
return function (err, res) {
if (err) {
if (no_password_is_set.test(err.message)) {
Expand All @@ -191,7 +196,7 @@ function auth_callback (self, pass, callback) {
// If redis is still loading the db, it will not authenticate and everything else will fail
debug('Redis still loading, trying to authenticate later');
setTimeout(function () {
self.auth(pass, callback);
self.auth(user, pass, callback);
}, 100);
return;
}
Expand All @@ -200,25 +205,46 @@ function auth_callback (self, pass, callback) {
};
}

RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, callback) {
RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (user, pass, callback) {
debug('Sending auth to ' + this.address + ' id ' + this.connection_id);

// Backward compatibility support for auth with password only
if (user instanceof Function) {
callback = user;
user = null;
}
// Stash auth for connect and reconnect.
this.auth_pass = pass;
this.auth_user = user;
var ready = this.ready;
this.ready = ready || this.offline_queue.length === 0;
var tmp = this.internal_send_command(new Command('auth', [pass], auth_callback(this, pass, callback)));
var tmp;
if (user) {
tmp = this.internal_send_command(new Command('auth', [user, pass], auth_callback(this, user, pass, callback)));
} else {
tmp = this.internal_send_command(new Command('auth', [pass], auth_callback(this, pass, callback)));
}
this.ready = ready;
return tmp;
};

// Only works with batch, not in a transaction
Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, callback) {
Multi.prototype.auth = Multi.prototype.AUTH = function auth (user, pass, callback) {
debug('Sending auth to ' + this.address + ' id ' + this.connection_id);

// Backward compatibility support for auth with password only
if (user instanceof Function) {
callback = user;
user = null;
}
// Stash auth for connect and reconnect.
this.auth_pass = pass;
this.queue.push(new Command('auth', [pass], auth_callback(this._client, callback)));
this.auth_user = user;
if (user) {
this.queue.push(new Command('auth', [user, pass], auth_callback(this._client, callback)));
} else {
this.queue.push(new Command('auth', [pass], auth_callback(this._client, callback)));
}
return this;
};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -38,7 +38,7 @@
},
"dependencies": {
"denque": "^1.4.1",
"redis-commands": "^1.5.0",
"redis-commands": "^1.6.0",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0"
},
Expand Down