currently only allowed connect method initially is mysql_native_password. Some servers can potentially prefer to start with custom auth immediately, instead of rejecting mysql_native_password and doing AUTH_SWITH_HANDLER sequence afterwards. Also some servers can be configured to allow 'plugin based auth' but not 'auth switch request' - those are two different capabilities flags
1) respect handshake packet plugin name
2) deprecate authSwitchHandler and rename it to be authPluginHandler
3) provide default handler for mysql_native_password
also need to think of something to make it easy to chain handlers:
const mysqlIamAuth = require('mysql-iam-auth'); // imaginary, does not exist
const mysqMyCustomAuth = require('@internal/customauth');
const pool = mysql2.createPool({
authPluginHandler: combineAuthHandlers(mysqlIamAuth, mysqMyCustomAuth)
})
thinking about merging plugin auth and auth switch. Maybe api like this:
const mysql2 = require('mysql');
const pool = mysql2.createPool({
authPlugins: {
sha256_password: (data, cb) => { /* ... probably going to be included by default. You should be able to disable it by specifying authPlugins: { sha256_password: null } */ },
mysql_clear_password: mysql2.authPlugins.mysql_clear_password(validateFunction), // not enabled by default but included with driver and documented
},
// better name for this option? "defaultPlugin" ? "initialConnectionPlugin" ?
// this is plugin name sent with initial connection (also handler executed at connection time and result of the handler included with initial connection"
// error if name does not match authPlugins keys ( or built-in plugins ). Default to "mysql_native_password" if not specified
connectAuthPluginName: 'mysql_native_password' // not used if server does not support PLUGIN_AUTH
// should it error if specified and no server support for PLUGIN_AUTH ?
// some way to handle dynamic plugin names? currently possible with authSwitchHandler but I want to deprecate it
}
defaultAuthPlugin sounds like a good name to me. An auth plugin should likely be able to write it's own kinds of packets though or at least find some way for the plugin/function to return the next handler for the command. Considering how the caching_sha2 one appears to want a response to the fullauthentication request and there is also the fast auth path (https://dev.mysql.com/doc/dev/mysql-server/8.0.4/page_caching_sha2_authentication_exchanges.html), you'd want the plugin to handle all success responses until it says it is done (return null).
it's own kinds of packets though
I think it's ok to assume plugin is only able to send data or null, afaik it's never allowed to send any other packet than AuthMoreData or OK, but there can be possible multiple exchanges and just having function as plugin is not enough, we need instanse of object that updates it state as it progresses from AuthMoreData to final OK
I think function that returns the next handler is fine. You as the middle man don't care for state, only what comes next. If I write a plugin then I'll worry about state on my side and know only to return to you what should be called next.
Object is fine too but then you have to figure out how to structure the methods it should call right? Not too big a fan, but done right it will work.
Is this stable? Is there a better example? My use case is AWS RDS IAM tokens.
I believe new plugin auth api is stable. Currently connection is always started with mysql_native_password and later uses plugin via AuthSwitch packets exchange. This issue tracks possible change to allow to connect with custom plugin in the initial auth packet, saving couple of network roundtrips time
Good example in the answer here: https://stackoverflow.com/a/60013378/705115
( I'll copy it here as well with some minor changes )
const iamTokenPlugin =({connection, command}) => (authPluginDataFromServer) => {
return signer.getAuthToken({
region: '...',
hostname: '...',
port: '...',
username: '...'
})
}
mysql.createPool({
...,
ssl: 'Amazon RDS',
authPlugins: {
mysql_clear_password: iamTokenPlugin
}
});
The reason plugin has ({connection, command}) => Buffer => return Promise<Buffer> signature is to allow plugins to have internal state and update it as a result to AuthSwitchMoreData commands.
see how plugin is "instantinated" here https://github.com/sidorares/node-mysql2/blob/ebc2cb438d380d81d57ae6e2d227bfafc684eb2a/lib/commands/auth_switch.js#L50 and later called (potentially many times) with data here https://github.com/sidorares/node-mysql2/blob/ebc2cb438d380d81d57ae6e2d227bfafc684eb2a/lib/commands/auth_switch.js#L79-L82
See mysql AuthSwitch docs here - https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchRequest
Amazon has been planning for quite some time to change their certificates for TLS to RDS, at least for mySQL.
If your RDS server has been so upgraded (which Amazon will do in June 2020), when attempting IAM token login, you will get the error:
Error: 139965154551680:error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol:../deps/openssl/openssl/ssl/statem/statem_lib.c:1929:
The solution is:
Most helpful comment
thinking about merging plugin auth and auth switch. Maybe api like this: