SAMLException: NameID element must be present as p

2019-04-09 12:04发布

Iam using spring-saml implementation. In the class WebSSOProfileConsumerImpl, I could find the following lines of code which checks for nameId in the assertion of the SAML response.

NameID nameID;
if (subject.getEncryptedID() != null) {
    Assert.notNull(context.getLocalDecrypter(), "Can't decrypt NameID, no decrypter is set in the context");
    nameID = (NameID) context.getLocalDecrypter().decrypt(subject.getEncryptedID());
} else {
    nameID = subject.getNameID();
}

Based on the code, its clear that the nameId should be part of the subject. But most of the IDP's including the one that I am using mention that nameId could be part of the subject/attribute. Seems that there are a few implementations which accept nameId in subject just like SimpleSAMLPHP.

The subject which I am receiving is as follows and does not have nameId enclosed

<saml2:Subject>
  <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">  
    <saml2:SubjectConfirmationData Address="91.X.X.X" InResponseTo="XXXX" NotOnOrAfter="2014-10-10T10:34:26.619Z" Recipient="http://localhost:8080/XXXX/saml/SSO"/>
  </saml2:SubjectConfirmation>
</saml2:Subject>

However, there is an attribute which has a nameId as its attribute value. Why cant this be used instead of the one in the subject.

<saml2:Attribute FriendlyName="testID" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
  <saml2:AttributeValue>
      <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="https://XXXX/idp/shibboleth" SPNameQualifier="urn:XX:XX:XX">XXXXXXXXXXXXXXXXX=
      </saml2:NameID>
  </saml2:AttributeValue>
</saml2:Attribute>

Can anyone explain the reason behind nameId being part of only subject in spring-saml implementation.

@vschafer Is there a way of customizing the securityContext.xml to choose nameId which is part of a specific attribute and not from subject?

2条回答
beautiful°
2楼-- · 2019-04-09 12:36

Spring SAML currently requires NameID to be present. Changing this would require code changes and cannot be currently done with configuration only. Please feel free to open a feature request for changing this in Spring SAML Jira.

查看更多
神经病院院长
3楼-- · 2019-04-09 12:37

We had a similar scenario with ADFS 3.0. This particular configuration of ADFS didn't supply NameId at all. We implemented a workaround by requesting an UPN claim from ADFS, and then using that as NameId. A pluggable NameIdResolver would be nice though, @vschafer.

Code for workaround if anyone's interested:

public class ClaimConstants {

public static final String UPN = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn";
}

 

public class NameIdWebSSOProfileConsumer extends WebSSOProfileConsumerImpl {

@Override
protected void verifySubject(Subject subject, AuthnRequest request, SAMLMessageContext context) throws SAMLException, DecryptionException {
    super.verifySubject(subject, request, context);

    Response response = (Response) context.getInboundSAMLMessage();
    for (EncryptedAssertion ea : response.getEncryptedAssertions()) {
        Assertion assertion = context.getLocalDecrypter().decrypt(ea);

        for (Statement statement : assertion.getStatements()) {
            if (statement instanceof AttributeStatementImpl) {
                for (Attribute attribute : ((AttributeStatementImpl) statement).getAttributes()) {
                    if (ClaimConstants.UPN.equals(attribute.getName())) {
                        NameID nameId = new NameIDBuilder().buildObject();
                        XSAnyImpl xmlObject = (XSAnyImpl) attribute.getAttributeValues().get(0);
                        nameId.setValue(xmlObject.getTextContent());
                        //noinspection unchecked
                        context.setSubjectNameIdentifier(nameId);
                        return;
                    }
                }
            }
        }
    }
}

And then use in Spring as normal:

<bean id="webSSOprofileConsumer" class="com.example.NameIdWebSSOProfileConsumer"/>
查看更多
登录 后发表回答