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.
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.
TLDR: Authenticate and authorize a Blazor app with a WebApi
I want to create a Blazor WebAssembly app hosted by an ASP.Core 5 App. Business Logic will get executed by another WebApi.
So I have 3 relevant projects:
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.
Blazor communicates with the Backend over WebApi ApiController (REST Api).
The Frontend has some areas which will need user authentication and authorization. The WebApi is meant to take care of this.
And here goes my problem.
I've added the IdentityService to my WebApi with customized IdentityUser
, IdentityRole
, IUserStore
and so on.
When I test my Api with Swagger the registration, login, changing password etc works just fine.
My Issue: The login is not remembered by the WebApi. That means I can log in and my SignInManager
tells me everything is cool but the controller won't know anything about the User when I call an endpoint the next time.
When I successfully call the login endopint there is a cookie stored in the browser. When I check the HttpContext
on my Backend I can see the cookie.
I've tried to keep the snippets short and stripped unrelevant parts.
Startup Configure Method
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(...);
app.UseEndpoints(x => x.MapControllers());
Startup ConfigureServices Method
services.AddControllers();
services.AddSwaggerGen(...);
services.AddScoped<IUserManager, AppUserManager>();
services.AddScoped<ISignInManager, AppSignInManager>();
services.AddTransient<IUserStore<AppUser>, AppUserStore>();
services.AddTransient<IRoleStore<AppRole>, AppRoleStore>();
services.AddIdentity<AppUser, AppRole>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(...);
services.AddHttpContextAccessor();
services.AddAuthentication();
services.AddAuthorization();
Auth Controller Endpoint
[HttpPost(nameof(Login))]
public async Task<IActionResult> 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(...);
}
The POST request made by swagger
curl -X POST "http://localhost:4000/_api/v1/Auth/Login"
-H "accept: */*"
-H "Content-Type: application/json"
-d "{\"password\":\"P4$$w0rd\",\"rememberMe\":true,\"username\":\"admin\"}"
The Cookie stored in the Browser
Name: Identity.External
Content: CfDJ8EGl21FYRChCvuGjMRYlEqvNaCBZMxNrNE8D [...]
Domain: localhost
Path: /
Created: 5 minutes ago
Expires: When the browsing session ends
Try adding the cookie scheme when you use the authentication service:
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);
Then, when you sign in use that same scheme:
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
IsPersistent = true,
};
await httpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.