Skip to content

JAXB3 Migration#1023

Open
maximthomas wants to merge 24 commits into
OpenIdentityPlatform:masterfrom
maximthomas:features/jaxb3-update-2026-05-19
Open

JAXB3 Migration#1023
maximthomas wants to merge 24 commits into
OpenIdentityPlatform:masterfrom
maximthomas:features/jaxb3-update-2026-05-19

Conversation

@maximthomas

Copy link
Copy Markdown
Contributor

No description provided.

@maximthomas
maximthomas requested a review from vharseko May 21, 2026 10:13
@vharseko vharseko linked an issue May 27, 2026 that may be closed by this pull request
@vharseko vharseko added this to the 16.2.0 milestone Jun 1, 2026
vharseko added 11 commits June 20, 2026 12:56
… after JAXB3 migration

getIDPSSOConfigOrSPSSOConfig() now returns List<JAXBElement<BaseConfigType>>,
but removeFromEntityConfig still cast elements directly to BaseConfigType /
AttributeType. Unwrap via getValue(), mirroring addToEntityConfig.
…B3 migration

getSingleLogoutService() returns List<SingleLogoutServiceElement> (JAXBElement
wrappers); unwrap to List<EndpointType> before LogoutUtil.doLogout().
Unwrap the SingleLogoutService wrapper list to List<EndpointType> before
LogoutUtil.doLogout(). The wrapper-expecting getSLOServiceLocation() path is
left unchanged.
…r JAXB3 migration

convertAttributes() added the AttributeValueElement wrapper instead of its
content to the list passed to setAttributeValueString(), which casts each
element to String. Add the unwrapped value.
…ws after JAXB3 migration

getIDPSSOConfigOrSPSSOConfigOrAuthnAuthorityConfig() returns
List<JAXBElement<BaseConfigType>>; unwrap via getValue() before use.
…ter JAXB3 migration

getUse() returns null when the optional use attribute is absent (one key for
both signing and encryption); guard before calling value().
… migration

SingleLogoutService / NameIDMappingService / AuthnQueryService /
AssertionIDRequestService endpoints were created with createAttributeServiceType(),
which injects a spurious xsi:type="AttributeServiceType" on marshal. Use
createEndpointType().
…DFFCOTUtils after JAXB3 migration

getAffiliationDescriptorConfig() is null for ordinary SP/IDP entities; guard the
wrapper before getValue() in add/remove EntityConfig.
…ements after JAXB3 migration

Optional JAXB elements are now possibly-null JAXBElement wrappers. Add a
null-safe jaxbValue() helper in IDPPBaseContainer and use it across the IDPP
container read-back methods.
…nt after JAXB3 migration

getIDPSSODescriptor() can return null for an unknown issuer; reject with
InvalidGrantException instead of dereferencing the null wrapper.
AttributeValueElement.getValue() returns the scalar content (not a List) for
string-valued attributes, so the "instanceof List" guard silently skipped
context matching. Normalize scalar and list content to restore the previous
getContent() behaviour.

@vharseko vharseko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #1023 "JAXB3 Migration" — fix registry

Branch tip after follow-up work: f168117cc6 (11 commits on top of 63ff4448ae).
PR: #1023


Root cause (common to all 11 fixes)

The migration moves XML binding from JAXB 1.0 / javax.xml.bind to JAXB 3.0 / jakarta.xml.bind and stops checking generated classes into the repo — they are now generated at build time (jaxb-maven-plugin). In doing so the shape of the generated API changes, which breaks consumer code in three ways that compile but fail at runtime:

  1. Global XML elements are now JAXBElement<T> wrappers.
    A getter that used to return the concrete type now returns a wrapper, so callers must call .getValue().

    • Any remaining raw cast (Type) iter.next() or enhanced-for for (Type x : rawList) over a list of wrappers → ClassCastException. It only compiles because the list is declared as a raw List.
  2. Optional elements are now nullable wrappers.
    A getXxx().getValue() chain on an absent (optional) element → NullPointerException, and the existing if (x != null) guard below becomes dead code.

  3. ObjectFactory.createXxx() factory methods now take a value argument.
    Passing the subtype AttributeServiceType into a factory whose declared value type is EndpointType makes JAXB emit a spurious xsi:type="AttributeServiceType" on marshal → invalid SAML2 metadata.


Commit registry

# Commit File(s) Type Essence
1 dac13f3c06 WSFederationCOTUtils.java CCE remove path not migrated
2 9e8cad2dd5 SAML2SingleLogoutHandler.java CCE wrappers into doLogout(List<EndpointType>)
3 ea473f7fc0 SPSingleLogout.java CCE same in SP SLO
4 6a4d81419b AttributeQueryUtil.java CCE wrapper added instead of value
5 3435063154 GetCircleOfTrusts.java, ImportSAML2MetaData.java CCE raw cast to BaseConfigType
6 271ad11235 SAMLv2ModelImpl.java NPE getUse() == null
7 faf0be2e7e SAMLv2ModelImpl.java XML spurious xsi:type on endpoints
8 d9d4b8e13e IDFFCOTUtils.java NPE no affiliation config
9 5aa4d1c5e3 IDPP* containers NPE optional Liberty PP elements
10 f77dbb76bd Saml2GrantTypeHandler.java NPE unknown issuer
11 f168117cc6 SAML2IDPProxyFRImpl.java logic silently disabled context matching

Per-fix detail

1. dac13f3c06 — WSFederationCOTUtils.removeFromEntityConfig (CCE)

File: openam-federation-library/.../wsfederation/meta/WSFederationCOTUtils.java
Problem: getIDPSSOConfigOrSPSSOConfig() returns List<JAXBElement<BaseConfigType>>. addToEntityConfig was migrated to .getValue(), but the sibling removeFromEntityConfig was not: it still did (BaseConfigType) iter.next() and (AttributeType) iter2.next(). Removing a WS-Fed entity from a circle of trust → CCE.
Fix: generics + .getValue(), mirroring the add method.

2. 9e8cad2dd5 — Multi-protocol SOAP single logout (CCE)

File: .../multiprotocol/SAML2SingleLogoutHandler.java
Problem: getSingleLogoutService()List<SingleLogoutServiceElement> (which are JAXBElement<EndpointType>). The list is passed to LogoutUtil.doLogout(List<EndpointType>), whose for (EndpointType e : list) → CCE. Sibling paths (IDPSessionListener/SPSessionListener) were fixed; this one was missed.
Fix: .stream().map(JAXBElement::getValue).collect(...) before doLogout.

3. ea473f7fc0 — SP single logout (CCE)

File: .../saml2/profile/SPSingleLogout.java
Problem: same wrapper list passed into doLogout(List<EndpointType>).
Fix: unwrap to List<EndpointType>. The second slosList (feeds getSLOServiceLocation, which expects the wrappers) is intentionally left unchanged.

4. 6a4d81419b — SAML2 attribute query conversion (CCE)

File: .../saml2/profile/AttributeQueryUtil.java
Problem: convertAttributes() added the wrapper AttributeValueElement instead of its content. The list goes to setAttributeValueString(), which does (String) iter.next() → CCE. The computed content was unused.
Fix: add content (the unwrapped value).

