{"record":{"id":"7ae380dc2cecf17b","repo":"quarkusio/quarkus","slug":"hostname-verification-failure","errorCode":null,"errorMessage":"Hostname verification failure","messagePattern":"Hostname verification failure","errorType":"exception","errorClass":"SSLException","httpStatus":null,"severity":"error","filePath":"extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/HttpClientBuilder.java","lineNumber":238,"sourceCode":"    }\n\n    public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {\n        this.clientKeyStore = keyStore;\n        this.clientPrivateKeyPassword = new String(password);\n        return this;\n    }\n\n    static class VerifierWrapper implements X509HostnameVerifier {\n        protected HostnameVerifier verifier;\n\n        VerifierWrapper(HostnameVerifier verifier) {\n            this.verifier = verifier;\n        }\n\n        @Override\n        public void verify(String host, SSLSocket ssl) throws IOException {\n            if (!verifier.verify(host, ssl.getSession()))\n                throw new SSLException(\"Hostname verification failure\");\n        }\n\n        @Override\n        public void verify(String host, X509Certificate cert) throws SSLException {\n            throw new SSLException(\"This verification path not implemented\");\n        }\n\n        @Override\n        public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {\n            throw new SSLException(\"This verification path not implemented\");\n        }\n\n        @Override\n        public boolean verify(String s, SSLSession sslSession) {\n            return verifier.verify(s, sslSession);\n        }\n    }\n","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/keycloak-authorization/runtime/src/main/java/io/quarkus/keycloak/pep/runtime/HttpClientBuilder.java#L220-L256","documentation":"This SSLException is thrown by the Keycloak adapter's hostname verifier wrapper when the configured HostnameVerificationPolicy's underlying verifier rejects the hostname presented in the server's SSL session during an HTTPS handshake. It means the certificate's CN/SAN entries do not match the hostname the client is connecting to, so the TLS connection is aborted.","triggerScenarios":"Making an HTTPS request from the Keycloak PEP (PolicyEnforcer/AuthzClient) to the Keycloak auth-server URL whose TLS certificate does not match the host in the URL (e.g. connecting via IP address or a different name than the cert's CN/SAN), while quarkus.keycloak.policy-enforcer... hostname verification is at the default (WILDCARD) policy instead of ANY.","commonSituations":"Local dev Keycloak started with a self-signed or generic certificate but accessed via localhost/IP; Docker/Kubernetes service names differing from cert SANs; hostname mismatch introduced when proxying or port-forwarding to the auth server.","solutions":["Fix the auth-server URL to use the exact hostname present in the Keycloak server certificate's CN/SAN entries.","Import the Keycloak server certificate into the configured truststore and ensure the hostname matches (truststore alone does not bypass hostname checks).","Set quarkus.oidc.tls.hostname-verification-algorithm / adapter config isAllowAnyHostname=true to relax hostname verification (dev/test only).","Use a properly signed certificate (or generate one with the correct SANs) on the Keycloak server."],"exampleFix":"// before (quarkus.properties / application.properties)\nquarkus.oidc.auth-server-url=https://127.0.0.1:8443/realms/quarkus\n// after (use the name on the cert, or explicitly allow any hostname in dev)\nquarkus.oidc.auth-server-url=https://localhost:8443/realms/quarkus\n# dev/test only:\nquarkus.keycloak.policy-enforcer.enable-https=false # or adapterConfig.setAllowAnyHostname(true)","handlingStrategy":"validation","validationCode":"// verify cert hostname before enabling policy enforcer\nKeyStore ts = KeyStore.getInstance(\"PKCS12\");\nts.load(new FileInputStream(truststorePath), tsPassword.toCharArray());\n// ensure auth-server-url host equals a SAN/CN in the server certificate:\n// keytool -list -v -keystore truststore.p12 | grep -i dns\nString host = URI.create(authServerUrl).getHost();\nif (!expectedSanPattern.matcher(host).matches()) throw new IllegalStateException(\"host mismatch\");","typeGuard":null,"tryCatchPattern":"try {\n    client = HttpClientBuilder.create(adapterConfig).build();\n} catch (SSLException e) {\n    if (e.getMessage().contains(\"Hostname verification failure\")) {\n        log.error(\"Auth-server cert does not match host; fix URL or cert SANs\", e);\n    }\n    throw e;\n}","preventionTips":["Always use the certificate's exact hostname in quarkus.oidc.auth-server-url (never raw IPs in prod).","Test TLS connectivity to Keycloak with curl --cacert before deploying.","Only relax hostname verification (allow-any-hostname) in dev/test profiles."],"tags":["ssl","tls","hostname-verification","keycloak"],"backgroundTag":"ssl-hostname-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}