MySQL Public Key Retrieval Is Not Allowed

This Connector/J error appears when the active authentication path reaches a point where the client would need the server RSA public key but Connector/J is not allowed to retrieve it. This commonly involves caching_sha2_password or sha256_password on a non-TLS path; with caching_sha2_password, a cached fast-auth path can behave differently from a full authentication exchange. Do not start with the common internet recipe allowPublicKeyRetrieval=true&useSSL=false. First choose the intended secure transport. If TLS is intentionally disabled and full authentication needs RSA password exchange, use an approved key path.

MySQL · Connector/J · AuthenticationTLS · RSA · caching_sha2_passwordLast reviewed Sep 27, 2026
🎯 You’re likely in the right place if:
Java/JDBC reports Public Key Retrieval is not allowed.The MySQL account uses caching_sha2_password or sha256_password, commonly with MySQL 8+.The error appears during authentication before your query runs.A GUI/framework may be constructing the JDBC URL for you, so the effective Connector/J properties matter more than the settings screen.
30-second decision — choose the transport before changing authentication
Production / remote databasePrefer TLS. Use sslMode=VERIFY_IDENTITY when you need both CA validation and hostname identity verification.
TLS required, but server identity is not being verifiedREQUIRED requires an encrypted TLS connection, but it does not validate the server CA chain or hostname. Do not treat REQUIRED as certificate verification. Use VERIFY_CA or, preferably when hostname identity matters, VERIFY_IDENTITY.
Local/dev and TLS intentionally disabledRSA password exchange may need serverRSAPublicKeyFile or explicit allowPublicKeyRetrieval=true. Understand which key you trust before enabling retrieval.
You already use TLSDo not add public-key retrieval blindly. Confirm the effective sslMode; secure connections do not need RSA password exchange for this authentication path.
DBeaver / Spring / IDE / container differsInspect the actual JDBC URL and Connector/J version used by the failing process.
Difficulty: ModerateSecurity-sensitive
⚡ Quick Check — are you using TLS?

Find the effective Connector/J connection properties before adding anything. Connector/J 8.0.13+ uses sslMode; legacy useSSL, requireSSL, and verifyServerCertificate are deprecated mappings.

1
Identify the driver
Confirm this is MySQL Connector/J and record its version.
2
Inspect sslMode
DISABLED, PREFERRED, REQUIRED, VERIFY_CA, or VERIFY_IDENTITY?
3
Inspect authentication
Does the account use caching_sha2_password / sha256_password?

Verify: reproduce with the same JDBC driver and effective URL/properties as the failing application. Do not assume a successful MySQL CLI login proves the Java path is configured the same way.

ADSENSE · reserved slot after the first useful step

Why this error exists

MySQL's caching_sha2_password can complete through a cached fast-auth path, but when full authentication is required the password exchange must be protected. Over TLS, the secure connection supplies that protection. On a non-TLS path, full authentication can use the server RSA public key. Connector/J does not permit the extra server-public-key retrieval round trip by default: allowPublicKeyRetrieval defaults to false. This is why behavior can appear intermittent after server restart, cache state changes, account/password changes, or movement to another server even when the JDBC URL is unchanged.

That is why simply changing the password or database permissions often does nothing—the failure is about the authentication transport, not SQL privileges.

Key distinction: TLS and RSA password exchange are two different ways to protect this authentication step. Decide which model your environment intends to use before changing connection properties.

Verify: force a fresh connection through the real application path rather than relying on an already-open pool connection. If verified TLS consistently removes the public-key retrieval error even when full authentication is required, the non-TLS RSA-retrieval branch is no longer needed.

Fix #1 — preferred remote/production path: use verified TLS

For remote or production connections, configure Connector/J to use TLS and validate the server identity. sslMode=VERIFY_CA verifies the certificate chain; sslMode=VERIFY_IDENTITY also verifies that the host name matches the server certificate. Connector/J can use a configured truststore or, depending on configuration, the Java system truststore.

jdbc:mysql://db.example.internal:3306/app?sslMode=VERIFY_IDENTITY
Template only: replace the host, database, and trust configuration with values approved for your environment. Do not paste credentials into the JDBC URL shown in tickets or public logs.

If the server uses a private/self-signed CA, configure the appropriate trusted CA through Java/Connector/J truststore settings rather than disabling certificate verification.

Verify: connect with VERIFY_IDENTITY (or your approved TLS policy) and confirm the application succeeds without allowPublicKeyRetrieval=true.

Fix #2 — non-TLS but controlled environment: pin the server RSA public key

If TLS is intentionally disabled and your security design permits RSA password exchange, Connector/J supports serverRSAPublicKeyFile. This supplies a client-side copy of the MySQL server's RSA public key used for password exchange instead of retrieving that key dynamically during authentication. It is not the TLS server certificate, a CA certificate, or a Java truststore.

serverRSAPublicKeyFile=/approved/path/mysql_server_public_key.pem
Do not download a random key. Obtain the server RSA public key through a trusted administrative channel and manage it as pinned configuration. Treat rotation as a key-lifecycle event: if the MySQL server RSA key changes, validate the replacement out of band and update the pinned file through the same trusted process. Do not respond to a stale pin by silently enabling dynamic retrieval.

Verify: with TLS intentionally disabled, create a fresh application connection that exercises the required authentication path and confirm it succeeds using the approved public-key file without dynamic key retrieval. Record which server/key the pin belongs to so failover or rotation does not silently change the trust assumption.