5. 3435063154 — OpenFM workflows (CCE)

Files: OpenFM/.../workflow/GetCircleOfTrusts.java, ImportSAML2MetaData.java
Problem: getIDPSSOConfigOrSPSSOConfigOrAuthnAuthorityConfig()List<JAXBElement<BaseConfigType>>, but the code did (BaseConfigType) config.iterator().next() → CCE when resolving the realm for a hosted entity.
Fix: generics + .getValue().

6. 271ad11235 — KeyDescriptor without use (NPE)

File: openam-console/.../federation/model/SAMLv2ModelImpl.java
Problem: keyOne.getValue().getUse().value()getUse() is null when a <KeyDescriptor> omits the optional use attribute (one key for both signing and encryption). The next line if (type == null ...) was written for exactly that null case but is now unreachable. NPE when viewing the entity in the console.
Fix: null guard before .value().

7. faf0be2e7e — invalid metadata endpoints (XML)

File: openam-console/.../federation/model/SAMLv2ModelImpl.java
Problem: SingleLogoutService / NameIDMappingService / AuthnQueryService / AssertionIDRequestService endpoints were built with createAttributeServiceType(). Since AttributeServiceType extends EndpointType, marshalling injects a spurious xsi:type="AttributeServiceType" → off-schema metadata. 8 sites.
Fix: createEndpointType(). The two legitimate createAttributeServiceElement(createAttributeServiceType()) sites are left untouched.

8. d9d4b8e13e — IDFFCOTUtils without affiliation config (NPE)

File: .../federation/meta/IDFFCOTUtils.java
Problem: getAffiliationDescriptorConfig().getValue() — for ordinary SP/IDP entities the getter is null, so .getValue() fails before the dead if (affiConfig != null) check. 2 sites (add/remove EntityConfig).
Fix: null-check the wrapper before .getValue().

9. 5aa4d1c5e3 — Liberty Personal Profile containers (NPE)

Files: IDPPBaseContainer.java + IDPPFacade, IDPPDemographics, IDPPLegalIdentity, IDPPEmploymentIdentity, IDPPCommonName, IDPPAddressCard
Problem: read-back methods (getXxxMap/createAddressCard) do obj.getXxx().getValue() on optional PP elements; for absent ones (common, e.g. middle name) → NPE. The old code stored the nullable value and downstream getAttributeMap handled null fine.
Fix: add protected static <T> T jaxbValue(JAXBElement<T>) to the base class and apply it at every read site.

10. f77dbb76bd — OAuth2 SAML2 bearer, unknown issuer (NPE)

File: openam-oauth2-saml2/.../core/Saml2GrantTypeHandler.java
Problem: metaManager.getIDPSSODescriptor(...) can return null for an unknown issuer; idpSsoDescriptor.getValue() → NPE. Previously null was handled gracefully (clean rejection). This turns a rejection into an uncaught exception.
Fix: null-check the descriptor → InvalidGrantException("Unknown assertion issuer").

11. f168117cc6 — IDP proxy: authn-context matching (logic)

File: .../saml2/plugins/SAML2IDPProxyFRImpl.java
Problem: AttributeValueElement.getValue() returns a scalar (String) for string-valued attributes, not a List, so the instanceof List guard silently skipped the whole proxy-IDP authn-context selection block (a silent regression, no error).
Fix: normalize scalar and list content to List, restoring the previous getContent() behaviour.


Verification

  • Build (JDK 26 / Maven 3.9.16) of the affected modules — BUILD SUCCESS:
    Federation Library, OpenFM, Admin Console, OAuth2-SAML2.
  • Schema modules (saml2/liberty/wsfederation/xacml3) build and generate classes correctly.
  • The cumulative diff of all 11 commits is byte-identical to the patch that was built and verified.
  • Push to the PR branch was a fast-forward (63ff4448ae..f168117cc6).

Still to verify manually (not covered by compilation)

  • JSPs (not compile-checked): SA_IDP.jsp, SA_SP.jsp, spSingleLogoutInit.jsp, realmSelection.jsp.
  • Functionally: SAML2 SLO (SOAP + multi-protocol), attribute query, COT add/remove (SAML2 / WS-Fed / IDFF), Liberty Personal Profile, OAuth2 SAML2 bearer.

vharseko added 2 commits June 20, 2026 14:07
- RestAuthNameValueOutputCallbackHandler.java: keep correct NameValueOutputCallback Javadoc
- ResourceOwnerSessionValidator.java: merge copyright attributions
@vharseko vharseko added the refactoring Code cleanup, refactor, dead-code or dependency removal label Jul 8, 2026

@vharseko vharseko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: JAXB 1.x → JAXB 3 migration

Deep review of the full diff vs merge base 0ee32ac4 (2,787 files, +4,327/−541,024). The build/codegen architecture was verified empirically (regenerated all three schema modules offline with the PR's plugin config and bindings, plus an unmarshal/marshal runtime probe with jaxb-runtime 3.0.2 on the PR's own test resources). The remaining findings are call-site bugs of the same classes already fixed in the follow-up commits on this branch.

What checks out (verified, not just read)

  • Package parity confirmed: codegen reproduces every deleted JAXB1 package exactly; every class-bearing package gets an ObjectFactory, so all JAXBContext.newInstance(contextPath) call sites resolve. Metadata + entity-config round-trip probe passes.
  • All 31 jaxb.properties correctly rewritten to org.glassfish.jaxb.runtime.v2.ContextFactory (the deprecated jakarta.xml.bind.context.factory key is accepted by the 3.0 ContextFinder).
  • xs:dateTime kept on java.util.Calendar and anyURI on String via globalBindings — avoids the XMLGregorianCalendar break; *Element classes recreated via jxb:class as JAXBElement<T> subclasses; the curation from ~127 to ~35 element classes in saml2 leaves zero dangling references.
  • Prefix-mapper key change to org.glassfish.jaxb.namespacePrefixMapper is correct and required (the old com.sun.xml.bind.* key throws PropertyException on the new runtime — verified).
  • No javax.xml.bind references remain anywhere in main sources. No hand-fixes were lost in the deleted generated code (checked full git history of those files).
  • Nice bonus fixes: the pre-existing iter/iterV bug in AttributeQueryUtil.convertAttributes, null check in Saml2GrantTypeHandler; new SAML2MetaUtilsTest + Playwright REST-STS e2e test.

Blocking bugs

CI is green because it compiles and runs unit tests, but these break at runtime ("needs testing" label is accurate).

WS-Federation — broken entirely

  • WSFederationMetaUtils.getAttributes (~line 231): casts members of List<AttributeElement> to AttributeType → guaranteed ClassCastException. Every WSFed extended-config read funnels through this helper (RPSigninRequest/RPSigninResponse, account/attribute mappers, WSFederationUtils.createSAML11Token).
  • WSFederationMetaUtils.getAttribute (~line 296): avp.getName() now resolves to JAXBElement.getName() returning a QName; equals(String key) is always false → every lookup (SIGNING_CERT_ALIAS, AUTH_URL, ASSERTION_TIME_SKEW, ACTIVE_REQUESTOR_PROFILE_ENABLED, ENDPOINT_BASE_URL, NameID settings) silently returns null. Needs avp.getValue().getName().

