Skip to main content

Authentication Switch Request

During the connection phase the server may ask the client to switch to a different auth method. If the authPlugins connection config option is set, it must be an object where each key is the name of a potential authentication plugin requested by the server, and the corresponding value must be a function that optionally receives the connection config options and returns another function, which in turn, optionally receives the switch request data.

The plugin is loaded with a ({user,password,...}) signature, and each call has a (pluginData) signature. Each call should make the plugin return any additional authentication data (Buffer) that should be sent back to the server, either synchronously or asynchronously using a Promise, or should yield an error accordingly.

Example: (imaginary ssh-key-auth plugin) pseudo code

const conn = mysql.createConnection({
user: 'test_user',
password: 'test',
database: 'test_database',
authPlugins: {
'ssh-key-auth': function ({ password }) {
return function (pluginData) {
return getPrivate(key)
.then((key) => {
const response = encrypt(key, password, pluginData);
// continue handshake by sending response data
return response;
})
.catch((err) => {
// throw error to propagate error to connect/changeUser handlers
});
};
},
},
});

There is also a deprecated API where if a authSwitchHandler connection config option is set it must be a function that receives switch request data and responds via a callback. In this case, the first invocation always has a ({pluginName, pluginData}) signature, following calls - ({pluginData}). The client replies with an opaque blob matching the requested plugin via callback(null, data: Buffer).

const conn = mysql.createConnection({
user: 'test_user',
password: 'test',
database: 'test_database',
authSwitchHandler: function ({ pluginName, pluginData }, cb) {
if (pluginName === 'ssh-key-auth') {
getPrivateKey((key) => {
const response = encrypt(key, pluginData);
// continue handshake by sending response data
// respond with error to propagate error to connect/changeUser handlers
cb(null, response);
});
} else {
const err = new Error(
`Unknown AuthSwitchRequest plugin name ${pluginName}`
);
err.fatal = true;
cb(err);
}
},
});

The initial handshake is always performed using mysql_native_password plugin. This will be possible to override in future versions.

Note that if the mysql_native_password method is requested it will be handled internally according to Authentication::Native41 and no authPlugins function or the authSwitchHandler will be invoked.

These MAY be called multiple times if the plugin algorithm requires multiple roundtrips of data exchange between client and server.

Multi-factor authentication​

If the user requires multi-factor authentication in the server, the client will receive a AuthNextFactor request, which is similar in structure to the regular authentication switch request and contains the name and possible initial data for the additional authentication factor plugin (up to 3). Additional passwords can be provided using the connection config options - password2 and password3. Again, for each authentication factor, multiple roundtrips of data exchange can be required by the plugin algoritm.

const conn = mysql.createConnection({
user: 'test_user',
password: 'secret1',
password2: 'secret2',
password3: 'secret3',
database: 'test_database',
authPlugins: {
// password1 === password
'auth-plugin1': function ({ password1 }) {
return function (serverPluginData) {
return clientPluginData(password1, serverPluginData);
};
},
'auth-plugin2': function ({ password2 }) {
return function (serverPluginData) {
return clientPluginData(password2, serverPluginData);
};
},
'auth-plugin3': function ({ password3 }) {
return function (serverPluginData) {
return clientPluginData(password3, serverPluginData);
};
},
},
});