Fix #3 — when allowPublicKeyRetrieval=true is actually appropriate

allowPublicKeyRetrieval=true permits Connector/J to request the RSA public key from the server during authentication. It can solve this exact error when TLS is disabled, but the property exists behind a false default for a reason: you are allowing the connection to obtain the key it will use for password protection from the peer it has not authenticated through TLS.

jdbc:mysql://localhost:3306/app?sslMode=DISABLED&allowPublicKeyRetrieval=true
Decision order: for remote/production use verified TLS first. If non-TLS is an intentional controlled design, prefer a server RSA public key obtained through a trusted channel. Dynamic public-key retrieval is the least identity-assured option of these three and should be an explicit trust decision.
Example for an intentionally non-TLS local/dev setup—not a production recommendation. Do not copy sslMode=DISABLED into a remote production connection merely to clear the error.

For production, prefer verified TLS. For a controlled non-TLS design where dynamic retrieval is accepted, document the trust assumption and network boundary. A pinned serverRSAPublicKeyFile avoids retrieving the key dynamically.

Verify: after enabling retrieval, confirm you are still in the intended network/security context. “Login works” alone does not prove the server identity is authenticated.

Fix #4 — stop mixing legacy useSSL with modern sslMode

Connector/J 8.0.13+ maps the deprecated legacy properties to sslMode. If sslMode is explicitly set, the legacy properties are ignored. This is why URLs copied from old answers can be misleading.

Modern modes:DISABLED — unencryptedPREFERRED — tries TLS first but can fall back to an unencrypted connection; do not use it when policy requires encryptionREQUIRED — TLS encryption is mandatory, but the server CA chain and hostname are not verified; this is not server-identity validationVERIFY_CA — encryption + CA verificationVERIFY_IDENTITY — encryption + CA verification + hostname verification

Verify: reduce the configuration to one intentional sslMode and confirm the effective application URL does not also depend on contradictory legacy properties.

Fix #5 — Spring, DBeaver, IDE, Docker, or CI still fails

Frameworks and tools can generate the JDBC URL, select a different Connector/J JAR, inject environment variables, reuse pooled connections, or route to another database node. Capture the actual driver version, effective properties and endpoint from the failing runtime. A local IDE test can succeed while a container uses another truststore, hostname, driver version, URL, server node, or authentication-cache state.

Reader rule: troubleshoot the command/runtime that fails, not the configuration screen you expected it to use.

Verify: compare the effective JDBC URL/properties and Connector/J version between the working and failing environments, with passwords/tokens redacted.

Fix #6 — do not downgrade the account authentication plugin as the first fix

Connector/J supports caching_sha2_password. Changing the MySQL account to an older authentication plugin can hide the transport problem while weakening or complicating your authentication policy. Fix TLS/RSA exchange first unless your server/application compatibility requirements explicitly require another plugin.

Verify: keep the intended account authentication plugin and prove the application connects through the approved TLS or RSA path.

Final verification — prove more than “the login works”

Acceptance checklist:expected MySQL host and portactual Connector/J versionintended sslModeserver identity validation policyaccount authentication pluginRSA key source if TLS is intentionally disabledsame settings verified in the real application/runtime

Verify: remove any temporary test-only properties that are not part of the approved design and reconnect from the real application.

What not to do

Do not blindly paste allowPublicKeyRetrieval=true&useSSL=false from an old answer.Do not disable TLS on a remote production database just to clear this authentication error.Do not assume sslMode=REQUIRED verifies the server identity; it requires encryption but not CA/hostname validation.Do not use PREFERRED when policy requires encryption, because it can fall back to an unencrypted connection.Do not download an unknown RSA public key or CA certificate from the web.Do not downgrade caching_sha2_password as the first response to a transport/configuration problem.Do not publish JDBC URLs containing passwords, tokens, or private infrastructure details.Do not assume one successful cached authentication proves the full-authentication path is configured correctly; test a fresh connection through the real runtime.Do not replace a stale pinned server RSA key by enabling dynamic retrieval without validating whether the server key legitimately rotated.Do not assume a pooled connection reproduces authentication; an existing pool session may bypass the connection/authentication path you are trying to test.Do not keep diagnosing public-key retrieval once authentication advances and the error changes to TLS identity, access denied, database authorization or another stage.

Still seeing “Public Key Retrieval is not allowed”?

Capture these before escalating:full redacted exception chainConnector/J version and JAR sourceMySQL server versionaccount authentication plugineffective JDBC URL/properties with secrets removedsslMode and truststore configurationwhether serverRSAPublicKeyFile or allowPublicKeyRetrieval is setlocal vs container/CI/IDE differenceswhether the test used a genuinely fresh connection or an existing connection poolthe exact MySQL endpoint/node reached, especially with proxies, replicas or failoverwhether a pinned server RSA key recently rotated or differs across nodesthe first different error after authentication advances past public-key retrieval

If the next failure becomes a TLS certificate or hostname error, stay on the TLS branch and repair trust/identity. Do not retreat to sslMode=DISABLED merely because TLS validation exposed the next real issue.

Official references

Still stuck? Ask the community

Share the redacted Connector/J version, sslMode, authentication plugin, and whether the same host works through verified TLS.

Keep it safe: never post database passwords, full JDBC URLs with secrets, private keys, truststore passwords, tokens, or internal credentials.
Powered by GitHub DiscussionsSign in with GitHub to comment. Reading comments does not require sign-in.

Loading community discussion…