feat: authentication_openid_connect_client plugin support#1221
Conversation
Implements MySQL's OpenID Connect authentication protocol for JWT-based authentication. The protocol sends: [1 byte capability][length-encoded token length][token] This enables connecting to MySQL servers using OIDC tokens passed as the password parameter.
c9b7675 to
dbc9854
Compare
|
@methane could we consider this PR? The core work is few lines, most of the diff in this PR is testing related. |
There was a problem hiding this comment.
Pull request overview
Adds client-side support in PyMySQL for MySQL’s authentication_openid_connect_client OpenID Connect authentication plugin by generating the required JWT auth payload during the initial handshake and during auth-switch, and introduces unit tests that mock the network layer to validate auth packet formatting across several plugins.
Changes:
- Implement
authentication_openid_connect_clientauth response formatting inConnection._request_authentication()andConnection._process_auth(). - Add initial-handshake support for
mysql_clear_passwordin_request_authentication(). - Add a new mocked-socket test suite covering native, caching_sha2, cleartext, OIDC, auth-switch flows, and
_lenenc_int()encoding.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
pymysql/connections.py |
Adds OIDC and cleartext auth response generation paths in handshake and auth-switch handling. |
pymysql/tests/test_auth_protocol.py |
Adds mocked unit tests validating auth protocol message formatting and length-encoding behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| else: | ||
| authresp = b"\0" # empty password | ||
| elif self._auth_plugin_name == "mysql_clear_password": | ||
| plugin_name = b"mysql_clear_password" |
There was a problem hiding this comment.
@nytai Is "mysql_clear_password" necessary for oidc? I still don't fully understand this authentication flow. I also haven't been able to try it out or capture packets.
| elif self._auth_plugin_name == "authentication_openid_connect_client": | ||
| plugin_name = b"authentication_openid_connect_client" | ||
| # OpenID Connect: [1 byte capability][length-encoded token length][token] | ||
| capability = b"\x01" | ||
| token_len = len(self.password) | ||
| authresp = capability + _lenenc_int(token_len) + self.password |
| elif plugin_name == b"authentication_openid_connect_client": | ||
| # OpenID Connect authentication | ||
| # Protocol: [1 byte capability][length-encoded token length][token] | ||
| # Based on MySQL's authentication_openid_connect_client_plugin.cc | ||
| _ = auth_packet.read_all() # discard auth switch data | ||
| capability = b"\x01" # capability flag | ||
| token_len = len(self.password) | ||
| data = capability + _lenenc_int(token_len) + self.password |
There was a problem hiding this comment.
That issue is also present in other auth plugins, right? I'll ignore it for now and resolve it later in this PR.
| """Extract the last packet's data (without header).""" | ||
| if len(self.sent_data) < 4: | ||
| return b"" | ||
| # Skip the 4-byte header (3 bytes length + 1 byte seq) | ||
| return bytes(self.sent_data[4:]) | ||
|
|
||
|
|
|
@methane any chance we could merge+release this? OIDC/JWT based auth is increasingly becoming the norm, so the feature introduced by this PR would be very valuable for the entire MySQL ecosystem once released. |
Where and whom? |
Implements MySQL's OpenID Connect authentication protocol for JWT-based authentication. The protocol sends:
[1 byte capability][length-encoded token length][token]
This enables connecting to MySQL servers using OIDC tokens passed as the password parameter.