Repository navigation
REF-16: Send OCSP requests using POST from the library, and make CRLCheckerTest reliable - #90
Merged
Conversation
…ach the responder The JDK OCSP client uses the RFC 5019 GET form (request base64-encoded in the URL path) for small requests. The NemLog-in test OCSP responder at ca1.cti-gov.dk returns HTTP 404 for that GET form (it only serves POST), so CRLCheckerTest's OCSP validation failed with UNDETERMINED_REVOCATION_STATUS and dropped the otherwise-valid certificate. Set com.sun.security.ocsp.useget=false in BaseServiceTest.beforeAll so the JDK POSTs the OCSP request (request in the body) instead. Verified end-to-end that this makes the responder return "good" and the certificate validate.
…n tests Replace TestConstants.REVOKED_CERTIFICATE with a certificate that is actually revoked at the NemLog-in test CA (verified: OCSP reports "revoked" and the serial is present in the issuing CRL; valid 2026-07-06 .. 2029-07-05). The revoked OCSP/CRL tests now pass because the certificate is genuinely revoked, rather than incidentally due to an unreachable responder. Tag both testOcspCheckOnRevokedCertificate and testCrlCheckOnRevokedCertificate with @tag("integration") since they depend on the live test CA revocation infrastructure. No group filtering is configured, so they still run by default; the tag allows excluding them from offline runs via -DexcludedGroups=integration.
…ests The JDK OCSP client uses the RFC 5019 GET form (request base64-encoded into the URL path) for requests of 255 characters or less, from JDK 12 onwards. The NemLog-in OCSP responders answer HTTP 404 to that form, so every OCSP check fails with UNDETERMINED_REVOCATION_STATUS: the SP silently degrades to the CRL fallback, or drops the IdP certificates entirely when CRL checking is disabled as well. Java 8 and 11 always POST and are unaffected. Forcing POST in the test base class only hid this from the test suite, it did not fix deployments. Set com.sun.security.ocsp.useget=false from OIOSAML3Service.init instead, gated by the new configuration property oiosaml.servlet.revocation.ocsp.post.enabled (default true). The JDK reads the property once, when sun.security.provider.certpath.OCSP is initialized, so it has to be set before the first OCSP check in the JVM. A value set explicitly by the deployer is left alone. POST support is mandatory for responders per RFC 6960, so forcing it is safe, the only cost is that GET responses are no longer HTTP cacheable for other OCSP users in the same JVM. Also replace the JVM global "ocsp.enable" and "ocsp.responderURL" security properties with a per validation PKIXRevocationChecker. The old code published the responder of the certificate being checked as a JVM wide default, which leaked into every other PKIX validation in the container and raced with concurrent checks. NO_FALLBACK keeps CRL fallback where it belongs, in checkCertificate, driven by the OIOSAML configuration. With the library doing this, BaseServiceTest no longer needs to set the system property, so CRLCheckerTest now exercises the production path. Verified: the four CRLCheckerTest cases pass, and re-running with -DargLine=-Dcom.sun.security.ocsp.useget=true makes the valid certificate OCSP test fail again, confirming both the 404 on GET and that the deployer override is honoured.
thomasnymand
force-pushed
the
feature/REF-16-ocsp-force-post-in-tests
branch
from
August 13, 2026 09:34
d41bbb3 to
5bbfa6a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sends OCSP requests using POST from the library itself, and fixes the
CRLCheckerTestproblems that uncovered the issue.The problem
The JDK OCSP client uses the RFC 5019 GET form (request base64-encoded into the URL path) for requests of 255 characters or less. The NemLog-in OCSP responders answer HTTP 404 to that form, so every OCSP check fails with
UNDETERMINED_REVOCATION_STATUS.This is not test-only. In a deployment it means:
warnper certificate),oiosaml.servlet.revocation.crl.check.enabled=false, all IdP certificates are dropped and login breaks.Version detail:
sun.security.provider.certpath.OCSPin JDK 8 and 11 always POSTs; the GET form and thecom.sun.security.ocsp.usegetswitch exist from JDK 12 onwards (confirmed present in 21/25/26, absent in 11/8).USE_GETis aprivate static final booleaninitialized in the class's static initializer from a system property only (System.getProperty, defaulttrue), soSecurity.setPropertyhas no effect and setting it after the first OCSP check is too late.Two further problems in
CRLCheckerTest:testOcspCheckOnValidCertificatefailed (expected: <1> but was: <0>) for the reason above.assertEquals(0, …). The revoked certificate's real status was never exercised.Changes
Force POST in the library, not in the tests.
CRLChecker.configureOcspTransportsetscom.sun.security.ocsp.useget=false, called fromOIOSAML3Service.initso it runs before the first OCSP check in the JVM. It is gated by a new propertyoiosaml.servlet.revocation.ocsp.post.enabled(defaulttrue), plumbed throughConstants→Configuration→DispatcherServlet. A value set explicitly by the deployer (-Dcom.sun.security.ocsp.useget=…) is left alone, and each branch logs what happened. POST support is mandatory for responders per RFC 6960, so forcing it is safe; the only cost is that GET responses are no longer HTTP cacheable for other OCSP users in the same JVM.Drop the JVM global security properties.
doOCSPCheckno longer setsocsp.enable/ocsp.responderURL. Those published the responder of the certificate currently being checked as a JVM wide default, which leaked into every other PKIX validation in the container and raced with concurrent checks. Replaced with a per validationPKIXRevocationChecker(Java 8 API):setOcspResponder(URI)plusOption.NO_FALLBACK, so CRL fallback stays incheckCertificatewhere the OIOSAML configuration drives it.Use a genuinely revoked certificate for
TestConstants.REVOKED_CERTIFICATE. Verified against the live test CA: OCSP reportsrevokedand the serial is present in the issuing CRL. Validity 2026-07-06 .. 2029-07-05 (no near-term expiry).Tag the revoked tests
@Tag("integration")(both OCSP and CRL variants) since they depend on the live test CA revocation infrastructure. No group filtering is configured, so they still run by default; the tag allows excluding them offline via-DexcludedGroups=integration.Remove the workaround from
BaseServiceTest, soCRLCheckerTestnow exercises the production path instead of a test-only property.Verification
mvn -pl oiosaml test: the fourCRLCheckerTestcases pass (present, not skipped). Re-running with-DargLine=-Dcom.sun.security.ocsp.useget=truemakestestOcspCheckOnValidCertificatefail again, which confirms both that the responder really 404s on GET and that the deployer override is honoured. The only remaining failure is the unrelatedOIOBPPUtilTest(JDK 26 JAXB incompatibility), which also fails onmaster.Notes
com.sun.security.ocsp.usegetis an OpenJDK/Oracle-internal property, reliable on HotSpot-derived JVMs and JVM-global in scope. It is applied wheneveroiosaml.servlet.revocation.ocsp.post.enabledis true, also when OIOSAML's own OCSP checking is disabled, because applying it lazily would risk being too late to take effect.PKIXRevocationChecker.setOcspResponses(…)so the JDK still does all signature and validity verification. That would remove the dependency on a JDK-internal property entirely and give us control over OCSP timeouts.