True, but there is a ton of conflicting information on it, and Microsoft glosses over the Authentication/Authorization most of the time. Just look at the other comments above asking why I'm using an iframe.
You are making assumptions based on opinion and prior observations not facts.
I have no interest in OAuth. I only want to authorize user accounts that are under my control. I know how SPAs work (or rather, suck). I understand using JSON Web Tokens. I have plenty of experience with .NET Identity and the old Membership Providers of the past too.
The old Membership Provider and Identity uses cookie authentication to secure ASP.NET applications. Given your responses, I'm guessing you want to host Blazor with Web API, Razor Pages, and/or MVC. I'm also guessing you to want to use cookie authentication rather than following standard modern security practices.
- Create a new Blazor WASM project.
- Select the Hosted option.
- Do not select an authentication option since you are going rouge.
The template creates three projects; client, server, and shared. The server project hosts Web API and the Blazor application. From this point you can scaffold Identity in the server project by following the docs. I built a sample project using cookie authentication without Identity to make the project as light weight as possible.
The Startup file
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
services.AddControllersWithViews();
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
}
The controller
[Route("[controller]")]
public class LoginController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public async Task<IActionResult> IndexAsync(LoginModel model)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.Username),
new Claim(ClaimTypes.Role, "Administrator"),
};
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
//AllowRefresh = <bool>,
// Refreshing the authentication session should be allowed.
//ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
// The time at which the authentication ticket expires. A
// value set here overrides the ExpireTimeSpan option of
// CookieAuthenticationOptions set with AddCookie.
//IsPersistent = true,
// Whether the authentication session is persisted across
// multiple requests. When used with cookies, controls
// whether the cookie's lifetime is absolute (matching the
// lifetime of the authentication ticket) or session-based.
//IssuedUtc = <DateTimeOffset>,
// The time at which the authentication ticket was issued.
//RedirectUri = <string>
// The full path or absolute URI to be used as an http
// redirect response value.
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
return Redirect("~/");
}
}
The code will create an authentication cookie and you can secure MVC endpoints with the cookie. I'm not sure how well this will work with Web API as Web API is stateless and clients do not expect to send a cookie.
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
You can go with a JWT rather than cookie authentication. Configure JWT bearer tokens in the startup. Create a Web API endpoint that accepts user credentials and returns the JWT to Blazor app. It's the same idea as the login action above except the action returns a JWT. You'll need to write code to persist the JWT and send the JWT bearer token to each secured Web API endpoints.
Unfortunately, you have not defined the client(s) or what you are securing. I still recommend that you learn OAuth/OIDC so you understand what you're giving up by creating a custom security solution.