IDFF — broken entirely

  • IDFFMetaUtils.getAttributes (lines 297–306): same (AttributeType) cast on a List<AttributeElement> → CCE. This is the central helper for the whole IDFF stack (FSAssertionManager, FSAuthnDecisionHandler, attribute mappers, IDP proxy, …).
  • IDFFCOTUtils.updateCOTAttrInConfig (line 226) / removeCOTNameFromConfig (line 263): (BaseConfigType) and (AttributeType) casts on element lists, and a raw AttributeType added into a List<AttributeElement>. The create path in the same file was migrated; the update helpers were missed — adding/removing an IDFF entity to/from a COT fails whenever the entity has an entity config.
  • federation/key/KeyUtil.getKeyDescriptor (~295–318): kd.getValue().getUse().value() NPEs when use is absent (the following use == null handling is now dead), and the no-match branch returns noUsageKD.getValue() → NPE where the old code returned null to null-tolerant callers.
  • IDFFProviderManager (~128/188/214), LibertyManager (~1276/2025), EncryptedNameIdentifier (~225): .getValue() chained onto nullable getSPDescriptorConfig(...) before the null check → NPE for IDP-only entities; the SP→IDP fallback logic is now dead code.

SAML2 — optional-Boolean unboxing NPEs (highest-impact class)

JAXB1 generated primitive boolean for optional XSD attributes (absent → false); XJC 3 generates nullable Boolean (attributes are use="optional" with no default in the XSDs). Direct unboxing now NPEs whenever the attribute is absent — which is schema-legal and common in third-party metadata:

  • IDPSSOUtil.java:1865, 1953, 2026acs.getValue().isIsDefault() looping over all ACS entries of the remote SP; getDefaultACSurl runs on the common no-ACS-in-request path → IDP-side SSO fails for typical third-party SP metadata with any ACS entry lacking isDefault.
  • SPSSOFederate.java:377, 448, 1000; SAML2Utils.java:495 (verifyResponse); IDPArtifactResolution.java:472; IDPSSOUtil.java:3017; UtilProxySAMLAuthenticator.java:161; IDPProxyUtil.java:222; SPACSUtils.java:511; QueryClient.java:811; QueryHandlerServlet.java:421isWantAssertionsSigned() / isAuthnRequestsSigned() / isWantAuthnRequestsSigned().
  • isHosted() — same class: SAML2MetaManager.java:1237/1408/1494/1532, SAML2MetaSecurityUtils.java:182/475, IDFFMetaManager.java:837/871, WSFederationMetaManager.java:833/896/982, ImportMetaData.java:192/264/324, OpenFM workflow tasks, console TaskModelImpl. OpenAM always writes the attribute, but hand-imported extended configs may omit it.
  • Systematic fix: Boolean.TRUE.equals(...) at call sites (the PR already does exactly this for isPassive() in UtilProxySAMLAuthenticator), or XSD defaults, or an xjb customization. Note the added test resources set every optional boolean (hosted="1", isDefault="1", …), which is why tests don't catch this class — please add a metadata fixture with the optional attributes omitted.
  • (IDFF metadata side is not affected: lib-arch-metadata.xsd has default="false" — checked.)

