title: ASP.NET Core WebApi Authentication with Identity
body: <p>Okay let me start by saying that I'm rather new to ASP.NET Core and web development in general. Though I did some minor projects in the past.<br />
  I'm at a point where I'm pretty much lost and can't figure out what my issue is. I hope you can at least point me in the right direction.</p>
  <h2>What I want to do</h2>
  <p>TLDR: Authenticate and authorize a Blazor app with a WebApi</p>
  <p>I want to create a Blazor WebAssembly app hosted by an ASP.Core 5 App. Business Logic will get executed by another WebApi.</p>
  <p>So I have 3 relevant projects:</p>
  <ul>
  <li>WebClient (Frontend)</li>
  <li>WebHost (Host for WebClient)</li>
  <li>WebApi (Backend)</li>
  </ul>
  <p>The WebHost is just meant to be hosted in a docker container which will run behind a reverse proxy. So everything I do is running on http locally.</p>
  <p>Blazor communicates with the Backend over WebApi ApiController (REST Api).</p>
  <p>The Frontend has some areas which will need user authentication and authorization. The WebApi is meant to take care of this.</p>
  <p>And here goes my problem.</p>
  <hr />
  <h2>What I've done</h2>
  <p>I've added the IdentityService to my WebApi with customized <code>IdentityUser</code>, <code>IdentityRole</code>, <code>IUserStore</code> and so on.<br />
  When I test my Api with Swagger the registration, login, changing password etc works just fine.</p>
  <p>My Issue: The login is not remembered by the WebApi. That means I can log in and my <code>SignInManager</code> tells me everything is cool but the controller won't know anything about the User when I call an endpoint the next time.<br />
  When I successfully call the login endopint there is a cookie stored in the browser. When I check the <code>HttpContext</code>on my Backend I can see the cookie.</p>
  <hr />
  <h2>Implementation Details</h2>
  <p>I've tried to keep the snippets short and stripped unrelevant parts.</p>
  <p>Startup Configure Method</p>
  <pre><code>app.UseRouting();
  app.UseAuthentication();
  app.UseAuthorization();
  
  app.UseSwagger();
  app.UseSwaggerUI(...);
  
  app.UseEndpoints(x =&gt; x.MapControllers());
  </code></pre>
  <p>Startup ConfigureServices Method</p>
  <pre><code>services.AddControllers();
  services.AddSwaggerGen(...);
  
  services.AddScoped&lt;IUserManager, AppUserManager&gt;();
  services.AddScoped&lt;ISignInManager, AppSignInManager&gt;();
  services.AddTransient&lt;IUserStore&lt;AppUser&gt;, AppUserStore&gt;();
  services.AddTransient&lt;IRoleStore&lt;AppRole&gt;, AppRoleStore&gt;();
  services.AddIdentity&lt;AppUser, AppRole&gt;()
          .AddDefaultTokenProviders();
  services.Configure&lt;IdentityOptions&gt;(...);
  
  services.AddHttpContextAccessor();
  services.AddAuthentication();
  services.AddAuthorization();
  </code></pre>
  <p>Auth Controller Endpoint</p>
  <pre><code>[HttpPost(nameof(Login))]
  public async Task&lt;IActionResult&gt; Login([FromBody] LoginUserCommand command)
  {
      // I've abstracted my logic into a Mediator Command
      // but simplified this is just
      // SignInManager.PasswordSignInAsync(user, pass, rememberMe)
      // ClaimsFactory.CreateAsync(user)
      var result = await Mediator.Send(command); 
  
      if (result.Succeeded)
      {
          // I've tried the following 2 methods to store the ClaimsPrincipal with no success
          await HttpContext.SignInAsync(result.Data);
          var signInResult = SignIn(result.Data); // positive result
  
          return Ok(...);
      }
  
      return BadRequest(...);
  }
  </code></pre>
  <p>The POST request made by swagger</p>
  <pre><code>curl -X POST &quot;http://localhost:4000/_api/v1/Auth/Login&quot;
       -H &quot;accept: */*&quot;
       -H &quot;Content-Type: application/json&quot;
       -d &quot;{\&quot;password\&quot;:\&quot;P4$$w0rd\&quot;,\&quot;rememberMe\&quot;:true,\&quot;username\&quot;:\&quot;admin\&quot;}&quot;
  </code></pre>
  <p>The Cookie stored in the Browser</p>
  <pre><code>Name: Identity.External
  Content: CfDJ8EGl21FYRChCvuGjMRYlEqvNaCBZMxNrNE8D [...]
  Domain: localhost
  Path: /
  Created: 5 minutes ago
  Expires: When the browsing session ends
  </code></pre>