Search code examples
angularasp.net-web-apiidentityserver4saml-2.0idp

WebAPI first time redirect as POST then as GET to the Angular application


I have strict infrastructure which cannot bo change and trying to enable IdentityServer4 to work with SAML2.0 assertions and tokens. Only API can be exposed to internet. The workflow is like this: 1. User hitting angular app 2. User is redirected to the external SAML2.0 IDP provider, and authenticate himself. 3. IDP redirect to the WebApi with SAML assertion then is redirected to the IS4 for validation and token generation 4. WebAPI send the token to the Angular APP with get request (and here is problem)

First time when I'm login to the IDP the WebApi sending the POST message to the angular which obviously causes an error. When I refresh the browser the workflow goes same way but din't need to provide credentials as I'm already sing-in in IDP, the WebApi sending the GET messages the Angular getting the token and saves it.

I've tried multiple solutions, couple redirect actions, adding header to response, sending the HttpResponseMessage with Location and 301 status code. With all those I get POST in the first time or just Json when sending the raw httpResponseMessage.

        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> PostLogin()
        {
            var form = Request.Form;
            var samlResponse = form["SamlResponse"];

            using (HttpClient client = new HttpClient())
            {
                var response = await client.RequestTokenAsync(new TokenRequest
                {
                    Address = $"{_configuration["IdentityServer"]}/connect/token",
                    GrantType = "SamlResponse",
                    ClientId = "Client",
                    ClientSecret = "Client",
                    Parameters = { { "SamlResponse", samlResponse } }
                });

                var r = new HttpResponseMessage(HttpStatusCode.SeeOther);
                r.Headers.Location = new Uri($"{_configuration["webpage"]}/login?token={response.Json["access_token"]}");

                Response.Headers.Add(HeaderNames.Location, $"{_configuration["webpage"]}/login?token={response.Json["access_token"]}");

                return StatusCode(301);
            }

or

                var r = new HttpResponseMessage(HttpStatusCode.SeeOther);
                r.Headers.Location = new Uri($"{_configuration["webpage"]}/login?token={response.Json["access_token"]}");

                return StatusCode(301, r);

or

        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> PostLogin()
        {
            var form = Request.Form;
            var samlResponse = form["SamlResponse"];

            using (HttpClient client = new HttpClient())
            {
               var response = await client.RequestTokenAsync(new TokenRequest
               {
                    Address = $"{_configuration["IdentityServer"]}/connect/token",
                    GrantType = "SamlResponse",
                    ClientId = "Client",
                    ClientSecret = "Client",
                    Parameters = { { "SamlResponse", samlResponse } }
                });

                if (response.IsError)
                {
                    return StatusCode(400, response.Error);
                }

                return Redirect($"{_configuration["webpage"]}/login?token={response.Json["access_token"]}");
            }
        }

Solution

  • The solution was to enable the chrome://flags/#allow-insecure-localhost flag at chrome. The red cert was causing to refresh the initial POST request. After that everything went fine.