Search code examples
corssaml-2.0identityserver4asp.net-core-identitysustainsys-saml2

Identity Server 4 & Sustainsys SAML2 rejecting non-CORS request as a CORS request


  • I am using Identity Server 4 with AspNetIdentity.
  • I have added a SAML Authentication provider using Sustainsys.
  • I can successfully login using a local account.
  • I want to link the SAML Authentication provider to my local account. I follow the process to link an external and social login (as I have successfully done with Google, Microsoft & Facebook) - link is https://identity.domain.com/Manage/ExternalLogins
  • I now have an option to link a SAML2 service
  • I can successfully link out to the external SSO and authenticate; I am then redirected back to https://identity.domain.com/Manage/LinkLoginCallback but the code is failing in the ManageController at the following point:

Null is being returned for GetExternalLoginInfoAsync. The user.Id is correct and exists in the database.

ExternalLoginInfo info = await signInManager.GetExternalLoginInfoAsync(user.Id);
        if (info == null)
        {
            throw new ApplicationException($"Unexpected error occurred loading external login info for user with ID '{user.Id}'.");
        }

From what I can see there should be a collection of properties that have been returned by the external SAML provider to:

public async Task<IActionResult> LinkLogin(string provider)

I suspect that the issue may be something related to the CORS error however I have not successfully addressed this error even though I've added the following lines in startup.cs as per documentation at http://docs.identityserver.io/en/release/topics/cors.html.

            var cors = new DefaultCorsPolicyService(_loggerFactory.CreateLogger<DefaultCorsPolicyService>())
        {
            AllowedOrigins = { "https://sso.acme.com" }
        };
        services.AddSingleton<ICorsPolicyService>(cors);

Here is the log of debugging information:

  • LinkLogin redirectUrl: /Manage/LinkLoginCallback
  • AuthenticationScheme: "Identity.Application" was successfully authenticated.
  • Extracted SAML assertion _ea533182b0cb1781868a660af48ced3529d568
  • AuthenticationScheme: "Identity.Application" was successfully authenticated.
  • LinkLoginCallback User.Id: a0162430-eb22-4154-bf59-0ba49bfd473d
  • Successfully processed SAML response _402e6060e55e8e5d3b05f52ff5e5d2d7d4d786 and authenticated test@acme.com
  • System.ApplicationException: Unexpected error occurred loading external login info for user with ID 'a0162430-eb22-4154-bf59-0ba49bfd473d'.
  • CORS request made for path: "/Saml2/Acs" from origin: "https://sso.acme.com" but was ignored because path was not for an allowed IdentityServer CORS endpoint
  • LinkLoginCallback starting
  • Validated conditions for SAML2 Response _402e6060e55e8e5d3b05f52ff5e5d2d7d4d786
  • Http POST binding extracted message
  • Signature validation passed for Saml Response _402e6060e55e8e5d3b05f52ff5e5d2d7d4d786
  • AuthenticationScheme: "Identity.Application" was successfully authenticated.

UPDATE: - Customer sending back Saml request says it is not a CORS request to /Saml2/ACS and therefore doesn't understand why we would be getting the error we are getting from Identity Server / Sustainsy


Solution

  • The solution to this problem was simple in the end.

    • I was trying to process a Saml response (within ExternalLoginCallback) using the approach to process a response from Google, Microsoft of Facebook

    ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync(user.Id);

    • It's apparent that the process for ExternalLoginCallback for a Saml request is slightly different - you need the following code:

    AuthenticateResult samlResult = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

    • You can then build an ExternalLoginInfo object using the properties in samlResult

    • All the code for this is available in the following sample:

    https://github.com/Sustainsys/Saml2/blob/netstandard/Samples/SampleIdentityServer4/Quickstart/Account/AccountController.cs

    • Interestingly, the log files still print out a CORS request made for path: "/Saml2/Acs" from origin: "https://sso.acme.com" but was ignored because path was not for an allowed IdentityServer CORS endpoint however this appears to have had no impact on the sign-in process. So a "red-herring".