diff --git a/src/auth/src/user_provider.rs b/src/auth/src/user_provider.rs index 47f21da6d6..8b8c63581a 100644 --- a/src/auth/src/user_provider.rs +++ b/src/auth/src/user_provider.rs @@ -115,6 +115,12 @@ pub trait UserProvider: Send + Sync { } } + /// Selects authentication after the MySQL handshake supplies a username. + /// The user is resolved in the same scope as [`authenticate`](Self::authenticate). + async fn mysql_auth_method_for_user(&self, _username: &str) -> Result { + Ok(self.mysql_auth_method()) + } + async fn postgres_auth_info(&self, _id: Identity<'_>, _catalog: &str) -> Result { Ok(PgAuthInfo::Cleartext) } diff --git a/src/servers/src/mysql/handler.rs b/src/servers/src/mysql/handler.rs index 6bb7dd2330..3764591bea 100644 --- a/src/servers/src/mysql/handler.rs +++ b/src/servers/src/mysql/handler.rs @@ -374,6 +374,15 @@ impl AsyncMysqlShim for MysqlInstanceShi if user == BEARER_TOKEN_USER.as_bytes() { return MysqlAuthMethod::ClearPassword.plugin_name(); } + if let Some(provider) = &self.user_provider { + let username = String::from_utf8_lossy(user); + match provider.mysql_auth_method_for_user(&username).await { + Ok(method) => return method.plugin_name(), + // This hook cannot return an error. Keep the default challenge; + // authentication still validates the credentials separately. + Err(e) => warn!(e; "Failed to select MySQL authentication method"), + } + } self.auth_plugin() }