Search code examples
asp.net-core-webapisingle-sign-onsaml-2.0itfoxtec-identity-saml2

How do I figure out what my SAML error is being caused by?


I am slowly building a .net core service provider web app using a SAML library called itfoxtec-identity-saml2

I have progressed to the point where I actually can connect to the IdP, but I am getting an error from the IdP that simple says, "Unable to Decode".

In my service provider web app project, when I step through it in Visual Studio, it gets to the AuthController.cs class and the error is thrown by the IdP when this is sent here:

    [Route("Login")]
    public IActionResult Login(string? returnUrl = null)
    {
        var binding = new Saml2RedirectBinding();
        binding.SetRelayStateQuery(new Dictionary<string, string> { { relayStateReturnUrl, returnUrl ?? Url.Content("~/") } });

        return binding.Bind(new Saml2AuthnRequest(config)).ToActionResult();
    }

Is there any other way to help debug this?

Here is all the data I could gather from the browser:

Headers

GET https://singlesignon.lowell.edu/idp/profile/SAML2/POST/SSO?SAMLRequest=fJBBb4MwDIX%2FCso9JCRQIAKkar1U2tRqVDvsMqU0VZEgyWIj7ecvdDuslx3t589%2Bzw3oeRJebRe82VfzuRjA5GueLKgfpSVLsMppGEFZPRtQOKh%2B%2B%2FKsRMqVDw7d4Cbyl%2Fkf0QAm4OgsSfa7lnxIaaoqL6%2B0rHVN87LQtBZc0rOp8nNW8CyvNyR5MwEi05K4IoIAi9lbQG0xtriQlG%2BoqE6ZVEWheJWWMnsnyS6mGa1er7XkhuhBMeajA%2B8Cpn5ETM1lYePFs5jkOk6GrT4FOx76E%2Bv7A%2BmaeyR1vxi6Y0TWiSdnrRnQhYY96L%2Fl4z%2B7bwAAAP%2F%2FAwA%3D&RelayState=ReturnUrl%3D%252F HTTP/1.1
sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://localhost:7133/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: shib_idp_session=dcefe3bd1b8e866da71b733a98a96a49ccb9d15f1481a74ba447757dcf86a7cf; JSESSIONID=D9B5D82C717EF64AE5D4AED9446A1042

HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Cache-Control: no-store
Content-Type: text/html;charset=utf-8
Content-Length: 1655
Date: Wed, 28 Jun 2023 13:59:31 GMT
Connection: close

Payload

SAMLRequest: fJBBb4MwDIX/Cso9JCRQIAKkar1U2tRqVDvsMqU0VZEgyWIj7ecvdDuslx3t589+zw3oeRJebRe82VfzuRjA5GueLKgfpSVLsMppGEFZPRtQOKh++/KsRMqVDw7d4Cbyl/kf0QAm4OgsSfa7lnxIaaoqL6+0rHVN87LQtBZc0rOp8nNW8CyvNyR5MwEi05K4IoIAi9lbQG0xtriQlG+oqE6ZVEWheJWWMnsnyS6mGa1er7XkhuhBMeajA+8Cpn5ETM1lYePFs5jkOk6GrT4FOx76E+v7A+maeyR1vxi6Y0TWiSdnrRnQhYY96L/l4z+7bwAAAP//AwA=
RelayState: ReturnUrl=%2F

Chrome SAML Tracer:

<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                     xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                     ID="_76e6448i-79a9-475a-9203-be84b1501496"
                     Version="2.0"
                     IssueInstant="2023-06-28T13:55:08.731Z"
                     Destination="https://singlesignon.lowell.edu/idp/profile/SAML2/POST/SSO"
                     >
    <saml2:Issuer>DevConnector</saml2:Issuer>
</saml2p:AuthnRequest>

GET
SAMLRequest: fJBBb4MwDIX/Cso9JCRQIAKkar1U2tRqVDvsMqU0VZEgyWIj7ecvdDuslx3t589+zw3oeRJebRe82VfzuRjA5GueLKgfpSVLsMppGEFZPRtQOKh++/KsRMqVDw7d4Cbyl/kf0QAm4OgsSfa7lnxIaaoqL6+0rHVN87LQtBZc0rOp8nNW8CyvNyR5MwEi05K4IoIAi9lbQG0xtriQlG+oqE6ZVEWheJWWMnsnyS6mGa1er7XkhuhBMeajA+8Cpn5ETM1lYePFs5jkOk6GrT4FOx76E+v7A+maeyR1vxi6Y0TWiSdnrRnQhYY96L/l4z+7bwAAAP//AwA=
RelayState: ReturnUrl=%2F

Solution

  • The IdP maybe expect you to use HTTP POST given the error message Unable to Decode.

    The samples default use HTTP GET with the Saml2RedirectBinding, like this in the .NET core sample https://github.com/ITfoxtec/ITfoxtec.Identity.Saml2/blob/master/test/TestWebAppCore/Controllers/AuthController.cs#L30

    You can change to use HTTP POST by changing the Saml2RedirectBinding to Saml2PostBinding.