spring-attic / spring-security-saml

SAML extension for the Spring Security project
Other
419 stars 482 forks source link

LogoutRequest: Error. "The requested NameID is invalid" #458

Closed walgarcia closed 4 years ago

walgarcia commented 4 years ago

The idp (an ADSF) sends the folowing LogoutRequest

<samlp:LogoutRequest ID="_3cc87400-d8b8-4cf7-8a7f-xxxxxx"
                     Version="2.0"
                     IssueInstant="2019-10-01T14:16:36.623Z"
                     Destination="https://localhost:8443/saml/SingleLogout"
                     NotOnOrAfter="2019-10-01T15:16:36.623Z"
                     xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                     >
    <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.windows.net/fabd047c-ff48-492a-xxxx/</Issuer>
    <NameID xmlns="urn:oasis:names:tc:SAML:2.0:assertion">walgxxx@xxx.edu.co</NameID>
    <samlp:SessionIndex>_9cb38a17-bae8-4d60-9bcf-xxxxx</samlp:SessionIndex>
</samlp:LogoutRequest>

The following error is reported by the logout request processor:

2019-10-01 09:16:36.955 DEBUG --- [nio-8443-exec-6] org.springframework.security.saml.util.SAMLUtil                                                      : Found endpoint org.opensaml.saml2.metadata.impl.SingleLogoutServiceImpl@16196d0d for request URL https://localhost:8443/saml/SingleLogout based on location attribute in metadata
2019-10-01 09:16:36.955 DEBUG --- [nio-8443-exec-6] org.springframework.security.saml.SAMLLogoutProcessingFilter                                         : Received logout request is invalid, responding with error

org.springframework.security.saml.SAMLStatusException: **The requested NameID is invalid**
    at org.springframework.security.saml.websso.SingleLogoutProfileImpl.processLogoutRequest(SingleLogoutProfileImpl.java:204)
    at org.springframework.security.saml.SAMLLogoutProcessingFilter.processLogout(SAMLLogoutProcessingFilter.java:178)
    at org.springframework.security.saml.SAMLLogoutProcessingFilter.doFilter(SAMLLogoutProcessingFilter.java:104)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.saml.SAMLLogoutFilter.processLogout(SAMLLogoutFilter.java:164)
    at org.springframework.security.saml.SAMLLogoutFilter.doFilter(SAMLLogoutFilter.java:106)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.saml.metadata.MetadataDisplayFilter.doFilter(MetadataDisplayFilter.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.saml.SAMLEntryPoint.doFilter(SAMLEntryPoint.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at grails.plugin.springsecurity.web.SecurityRequestHolderFilter.doFilter(SecurityRequestHolderFilter.groovy:58)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    ...
    at java.lang.Thread.run(Thread.java:748)

the sp.xml contains

     ...
      <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
      <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
      <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
      <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
      <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>
      ...

Is this an issue when working with an ADSF idp ? Is the idp obliged to describe the format of the NameID ?

fhanik commented 4 years ago

Seems to be a logical flow, and probably not a bug. Reopen this issue if you do believe it is a bug.

You will want to set a break point at NameID nameID = getNameID(context, logoutRequest);

https://github.com/spring-projects/spring-security-saml/blob/4e9932d52f01d06f5fd3d6eb2998073450f02213/core/src/main/java/org/springframework/security/saml/websso/SingleLogoutProfileImpl.java#L209

walgarcia commented 4 years ago

I found context and credential nameID differ in the format field, due to idps saml message. so equalsNameID(credential.getNameID(), nameID) fails.

https://github.com/spring-projects/spring-security-saml/blob/4e9932d52f01d06f5fd3d6eb2998073450f02213/core/src/main/java/org/springframework/security/saml/websso/SingleLogoutProfileImpl.java#L210

2019-10-01 12:53:01.535 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : context     nameID: object   org.opensaml.saml2.core.impl.NameIDImpl@43493cab
2019-10-01 12:53:01.535 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : context     nameID: value()  walgxxx@xxx.edu.co
2019-10-01 12:53:01.535 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : context     nameID: format() null
2019-10-01 12:53:01.537 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : context     nameID: nameq()  null
2019-10-01 12:53:01.537 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : context     nameID: spprov() null
2019-10-01 12:53:01.537 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : context     nameID: spname() null
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : context     nameID: childn() null
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : credentials nameID: object   org.opensaml.saml2.core.impl.NameIDImpl@44afe458
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : credentials nameID: value()  walgxxx@xxx.edu.co
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : credentials nameID: format() walgxxx@xxx.edu.co
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : credentials nameID: nameq()  null
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : credentials nameID: spprov() null
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : credentials nameID: spname() null
2019-10-01 12:53:01.538 TRACE --- [nio-8443-exec-1] o.s.s.s.websso.SingleLogoutProfileImpl   : credentials nameID: childn() null
2019-10-01 12:53:01.539 DEBUG --- [nio-8443-exec-1] o.s.s.saml.SAMLLogoutProcessingFilter    : Received logout request is invalid, responding with error

thanks @fhanik

fhanik commented 4 years ago

You are welcome @walgarcia

ripjal commented 3 years ago

@walgarcia I am facing similar issue with ADSF IDP ?Did you find any solution to this ?

walgarcia commented 3 years ago

@ripjal The solution was to patch the code:

private boolean equalsNameID(NameID a, NameID b) {
    boolean equals = !differ(a.getSPProvidedID(), b.getSPProvidedID());
    equals = equals && !differ(a.getValue(), b.getValue());

    //
    // Azure adsf doesnot include format!!! so skip
    //
    //equals = equals && !differ(a.getFormat(), b.getFormat());

    equals = equals && !differ(a.getNameQualifier(), b.getNameQualifier());
    equals = equals && !differ(a.getSPNameQualifier(), b.getSPNameQualifier());
    equals = equals && !differ(a.getSPProvidedID(), b.getSPProvidedID());
    return equals;
}
ripjal commented 3 years ago

@walgarcia ahh...I was thinking this must be misconfiguration at ADFS side which could be corrected. So I believe you overrode the SingleLogoutProfileIMpl and copied almost all processLogoutRequest method and just commented this one line which is comparing the format.

walgarcia commented 3 years ago

@ripjal I did not have access to the adfs configuration so this was the workarround.