Fix NPE in SAML 2.0 configuration when OpenSAML is on the module path - #19784
Open
akashchamp wants to merge 1 commit into
Open
akashchamp wants to merge 1 commit into
akashchamp wants to merge 1 commit into
Conversation
Version.getVersion() relies on Package#getImplementationVersion(),
which is null when OpenSAML is loaded as a named module from the
Java module path (instead of the classpath). Since USE_OPENSAML_5
was computed as Version.getVersion().startsWith("5") in a static
field initializer, this threw a NullPointerException at class-init
time, permanently marking the class unusable for the lifetime of the
JVM (ExceptionInInitializerError -> NoClassDefFoundError on every
subsequent reference).
This same pattern was duplicated identically in five places:
Saml2LoginConfigurer, Saml2LogoutConfigurer, Saml2MetadataConfigurer,
Saml2LoginBeanDefinitionParserUtils, and
Saml2LogoutBeanDefinitionParserUtils. All five are fixed the same
way: fall back to the class's module descriptor version when the
package implementation version is unavailable, and default to
assuming OpenSAML 5 (the only version this codebase supports) when
neither can be determined, instead of crashing.
Closes spring-projectsgh-19628
Signed-off-by: Akash Kumar <116457960+akashchamp@users.noreply.github.com>
This branch has not been deployed
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.
Fixes gh-19628
Problem
Saml2LoginConfigurer(and four sibling SAML 2.0 configuration classes) compute a static field via:org.opensaml.core.Version#getVersion()readsPackage#getImplementationVersion(), which isnullwhen OpenSAML is loaded as a named module from the Java module path rather than the classpath (confirmed below). Calling.startsWith("5")on thatnullresult throws aNullPointerExceptionduring the class's static initializer, which permanently marks the class unusable for the lifetime of the JVM (ExceptionInInitializerErrorthe first time,NoClassDefFoundErroron every later reference) — so any application that loads OpenSAML from the module path cannot use SAML 2.0 login at all.The exact same pattern (and therefore the exact same bug) is duplicated in five places:
Saml2LoginConfigurerSaml2LogoutConfigurerSaml2MetadataConfigurerSaml2LoginBeanDefinitionParserUtilsSaml2LogoutBeanDefinitionParserUtilsFix
Each of the five duplicates now computes the flag with a small null-safe helper, following the fallback the reporter suggested: if the package implementation version is unavailable, fall back to the owning module's descriptor version (available for a named/automatic module); if neither is available, default to assuming OpenSAML 5, since it's the only version this codebase currently supports, rather than crashing.
The method takes the lookup class as a parameter (instead of hardcoding
Version.classinside it) purely so it's directly unit-testable without needing to construct a real Java module layer in the test.How this was verified
Reproduced the exact crash with the actual
opensaml-core-api-5.2.3.jarfrom this project's own dependency graph, loadingorg.opensaml.core.Versionfirst from the classpath, then as a module-path automatic module:This confirms both halves of the reporter's diagnosis: the package version really is
nullunder the module path, and the module descriptor fallback correctly recovers5.2.3from the automatic module's filename-derived version, matching the pre-fix classpath behavior with no regression.Automated tests: added a regression test per file (10 total) that exercises
useOpenSaml5(...):Version.class, asserting it still matchesVersion.getVersion().startsWith("5")on the normal test classpath (no behavior change)nulland it runs in the unnamed module) to prove the null-guard path no longer throwsRan the full existing suites for the five affected files locally (
Saml2LoginConfigurerTests,Saml2LogoutConfigurerTests,Saml2MetadataConfigurerTests,Saml2LoginBeanDefinitionParserTests,Saml2LogoutBeanDefinitionParserTests) — all passing, no change to existing behavior on a normal classpath.AI disclosure
This change was implemented with AI assistance (Claude Code).