SAML2 — other

  • AttributeQueryUtil.isSameAttribute:988desired.getName().equals(supported.getName()) compares String to QName (always false) → every AttributeQuery naming specific attributes is rejected with "Attribute name not supported". Needs supported.getValue().getName().
  • SAML2MetaSecurityUtils.setExtendedAttributeValue:565(AttributeType) cast on an AttributeElement list → CCE; breaks ssoadm update-entity-keyinfo (the add at line 575 was fixed, the removal loop wasn't).
  • SAML2MetaSecurityUtils.updateProviderKeyInformation:483-495.getValue() NPEs before the intended entityNotIDP/entityNotSP errors (now dead code).
  • SAML2ProviderManager (lines ~96, ~167, ~191, ~216) — getSPSSOConfig(...).getValue() NPEs for IDP-only providers; the IDP fallback in all four methods is dead; the catch handles SAML2MetaException only.

Liberty PP / Discovery / WSS Policy

  • WSSPolicyManager (lines 120, 131, 249–250, 302–303): createExactlyOneElement(createPolicyElement()) substitutes the anonymous Policy type where OperatorContentType is expected — the runtime reports SUBSTITUTED_BY_ANONYMOUS_TYPE and marshalling aborts → getPolicy()/getInputPolicy()/getOutputPolicy() always throw. Use createOperatorContentType().
  • IDPPEncryptKey/IDPPSignKey (getContainerObject): bare X509DataType added into KeyInfo content (an @XmlElementRefs list) → MarshalException: missing an @XmlRootElement annotation. Should be of.createX509DataElement(x509DataType) (the read paths in the same files already expect X509DataElement).
  • IDPPLegalIdentity:489(AltIDType) cast after instanceof AltIDElement → CCE (AltIDElement extends JAXBElement<AltIDType> now); :105createAltIDElement(getAltID(userMap)) is never null, so an empty <AltID/> is always added where the old code added nothing.
  • IDPPDemographics:281IDPPBaseContainer.getAttributeMap: List<LanguageElement> members match neither instanceof DSTString nor DSTURI → PP Language values silently dropped on read and potentially wiped on modify.
  • DiscoveryService (~221, ~362): getEncryptedResourceID().getValue() NPEs when both ResourceID variants are absent.

Console

  • ImportEntityModelImpl (~145 createSAMLv2Entity, ~316 createWSFedEntity): (BaseConfigType) config.iterator().next() on List<JAXBElement<BaseConfigType>> → CCE when importing hosted entities with extended metadata via the console (the identical pattern was fixed in OpenFM ImportSAML2MetaData/GetCircleOfTrusts; the console counterpart was missed).
  • SAMLv2ModelImpl:2035, 2096(AttributeType) casts → CCE opening the XACML PEP/PDP extended-metadata pages (lines 1605/1676 in the same file show the correct pattern).
  • SAMLv2ModelImpl:1733-1737getClass().getName().contains("KeySizeImpl") matches nothing under JAXB3 (no *Impl classes) → encryption key size silently never read. Should be instanceof EncryptionMethodType.KeySize.
  • IDFFModelImpl:497, 565, 1247, 1306, 1494; SAMLv2ModelImpl:2321, 2380.getValue() before the null check: first-time access to an IDFF entity's IDP/SP tab now NPEs instead of auto-creating the default extended config; invalid.entity.name errors degraded to NPE.
  • SMDiscoEntryData (~212–267): directives unwrapped to bare DirectiveType and added to an @XmlAnyElement list → MarshalException + element identity (which directive) lost; the read path checks instanceof AuthenticateRequesterElement etc., so the round-trip is broken. Add the JAXBElement wrappers, not their values.

Build / packaging

  • openam-clientsdk/pom.xml (~146): shade includes the non-existent coordinate jakarta.xml.bind:jaxb-api (correct: jakarta.xml.bind:jakarta.xml.bind-api) and omits jaxb-runtime's transitive deps (org.glassfish.jaxb:jaxb-core, com.sun.istack:istack-commons-runtime, org.glassfish.jaxb:txw2, jakarta.activation:jakarta.activation-api) → standalone clientsdk consumers get NoClassDefFoundError on first JAXB use.
  • openam-wsfederation-schema/pom.xml:85-88: leftover com.sun.xml.bind:jaxb1-impl dependency (removed from saml2/liberty poms in this PR) — drags the dead JAXB1 runtime into every WAR. Related: openam-auth-saml2 SAML2ProxyTest.java:26 still imports com.sun.xml.bind.StringInputStream (exists only in jaxb1-impl).

Risks / cleanups (non-blocking)

  • Sweep the .getValue()-before-null-check pattern — beyond the cases above there are ~a dozen more (e.g. SAML2Utils.java:556/2194/3556, SPACSUtils.java:392, IDPSessionListener.java:159, NameIDMapping.java:206, DoManageNameID.java:291, AssertionIDRequestUtil.java:405, multiprotocol IDFFSingleLogoutHandler:226, SingleLogoutManager:689, ValidRelayStateExtractor, DefaultAttributeMapper, ValidWReplyExtractor, ConfigureGoogleApps:94). Formerly handled null-metadata cases now surface as NPEs.
  • BaseConfigType flipped abstract="true""false" in three XSDs — necessary for JAXB3 instantiation and only used as codegen input, but worth recording as intentional in the PR description (which is currently empty).
  • Split package: org.w3._2001.xmlschema.Adapter1 is now generated into both the liberty and wsfederation jars (same bytecode; duplicate-class checkers/JPMS will complain). saml2 avoids this via its schema.xsd package-mapping trick — the same could be applied to wsfed.
  • FAMClassLoader (OpenFM): lists now internally inconsistent — classesToBeLoaded says jakarta.xml.bind. but maskedResouces still masks javax/xml/bind/, and com.sun.xml.bind.* (JAXB1 RI) entries remain.
  • Dead JAXB1 cruft to delete with this PR: ~25 bgm.ser grammar caches still packaged in the schema jars; JAXB1 entries in THIRD-PARTY.properties; com.sun.xml.bind.util.ListImpl/ProxyListImpl whitelist entries in IOUtils and serverdefaults.properties:191; root pom <jaxb1.version> property; orphan jaxb.properties in packages with no classes (.../common/jaxb/xmlsec/, parent common/jaxb/).
  • PPRequestHandler: stray junk import org.glassfish.jaxb.core.v2.model.core.ID; getMarshaller().setProperty(...); getMarshaller().marshal(...) uses two different marshaller instances so the prefix mapper never applies (pre-existing).
  • SLOLocationTest: createSingleLogoutServiceElement(of.createAttributeServiceType()) works only because AttributeServiceType extends EndpointType — use createEndpointType().
  • Upgrade note: previously serialized blobs containing JAXB1 com.sun.xml.bind.util.ListImpl instances can no longer deserialize after upgrade (class gone from classpath).

Suggested order of fixes

  1. WSFederationMetaUtils.getAttributes/getAttribute, IDFFMetaUtils.getAttributes, IDFFCOTUtils update helpers (restores WSFed + IDFF).
  2. Systematic optional-Boolean sweep (Boolean.TRUE.equals(...) or XSD defaults) + a test metadata fixture with optional attributes omitted.
  3. .getValue()-before-null-check sweep.
  4. WSSPolicyManager, PP containers, SMDiscoEntryData, console CCEs (ImportEntityModelImpl, SAMLv2ModelImpl).
  5. clientsdk shade config + jaxb1-impl removal.

Resolves the runtime defects found reviewing the JAXB1->JAXB3 migration:
- WSFederation/IDFF metadata helpers: unwrap AttributeElement/JAXBElement
  lists (ClassCastException) and compare element value names, not QNames
- SAML2/WSFed/IDFF: guard optional Boolean metadata attributes with
  Boolean.TRUE.equals(...) (absent attribute is false, not an NPE) on the
  core SSO, artifact, logout and query paths
- KeyUtil/SAML2MetaSecurityUtils/SAML2ProviderManager and ~12 other sites:
  null-check JAXB elements before getValue() so designed null/fallback
  paths run instead of throwing
- Liberty PP, WS-Policy and Disco: marshal element wrappers (not bare
  types) so KeyInfo/Policy/Directive content serialises
- Console: fix entity-import CCEs, XACML PEP/PDP casts, key-size read and
  extended-config auto-creation
- clientsdk shade: correct jakarta.xml.bind-api coordinate and add the
  jaxb-runtime transitive stack
- Build cleanup: drop leftover jaxb1-impl, dead bgm.ser/jaxb.properties,
  jaxb1 THIRD-PARTY entries and jaxb1.version; move wsfed Adapter1 out of
  the split org.w3._2001.xmlschema package
- Add sp-metadata-no-optional-booleans.xml + SAML2MetaUtilsTest coverage
  pinning the nullable-Boolean generated shape
@vharseko

Copy link
Copy Markdown
Member

Fixes pushed — a18c3c1 (addresses the review findings above)

All blocking bugs, risks, and cleanups from the review are now fixed on this branch. Summary mapped to the findings, with verification at the end.

Blocking bugs — fixed

WS-Federation (was broken entirely)

  • WSFederationMetaUtils.getAttributes — unwrap AttributeElement before use (was (AttributeType) cast → CCE).
  • WSFederationMetaUtils.getAttribute — compare avp.getValue().getName() (was JAXBElement.getName() QName, always ≠ String key).

IDFF (was broken entirely)

  • IDFFMetaUtils.getAttributes — unwrap AttributeElement (CCE).
  • IDFFCOTUtils.updateCOTAttrInConfig / removeCOTNameFromConfig — unwrap descriptor-config JAXBElements (handling both the wrapped SP/IDP lists and the unwrapped affiliation entry), unwrap AttributeElement, and add new attributes via createAttributeElement.
  • federation/key/KeyUtil.getKeyDescriptor — null-safe getUse(), and return null instead of noUsageKD.getValue() when there is no match.
  • IDFFProviderManager / LibertyManager / EncryptedNameIdentifier — null-check the config element before getValue() so the IDP fallback runs (was NPE for IDP-only entities).

SAML2 — optional-Boolean unboxing (highest-impact class)
Absent optional attributes are now treated as false via Boolean.TRUE.equals(...) instead of NPE-ing on the nullable Boolean: IDPSSOUtil (ACS isIsDefault, isWantAssertionsSigned), SPSSOFederate, SAML2Utils.verifyResponse, IDPArtifactResolution, UtilProxySAMLAuthenticator, IDPProxyUtil, SPACSUtils, QueryClient, QueryHandlerServlet, AttributeQueryUtil (isSupportsX509Query), and every isHosted() site in SAML2MetaManager / SAML2MetaSecurityUtils / IDFFMetaManager / IDFFMetaSecurityUtils / WSFederationMetaManager / cli ImportMetaData.

SAML2 — other

  • AttributeQueryUtil.isSameAttributesupported.getValue().getName() (was String.equals(QName), always false).
  • SAML2MetaSecurityUtils.setExtendedAttributeValue — unwrap AttributeElement in the removal loop (CCE); updateProviderKeyInformation — null-check role config/descriptor before getValue() so entityNotIDP/entityNotSP fires.
  • SAML2ProviderManager — restored the SP→IDP fallback via a null-safe unwrap in all four methods.

Liberty PP / Discovery / WS-Policy

  • WSSPolicyManager — pass createOperatorContentType() (was anonymous-type PolicyElementMarshalException).
  • IDPPEncryptKey / IDPPSignKey — add createX509DataElement(...) wrapper to KeyInfo (was bare X509DataTypeMarshalException).
  • IDPPLegalIdentity((AltIDElement)…).getValue() (CCE) and add AltID only when non-null.
  • IDPPDemographics / IDPPBaseContainer.getAttributeMap — unwrap JAXBElement list members so Language values survive; also fixed the pre-existing DSTURI loop-var typo.
  • SMDiscoEntryData — put the directive element wrappers into getAny() so the round-trip and read-path instanceof checks work.
  • DiscoveryService — null-safe getEncryptedResourceID().

Console

  • ImportEntityModelImpl — unwrap JAXBElement<BaseConfigType> on hosted-entity import (SAMLv2 + WSFed CCE).
  • SAMLv2ModelImpl — unwrap AttributeElement on the XACML PEP/PDP pages (CCE); replace getClass().getName().contains("KeySizeImpl") with instanceof EncryptionMethodType.KeySize; null-check configs so invalid.entity.name is reachable; Boolean.TRUE.equals(...) on the remaining nullable-Boolean reads.
  • IDFFModelImpl — null-check descriptor/affiliation configs so first-time tabs auto-create the extended config instead of NPE.
  • SAMLv2SPServicesViewBean — render isDefault as false (not "null") when absent.

Build / packaging

  • openam-clientsdk shade — corrected jakarta.xml.bind:jakarta.xml.bind-api and added the jaxb-runtime transitive stack (jaxb-core, istack-commons-runtime, txw2, jakarta.activation-api).
  • Removed leftover com.sun.xml.bind:jaxb1-impl from the wsfederation-schema pom, and migrated SAML2ProxyTest off com.sun.xml.bind.StringInputStream to ByteArrayInputStream.

Risks / cleanups — done

  • Swept the .getValue()-before-null-check pattern across SAML2Utils, SPACSUtils, IDPSessionListener, NameIDMapping, DoManageNameID, AssertionIDRequestUtil, ValidRelayStateExtractor, multiprotocol handlers, DefaultAttributeMapper, ValidWReplyExtractor (null-safe unwrap).
  • BaseConfigType anonymous subclasses → ObjectFactory.createBaseConfigType().
  • Split-package org.w3._2001.xmlschema.Adapter1 in the wsfed jar fixed via a new schema.xsd package binding (verified by regenerating: Adapter1 now lands in com.sun.identity.wsfederation.jaxb.schema, no org.w3._2001.xmlschema classes, compiles clean).
  • FAMClassLoader mask/load lists made jakarta/glassfish-consistent.
  • Deleted dead JAXB1 cruft: 41 bgm.ser, 3 orphan jaxb.properties, jaxb1-impl entries in THIRD-PARTY.properties, <jaxb1.version> in the root pom, and the com.sun.xml.bind.util.* whitelist entries in IOUtils / serverdefaults.properties.
  • PPRequestHandler — dropped the junk import and used a single Marshaller instance so the prefix mapper applies; ConfigureGoogleApps null-guard; CreateWSFedMetaDataTemplate uses the computed ssneUri; normalized jaxb.properties.

New test coverage

sp-metadata-no-optional-booleans.xml + SAML2MetaUtilsTest.optionalBooleanAttributesUnmarshalAsNull pins the JAXB 3 generated shape (isIsDefault()/isWantAssertionsSigned()/isAuthnRequestsSigned() return null when the attribute is absent) — the class of regression the existing fixtures did not exercise, since they set every optional boolean.

Verification

  • Schema regeneration (JAXB 3) + compile of openam-schema/*, openam-shared, openam-federation-library, OpenFM, openam-console, openam-cli-impl, openam-auth-saml2, openam-clientsdkBUILD SUCCESS on JDK 26.
  • Confirmed the generated IndexedEndpointType.isIsDefault() is a nullable Boolean (the premise of the unboxing bugs).
  • Tests: openam-federation-library 45/45, SAML2ProxyTest 10/10, 0 failures/errors.

Net: 153 files changed (+490 / −336), including the JAXB1 cruft deletions and 2 new files.

@vharseko
vharseko self-requested a review July 14, 2026 12:54
Optional config/metadata getters now return JAXBElement wrappers; several
call sites unwrapped them with a bare .getValue(), throwing NPE on entities
that lack an extended/role config where the pre-migration code degraded
gracefully (null flowed through to a null-tolerant consumer). Add a
null-safe unwrap() helper to SAML2MetaUtils / IDFFMetaUtils and route the
affected sites through it, or guard inline.

HIGH:
- IDPPBaseContainer: unwrap the JAXBElement in the scalar attribute branch
  (mirroring the list branch) so Personal Profile scalar values are no
  longer silently cleared on Modify.
- DiscoveryService.getResourceID: accept and marshal the
  EncryptedResourceIDElement (a JAXBElement) instead of the non-root
  EncryptedResourceIDType, which failed to marshal and misrouted encrypted
  resource-ID lookups to the implied-resource (B2E) path.
- IDFFMetaUtils.getExtendedConfig, SAML2MetaManager (PEP branch guard to
  match the PDP branch), AssertionIDRequestUtil, SPSessionListener,
  AuthnQueryUtil.

MED (unguarded .getValue() on a nullable config getter whose consumer
tolerates null; NPE otherwise escaped an IDFFMetaException-only catch):
- IDPSingleLogout, IDPSessionListener, SPSingleLogout (idpConfig is null
  for all non-SOAP bindings), QueryClient, FSLoginHelper, FSServiceManager,
  FSAttributeStatementHelper, FSPreLogin, FSReturnLogoutServlet,
  FSTerminationReturnServlet, FSPostLogin, FSIDPFinderService,
  FSAssertionManager, FSSingleLogoutHandler.

Cleanup:
- Cache DatatypeFactory in a static field in Time.java.
- Drop the orphaned jaxb.version property and the redundant JAXB version
  pins / commented-out JAXB2 dependency blocks in openam-core.
@vharseko

Copy link
Copy Markdown
Member

Fix round: JAXB3 migration NPE regressions in config/metadata unwrapping (07b3585)

Follow-up on a review of the migration. The recurring issue: optional config/metadata getters now return JAXBElement wrappers, and several call sites unwrapped them with a bare .getValue(). On entities that lack an extended/role config the getter returns null, so .getValue() throws an NPE — where the pre-migration code let null flow through to a null-tolerant consumer. Added a null-safe unwrap() helper to SAML2MetaUtils / IDFFMetaUtils and routed the affected sites through it (or guarded inline). Behaviour-preserving: null → null, no control-flow change.

HIGH

  • IDPPBaseContainer — unwrap the JAXBElement in the scalar attribute branch (the list branch already did). Without it every instanceof DSTString/DSTURI/… missed the *Element wrapper, so Personal Profile scalar values (Gender, DOB, MaritalStatus, …) were silently cleared on Modify.
  • DiscoveryService.getResourceID — accept and marshal the EncryptedResourceIDElement (a JAXBElement) instead of the non-root EncryptedResourceIDType. The raw type has no @XmlRootElement, so marshal threw, was swallowed, returned null, and encrypted resource-ID lookups were misrouted to the implied-resource (B2E) path → wrong principal.
  • IDFFMetaUtils.getExtendedConfig, SAML2MetaManager (PEP branch guarded to match the PDP branch), AssertionIDRequestUtil, SPSessionListener, AuthnQueryUtil.

MED (unguarded .getValue() on a nullable config getter; the NPE also escaped an IDFFMetaException-only catch)

  • IDPSingleLogout, IDPSessionListener, SPSingleLogout (note: idpConfig is null for all non-SOAP bindings), QueryClient, FSLoginHelper, FSServiceManager, FSAttributeStatementHelper, FSPreLogin, FSReturnLogoutServlet, FSTerminationReturnServlet, FSPostLogin, FSIDPFinderService, FSAssertionManager, FSSingleLogoutHandler.

Cleanup

  • Cache DatatypeFactory in a static field in Time.java.
  • Drop the orphaned jaxb.version property and the redundant JAXB version pins / commented-out JAXB2 dependency blocks in openam-core.

Verified: openam-shared + openam-federation-library compile cleanly (863 source files, no errors).

Not changed (deliberate):

  • LOW hosted-entity self-lookups where the config is practically always present or the NPE is absorbed by a catch(Exception) (registration/termination servlets, FSAccountManager, FSSOAPReceiver, DefaultFedletAdapter, DefaultAccountMapper, wsfederation plugins where the pre-migration code dereferenced the same nullable config identically — not migration regressions).
  • openam-wsfederation-schema has no <schemaIncludes> (globs every xsd in src/main/xsd, including import-only schemas) and the openam-xacml3-schema regeneration profile is still pinned to com.sun.xml.bind:jaxb-xjc:2.1.10 (would re-emit javax.* imports). Left as-is pending a CI build to confirm the generated class set before touching working codegen.
  • IOUtils deserialization whitelist (dropped com.sun.xml.bind.util.ListImpl/ProxyListImpl) — fail-closed; verify no rolling-upgrade session relies on them.

vharseko added 2 commits July 14, 2026 18:52
Creating the factory in a static initializer ran it on every Time
class-load, which nearly all code paths (and test setup) trigger; on a
classpath with an older javax.xml.datatype JAXP jar this threw
IllegalAccessError (FactoryFinder -> jdk.xml.internal.SecuritySupport),
failing 91 openam-core tests. Move it to a lazy holder so it initializes
only on first getXMLGregorianCalendarInstance use, off the class-init path.
Under JAXB3 several generated element classes are JAXBElement wrappers
rather than their value types, and top-level types lack @XmlRootElement.
Fix the call sites that still assumed the JAXB1 shape:

- IDPPBaseContainer.toXMLDocument: wrap PPType via ObjectFactory.createPP
  before marshalling (PPType has no @XmlRootElement) so Personal Profile
  containers render instead of throwing MarshalException.
- PPRequestHandler: unwrap Resource/EncryptedResourceID elements before
  DSTRequestHandler.getResourceID so IDPP Query/Modify are not rejected
  with NO_RESOURCE.
- IDPP container getXxxMap helpers (CommonName, Demographics,
  EmploymentIdentity, LegalIdentity, VAT): unwrap the top-level container
  element so whole-container Modify applies instead of "invalid Element".
- Discovery authorization (DiscoUtils lookup, DiscoveryService insert and
  remove): pass ResourceOfferingType (and unwrap DiscoEntryElement on the
  remove path) so DefaultDiscoAuthorizer authorizes policy-protected calls.
- IDFFMetaSecurityUtils: unwrap AttributeElement before reading AttributeType
  so certificate-alias updates don't throw ClassCastException.
- IDPPLegalIdentity: unwrap IDValueElement before casting to DSTString for
  AltID/VAT IDValue updates.
@vharseko

Copy link
Copy Markdown
Member

Fix round: unwrap JAXB3 element wrappers in Liberty IDPP & Discovery flows (89062d3)

Addresses the reported P1/P2 regressions where JAXB1 call sites relied on generated element classes being their value types. Under JAXB3 those are JAXBElement wrappers (and top-level types lack @XmlRootElement), breaking core Liberty Personal Profile and policy-enabled Discovery at runtime. Fixed the consuming call sites (the wrappers themselves are correct; we unwrap at the boundary with the older API). Verified each against the generated sources; openam-federation-library compiles (863 files).

P1

  • IDPPBaseContainer.toXMLDocumentgetContainerObject() returns a bare PPType, which has no @XmlRootElement (root is ObjectFactory.createPP(PPType)JAXBElement<PPType>). Now wrapped via createPP(...) before marshalling, so PP containers render instead of throwing MarshalException. Centralized fix covers every container.
  • PPRequestHandler (Query + Modify) — getResourceID() / getEncryptedResourceID() now return *Element wrappers; DSTRequestHandler.getResourceID() only knows *Type. Unwrap before the call so IDPP requests are not rejected with NO_RESOURCE.
  • IDPP getXxxMap helpers (CommonName, Demographics, EmploymentIdentity, LegalIdentity, VAT) — the Modify dispatch passes *Element; the helpers test instanceof *Type. Unwrap the top-level container element so whole-container Modify applies instead of throwing invalid Element. (IDPPFacade already consumed the element form — left as-is.)
  • Discovery authorizationInsertEntryType.getResourceOffering() now returns ResourceOfferingElement, but DefaultDiscoAuthorizer casts data to ResourceOfferingType. Pass .getValue() at all three isAuthorized(...) sites: DiscoUtils (lookup) and DiscoveryService insert/remove. DiscoUtils's marshalling call (convertJAXBToElement) still receives the element and is intentionally unchanged.

P2

  • DiscoveryService.isUpdateAllowed (remove path)getDiscoEntries() returns Map<…, DiscoEntryElement>; the code cast to InsertEntryType. Now ((DiscoEntryElement) …).getValue().getResourceOffering().getValue(), fixing a ClassCastException.
  • IDFFMetaSecurityUtils.setExtendedAttributeValueconfig.getAttribute() is List<AttributeElement> (extends JAXBElement<AttributeType>); unwrap before reading AttributeType so certificate-alias updates do not ClassCastException.
  • IDPPLegalIdentity.getDataMapForSelectIDValueElement extends JAXBElement<DSTString>; unwrap before the DSTString cast for AltID/VAT IDValue updates.

9 files, +38/−7. (Also, the previous Time fix that was failing CI is now green.)

vharseko added 2 commits July 15, 2026 10:05
Resolve conflicts from master:
- 1206 generated JAXB sources under openam-schema that master touched with a
  copyright bump: kept deleted (generated at build time now).
- 12 copyright-header conflicts: take master's canonical
  "Portions Copyrighted 2026 3A Systems, LLC" form, preserving our code.
- openam-schema: skip the Javadoc jar for the generated schema modules, since
  master's new doclint (all,-missing) + failOnWarnings policy (OpenIdentityPlatform#1070) fails on
  XJC-generated Javadoc (e.g. {@link byte[]}).
…te-2026-05-19

# Conflicts:
#	openam-entitlements/src/test/java/com/sun/identity/entitlement/xacml3/XACMLPrivilegeUtilsTest.java

@vharseko vharseko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — JAXB3 Migration

Scope: full diff vs merge base 1e507b28 (2,839 files, +4,718/−541,137). All 2,487 deleted files verified to be checked-in JAXB1-generated sources (plus bgm.ser/jaxb.properties artifacts and vendored com.sun.xml.bind stubs). All 287 hand-modified non-generated files were reviewed individually; the 55 XACML3 edits are purely mechanical javaxjakarta rewrites. The PR head was also compile-verified locally (federation library, OpenFM, console, entitlements — BUILD SUCCESS), and several findings below were reproduced empirically against the built generated model + jaxb-runtime 3.0.2.

The overall approach is right: build-time generation removes ~541K lines of unauditable checked-in code, and the xjb customizations faithfully restore the JAXB1-era class surface (*Element classes, Calendar for xs:dateTime, String for xs:anyURI) — no name/namespace/type drift found. The remaining bugs cluster in four recurring patterns: unwrapping JAXBElement too early before helpers that still expect wrappers, instanceof checks on lax-any content, unguarded .getValue() on absent extended config, and xs:anyType values now being DOM nodes instead of strings.

High severity (confirmed — should block merge)

1–2. SAML2 session-sync single logout throws ClassCastException on both sides.
IDPSessionListener.java:305-307 and SPSessionListener.java:246-248 unwrap the SLO list to List<EndpointType> via .map(JAXBElement::getValue) and pass it to LogoutUtil.getSLOServiceLocation, which still casts each item to SingleLogoutServiceElement and calls .getValue() (LogoutUtil.java:652-654). Any session timeout/destroy with session-sync enabled and a peer that has an SLO endpoint in metadata → CCE, sync logout never sent. Fix: don't unwrap — pass the element list like the other getSLOServiceLocation callers do.

3. WS-Fed token signature verification completely broken.
WSFederationMetaManager.java:1369getTokenSigningCertificate checks o1 instanceof X509DataType on SecurityTokenReferenceType.getAny() content, which now unmarshals as X509DataElement extends JAXBElement<X509DataType> (reproduced with the built classes). The check never matches → method returns null → NPE in wsfederation/key/KeyUtil.getCert. Every signed SAML 1.1 token from a remote WS-Fed IdP fails verification. It fails closed (availability break, not a bypass), and the surrounding lines were adapted — this one instanceof was missed.

4. Liberty PP EncryptedResourceID handling throws MarshalException.
PPRequestHandler.java:205-211 (and 486–491) unwrap to raw EncryptedResourceIDType before DSTRequestHandler.getResourceID marshals it directly (DSTRequestHandler.java:200) — the type has no @XmlRootElement, so marshalling throws and every PP Query/Modify with an encrypted resource ID is rejected as invalidResourceID. DiscoveryService handles the same pattern correctly by keeping the element wrapper; PP should do the same.

Medium severity

  • AttributeValue values are now DOM nodes, not strings. Three sites collect JAXBElement.getValue() of the xs:anyType-bound AttributeValueElement, yielding ElementNSImpl (whose toString() is [saml:AttributeValue: null]) where JAXB1's getContent() gave text:

    • SAML2IDPProxyFRImpl.idpAuthnContextFilter (lines 363–377): EntityAttributes-based IdP-proxy filtering silently never matches any IdP.
    • AttributeQueryUtil.convertAttributes (lines 879–890): CCE in AttributeImpl.setAttributeValueString when an AttributeQuery relies on AA metadata attributes.
    • AttributeQueryUtil.isValueValid (lines 1022–1036): valid requested values are now always rejected with INVALID_ATTR_NAME_OR_VALUE.

    All three need a text-extraction helper (e.g. DOM getTextContent()).

  • PP Modify flows reject valid requests. Lax-any content of NewData unmarshals as plain JAXBElement for PP global elements that have no element-class customization, so instanceof AnalyzedNameType in IDPPBaseContainer.getAnalyzedNameMap (line 437, used by IDPPCommonName/IDPPLegalIdentity) and instanceof DSTString in IDPPAddressCard (line 359 — Nick, PostalAddress, L, St, C, PostalCode, …) can never match → invalidElement on every such modify. Sibling methods (getAttributeMap, getCommonNameMap) got unwraps; these two were missed.

  • NPE regressions on absent extended entity config where the old code tolerated null: SPSessionListener.java:262 (masked today by finding 1–2), SAML2SingleLogoutHandler.java:360 (the NPE escapes the per-SP catch and aborts logout for all remaining SPs), FSServiceManager.java:713-719 (name-registration handler becomes null for remote providers without extended config).

Low severity

  • NameIDMapping.java:475-477, FSAssertionManager.java:495-496, FSIDPFinderService.java:247: NPE instead of the old graceful SAML2Exception/null-tolerant path when descriptors/config are absent.
  • FSAccountManager.java:93,97: missing-hosted-config error degrades to FSAccountMgmtException("null") — the explicit NULL_HOSTED_CONFIG guard below is now dead code.
  • WSFedPropertiesModelImpl.setGenAttributeValues (388–391): console save replaces the TokenIssuerName value object, dropping any extensible attributes on it.
  • FAMClassLoader masks jakarta.xml.bind./org.glassfish.jaxb. from parent delegation but its hardcoded jar list contains no jakarta JAXB jars → CNFE on the legacy WSS STS path (that jar list was already stale pre-migration).
  • IDPPBaseContainer.getDSTMonthDay now parses via DatatypeFactory: values not in --MM-DD lexical form are silently dropped where they previously passed through raw.

Verified non-issues (checked, no action needed)

  • instanceof *Element on lax-any content works for all xjb-customized element classes (glassfish RI instantiates them); verified for FederationElement, TokenSigningKeyInfoElement, descriptor/config elements, EncryptionMethodType.KeySize, etc.
  • Boolean.TRUE.equals(...isHosted()/isWantAuthnRequestsSigned()/...) preserves JAXB1 absent→false semantics (no schema defaults involved), locked in by the new sp-metadata-no-optional-booleans.xml test.
  • new BaseConfigType() {} anonymous subclasses marshal correctly under jaxb-runtime 3.0.2 (empirically tested; fragile only if the runtime is ever swapped). The BaseConfigType abstract="true"→"false" XSD change is required and marshalling-neutral.
  • All rewritten jaxb.properties point at org.glassfish.jaxb.runtime.v2.ContextFactory; all bgm.ser deleted; deserialization-whitelist removal of com.sun.xml.bind.util.ListImpl/ProxyListImpl is consistent with the classes no longer existing.
  • The failing CodeQL check is noise: every alert points at files this PR never touches (vendored YUI JS, workflow YAML, idp-discovery servlets), flagged only because the diff exceeded CodeQL's 300-file window — its own summary says as much.

Test coverage

New targeted tests are good (SAML2MetaUtilsTest round-trips, optional-boolean metadata, SLO locations, REST-STS e2e), and CI runs the full suite on nine JDK/OS combos. But every bug above lives in an untested flow: session-sync SLO listeners, WS-Fed token certificate extraction, PP Modify variants, AttributeQuery against AA metadata. Cheap unit tests around LogoutUtil.getSLOServiceLocation and getTokenSigningCertificate would have caught the two worst ones.

Build note

Local reactor builds of the PR fail at jato-shaded because org.openidentityplatform.external.com.iplanet.jato:jato-shaded:16.2.0-SNAPSHOT isn't published; installing a local copy under that version unblocks it. Pre-existing infra issue, not caused by this PR, but it will bite anyone building the branch locally.

…ert lookup, PP EncryptedResourceID and null-guard regressions

- LogoutUtil: accept both SingleLogoutServiceElement wrappers and unwrapped
  EndpointType items in getSLOServiceLocation/getSLOResponseServiceLocation
  (fixes session-sync SLO ClassCastException in IDP/SP session listeners)
- WSFederationMetaUtils.findTokenSigningCertificate: unwrap X509DataElement
  in lax any content so remote WS-Fed IdP token signature verification works
- DSTRequestHandler: marshal EncryptedResourceIDType via its element wrapper
  (raw type has no @XmlRootElement) — fixes PP Query/Modify with encrypted
  resource IDs
- SAML2Utils.getAttributeValueString: extract text from anyType-bound
  AttributeValue payloads (DOM nodes after JAXB3); use in SAML2IDPProxyFRImpl
  and AttributeQueryUtil
- IDPPBaseContainer/IDPPAddressCard: unwrap JAXBElement for PP elements
  without generated element classes (AnalyzedName, address-card leaves)
- Null-guard absent extended entity config: SPSessionListener,
  SAML2SingleLogoutHandler, FSServiceManager, FSAssertionManager,
  FSIDPFinderService, FSAccountManager, NameIDMapping
- WSFedPropertiesModelImpl: mutate TokenIssuerName value in place to keep
  extensible attributes
- FAMClassLoader: restore javax/com.sun.xml.bind masks (provided by bundled
  Metro jars); let jakarta JAXB delegate to the webapp classloader
- IDPPBaseContainer.getDSTMonthDay: accept legacy MM-DD directory values
- Tests: SLO location lookups for both list shapes, WS-Fed token certificate
  round-trip, AttributeValue text extraction, EncryptedResourceID marshalling
@vharseko

Copy link
Copy Markdown
Member

Fix report for the review findings

All findings from the review above — high, medium and low — are addressed in d020a36 (22 files, +388/−78).

High severity

  • SAML2 session-sync SLO ClassCastExceptionLogoutUtil.getSLOServiceLocation and getSLOResponseServiceLocation now normalize each list item via a toEndpointType helper, accepting both the SingleLogoutServiceElement wrappers (all metadata callers) and the unwrapped EndpointType items that IDPSessionListener/SPSessionListener must pass to doLogout. The listeners themselves are unchanged apart from a null guard.
  • WS-Fed token signature verification — the certificate extraction now unwraps X509DataElement in the lax any content (previous instanceof X509DataType could never match). The logic moved to a static WSFederationMetaUtils.findTokenSigningCertificate, with WSFederationMetaManager.getTokenSigningCertificate delegating to it, so it is testable without a configured meta manager.
  • Liberty PP EncryptedResourceID MarshalExceptionDSTRequestHandler.getResourceID marshals the type through createEncryptedResourceIDElement(...) instead of the bare EncryptedResourceIDType (no @XmlRootElement). Fixing the shared callee covers both the PP Query and Modify paths.

Medium severity

  • AttributeValue DOM payloads — new helper SAML2Utils.getAttributeValueString(Object) unwraps JAXBElements and extracts Node.getTextContent() from the xs:anyType-bound payloads (plain Strings pass through). Applied at all three broken sites: SAML2IDPProxyFRImpl.idpAuthnContextFilter, AttributeQueryUtil.convertAttributes, AttributeQueryUtil.isValueValid.
  • PP Modify rejectionsIDPPBaseContainer.getAnalyzedNameMap and the IDPPAddressCard leaf branch (Nick, PostalAddress, L, St, C, PostalCode, LComment) now unwrap the JAXBElement before the instanceof checks, matching the pattern the migration already used in getAttributeMap/getCommonNameMap. The AddressCardElement/AddressElement branches are untouched (those have generated element classes and must stay wrapped).
  • NPE on absent extended entity config — null guards restored in SPSessionListener, SAML2SingleLogoutHandler (an NPE there escaped the per-SP catch and aborted logout for all remaining SPs) and FSServiceManager.getNameRegistrationHandler.

Low severity

  • Null guards restoring the old graceful error paths in NameIDMapping.getEncryptedID, FSAssertionManager, FSIDPFinderService, and FSAccountManager (the explicit NULL_HOSTED_CONFIG error code is reachable again).
  • WSFedPropertiesModelImpl.setGenAttributeValues mutates the existing TokenIssuerName value in place, preserving extensible attributes; the fresh-object path remains as fallback.
  • FAMClassLoader again masks javax.xml.bind./com.sun.xml.bind. (self-supplied by the bundled 2009-era Metro jars) and no longer masks jakarta.xml.bind./org.glassfish.jaxb., which the child jar list cannot provide — jakarta JAXB now delegates to the webapp classloader.
  • IDPPBaseContainer.getDSTMonthDay accepts legacy MM-DD directory values by normalizing them to the --MM-DD gMonthDay lexical form.

Tests added

  • SLOLocationTest — two new tests covering getSLOServiceLocation/getSLOResponseServiceLocation with both the wrapped and the unwrapped list shapes (the exact listener regression).
  • WSFederationMetaUtilsTest (new) — builds Federation metadata with TokenSigningKeyInfo, round-trips it through marshal/unmarshal (producing the X509DataElement wrapper shape seen with real remote metadata) and asserts the certificate bytes are found. Failed before the fix.
  • SAML2UtilsTest — two new tests: text extraction from an unmarshalled EntityAttributes/AttributeValue fragment, and plain/null payload handling.
  • DiscoUtilsTest (new) — locks in that EncryptedResourceID marshals via the element wrapper with the expected qualified name.

Verification

  • Full openam-federation-library test suite: 51/51 pass.
  • openam-federation-library, OpenFM, openam-console, openam-entitlements all compile against the change.

One note for anyone building this branch locally: Maven's --update-snapshots (used by CI-style invocations) pulls pre-migration 16.2.0-SNAPSHOT artifacts from the remote snapshot repository over locally built migrated ones, which produces confusing "interface has no getValue()" compile errors. Build with -nsu after installing the branch's schema modules, or bump the branch version, to avoid the clash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

help wanted needs testing refactoring Code cleanup, refactor, dead-code or dependency removal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenAM has doubled in size since version 14

2 participants