spring-projects/spring-security · error · Saml2AuthenticationException
subject_not_found
subject_not_found
Error message
Assertion [" + assertion.getID() + "] is missing a subject
What it means
During authentication, OpenSaml5AuthenticationProvider builds the authenticated principal from the Assertion's Subject. If the assertion carries no Subject/NameID (hasName returns false), it throws a Saml2AuthenticationException with the subjectNotFound error code rather than producing an Authentication, because Spring Security's SAML login requires a subject identity.
Source
Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml5AuthenticationProvider.java:947
Assert.notNull(principalNameConverter, "principalNameConverter cannot be null");
this.principalNameConverter = principalNameConverter;
}
/**
* Use this strategy to grant authorities to a principal given the first
* {@link Assertion} in the response. By default, this will grant
* {@code ROLE_USER}.
* @param grantedAuthoritiesConverter the conversion strategy to use
*/
public void setGrantedAuthoritiesConverter(
Converter<Assertion, Collection<GrantedAuthority>> grantedAuthoritiesConverter) {
Assert.notNull(grantedAuthoritiesConverter, "grantedAuthoritiesConverter cannot be null");
this.grantedAuthoritiesConverter = grantedAuthoritiesConverter;
}
private static String authenticatedPrincipal(Assertion assertion) {
if (!BaseOpenSamlAuthenticationProvider.hasName(assertion)) {
throw new Saml2AuthenticationException(
Saml2Error.subjectNotFound("Assertion [" + assertion.getID() + "] is missing a subject"));
}
Subject subject = assertion.getSubject();
Assert.notNull(subject, "Assertion#Subject cannot be null");
NameID nameId = subject.getNameID();
Assert.notNull(nameId, "Assertion#Subject#NameID cannot be null");
return Objects.requireNonNull(nameId.getValue());
}
private static Collection<GrantedAuthority> grantedAuthorities(Assertion assertion) {
return AuthorityUtils.createAuthorityList("ROLE_USER");
}
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Configure the IdP to release a NameID (or an attribute mapped as principal) for this SP — check NameID format and attribute release policies.
- Ensure your SP metadata requests a NameIDFormat the IdP supports (e.g. emailAddress or persistent).
- If you legitimately use subject-less assertions, set a custom responseAuthenticationConverter / assertion validator that does not require a Subject.
- Verify the assertion you are validating is the intended login assertion, not an auxiliary one.
Example fix
// before: IdP omits NameID -> assertion has no Subject
// after: request a supported format in SP metadata
RelyingPartyRegistration.withRegistrationId("idp")
.nameIdFormat(NameIDFormat.EMAIL)
... // IdP then emits <saml2:NameID> and the Subject element Defensive patterns
Strategy: try-catch
Validate before calling
boolean hasSubject = assertion.getSubject() != null
&& assertion.getSubject().getNameID() != null;
if (!hasSubject) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED,
"Assertion " + assertion.getID() + " carries no Subject/NameID");
} Try / catch
try {
Authentication auth = provider.authenticate(token);
} catch (Saml2AuthenticationException ex) {
if (Saml2Error.SUBJECT_NOT_FOUND.equals(ex.getSaml2Error().getCode())) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"IdP released no NameID — check NameID format and attribute release policy");
} else { throw ex; }
} Prevention
- Declare a NameIDFormat in SP metadata that your IdP actually supports.
- Confirm the IdP's attribute release/NameID policy for this SP entityID.
- Integration-test the full SSO round-trip, not just signature validation.
- Inspect assertions in a SAML tracer to see exactly what the IdP emits.
When it happens
Trigger: Validating a signed response whose assertion lacks a <saml2:Subject>/<saml2:NameID> — e.g. attribute-only assertions, assertions used only for authorization, or IdP configured to omit NameID.
Common situations: IdP releases no NameID (misconfigured NameID format or attribute filter suppressing it); SP metadata requests a NameID format the IdP won't provide so it omits the element entirely; using an assertion for logout/attribute flows where the IdP intentionally omits the subject; automated tests constructing assertions without a Subject.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Unable to inflate string
- Unsupported element of type
- Failed to deserialize payload
- Unable to resolve Builder for " + elementName
- Unsupported element of type " + element.getTagName()
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/8c21b8de98bb0645.
Report an issue: GitHub.