-
Notifications
You must be signed in to change notification settings - Fork 6k
Make name resolution configurable in OpenSamlLogoutRequestValidator #12128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for the report, @palakova. It sounds like there are two things happening here, and I want to see if we can separate them out. First, you are saying that it would be nice to have the entire NameID available, at least so that the construction and validation of LogoutRequests can be customized, which I agree with worth looking at. Since transient is meant to be treated as opaque, I'm not sure that the framework can do better than that. Second, you are asking for a way to provide a name-resolution strategy that is simpler than an entire converter. If so, would you mind placing the second one on a separate ticket? Or if I haven't understood, would you help clarify your request? |
Hi @jzheaux I also meet similar issues as @palakova when I was previously integrating SAML provider. It's great that I found this discussion. Both former Spring SAML extension and Shibboleth SAML SP implementation will attempt to save NameID in the current session and later use it for logout. I workaround by subclassing public class MySaml2AuthenticatedPrincipal extends DefaultSaml2AuthenticatedPrincipal {
public NameID getNameID() {
return nameID;
}
private final NameID nameID; // the app support only NameID
// in the early version, sessionIndexes are also saved here
public MySaml2AuthenticatedPrincipal(NameID nameID, Map<String, List<Object>> attributes, List<String> sessionIndexes) {
super(nameID.getValue(), attributes, sessionIndexes);
this.nameID = nameID;
}
}
public class MySaml2Util {
public static Converter<OpenSaml4AuthenticationProvider.ResponseToken, Saml2Authentication> createMyResponseAuthenticationConverter() {
return (responseToken) -> {
Response response = responseToken.getResponse();
Saml2AuthenticationToken token = responseToken.getToken();
Assertion assertion = CollectionUtils.firstElement(response.getAssertions());
RelyingPartyRegistration relyingPartyRegistration = token.getRelyingPartyRegistration();
// add here
NameID nameId = assertion.getSubject().getNameID(); // be aware of NPE
Map<String, List<Object>> attributes = getAssertionAttributes(assertion); // copied from OpenSaml4AuthenticationProvider
List<String> sessionIndexes = getSessionIndexes(assertion); // copied from OpenSaml4AuthenticationProvider
DefaultSaml2AuthenticatedPrincipal principal = new MySaml2AuthenticatedPrincipal(nameId, attributes, sessionIndexes);
principal.setRelyingPartyRegistrationId(relyingPartyRegistration.getRegistrationId());
// customization codes
// ...
return new Saml2Authentication(principal, token.getSaml2Response(),
AuthorityUtils.createAuthorityList("ROLE_USER"));
};
}
public static Consumer<LogoutRequestParameters> createMyLogoutRequestResolverParametersConsumer() {
return (parameters) -> {
//...
LogoutRequest logoutRequest = parameters.getLogoutRequest();
MySaml2AuthenticatedPrincipal principal = (MySaml2AuthenticatedPrincipal)parameters.getAuthentication().getPrincipal(); // be aware of exception
NameID nameID = logoutRequest.getNameID();
NameID principalNameID = principal.getNameID();
//...
// be aware of NPE...
nameID.setFormat(principalNameID.getFormat());
nameID.setFormat(principalNameID.getFormat());
nameID.setNameQualifier(principalNameID.getNameQualifier());
nameID.setSPNameQualifier(principalNameID.getSPNameQualifier());
nameID.setSPProvidedID(principalNameID.getSPProvidedID());
nameID.setValue(principalNameID.getValue());
// in the early version, sessionIndexes are also handled here
};
}
} My thoughts:
|
I came across this as well with inbound single logout requests when using a different principal than the incoming NameID value. Customizing logout request resolver parameter consumer allows changing the NameID fine. With inbound logout requests, This would be better if The #12136 issue focuses more on authentication responses, while this one has focused more on the inbound logout requests but I would like a better way to resolve the NameID here like with the logout request resolvers. |
Describe the bug
Spring SAML considers NameID to hold username, populates
Saml2AuthenticatedPrincipal#name
with NameID value and later in Single Logout flow again populates/validates NameID value using Principal Name. This behaviour breaks our current integrations.Username can be released by IdP in one of Assertion’s Attribute element instead. NameID, if present (as it is even optional, as also discussed in #11463), can be of different Format, holding different kind of values.
One example for all: According to SAML spec, NameID Format
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
indicates that the content of the element is an identifier with transient semantics and SHOULD be treated as an opaque and temporary value by the relying party. This NameID element is also sent by IdP in LogoutRequest (causing validation against Principal Name inOpenSamlLogoutRequestValidator#validateNameId
to fail) and is expected to be present in LogoutRequest sent from relying party (where it is populated with Principal Name in OpenSamlLogoutRequestResolver, making the IdP refuse the request).Our workarounds:
To Reproduce
Reproduced when integrating with Shibboleth IdP, which uses transient NameID and an Attribute to release username.
Expected behavior
Whole NameID element could be stored in DefaultSaml2AuthenticatedPrincipal (similar as session indexes are stored already) during login. It would be used to construct NameID element in outbound LogoutRequest, and it’s value would be used for validation when handling inbound LogoutRequest.
Ideally could you consider also to configure where to retrieve the username from in the first place (NameID element versus providing a Name of an Assertion Attribute)?
The text was updated successfully, but these errors were encountered: