Codelabs.SimpleAuthentication
1.0.0
See the version list below for details.
dotnet add package Codelabs.SimpleAuthentication --version 1.0.0
NuGet\Install-Package Codelabs.SimpleAuthentication -Version 1.0.0
<PackageReference Include="Codelabs.SimpleAuthentication" Version="1.0.0" />
paket add Codelabs.SimpleAuthentication --version 1.0.0
#r "nuget: Codelabs.SimpleAuthentication, 1.0.0"
// Install Codelabs.SimpleAuthentication as a Cake Addin #addin nuget:?package=Codelabs.SimpleAuthentication&version=1.0.0 // Install Codelabs.SimpleAuthentication as a Cake Tool #tool nuget:?package=Codelabs.SimpleAuthentication&version=1.0.0
SimpleAuthentication
Currently Supports Blazor Server & ASP.NET Core MVC. Next Release will support WASM/JWT
How to set up
Download Nuget Package
Install-Package Codelabs.SimpleAuthentication
For Blazor Server Apps You Need A Custom AuthenticationState Provider. Just Copy the class below and add it in your project.
public class RevalidatingIdentityAuthenticationStateProvider<TUser>
: RevalidatingServerAuthenticationStateProvider where TUser : class
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IdentityOptions _options;
public RevalidatingIdentityAuthenticationStateProvider(
ILoggerFactory loggerFactory,
IServiceScopeFactory scopeFactory,
IOptions<IdentityOptions> optionsAccessor)
: base(loggerFactory)
{
_scopeFactory = scopeFactory;
_options = optionsAccessor.Value;
}
protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30);
protected override async Task<bool> ValidateAuthenticationStateAsync(
AuthenticationState authenticationState, CancellationToken cancellationToken)
{
// Get the user manager from a new scope to ensure it fetches fresh data
var scope = _scopeFactory.CreateScope();
try
{
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<TUser>>();
return await ValidateSecurityStampAsync(userManager, authenticationState.User);
}
finally
{
if (scope is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync();
}
else
{
scope.Dispose();
}
}
}
private async Task<bool> ValidateSecurityStampAsync(UserManager<TUser> userManager, ClaimsPrincipal principal)
{
var user = await userManager.GetUserAsync(principal);
if (user == null)
{
return false;
}
else if (!userManager.SupportsUserSecurityStamp)
{
return true;
}
else
{
var principalStamp = principal.FindFirstValue(_options.ClaimsIdentity.SecurityStampClaimType);
var userStamp = await userManager.GetSecurityStampAsync(user);
return principalStamp == userStamp;
}
}
}
Next Install <code>Microsoft.EntityFrameworkCore.Tools</code> and the Database provider of your choice in the demo <code>Microsoft.EntityFrameworkCore.SQLite</code> is used. <br/> Lastly in your <code>Program.cs</code> configure SimpleAuthentication Like below.
using Demo;
using Demo.Data;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.EntityFrameworkCore;
using SimpleAuthentication;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSimpleAuthentication(userStoreOptions =>
{
userStoreOptions.UseSqlite("Data Source = Identity.db");//Database to use
});
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<User>>();
builder.Services.AddSingleton<WeatherForecastService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
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.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSimpleAuthentication();//important
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
The code below shows a demo login page using Razor.
@page "/login"
@attribute [AllowAnonymous]
@layout LoginLayout
<div class="container center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h4 class="text-primary">Login</h4>
</div>
<div class="card-body">
<EditForm Model="@Model" OnValidSubmit="LoginAsync" id="loginForm">
<DataAnnotationsValidator />
<div class="form-group mb-4">
<label for="username">Username:</label>
<InputText @bind-Value="Model.UserName" type="text" class="form-control" id="username" name="username" />
<ValidationMessage For="()=>Model.UserName" />
</div>
<div class="form-group mb-4">
<label for="password">Password:</label>
<InputText @bind-Value="Model.Password" type="password" class="form-control" id="password" name="password" />
<ValidationMessage For="()=>Model.Password" />
</div>
<button title="Login now." type="submit" class="btn btn-primary">Login</button>
<a href="register" title="Don't have an account yet? Register."
class="btn btn-success mx-4">Register</a>
</EditForm>
@if (failed)
{
<div id="e-message" class="mt-4 pa-2">
<div class="alert alert-danger">
<div class="d-flex align-items-center">
<div>
<i id="e-icon" class="oi oi-warning"></i>
</div>
<div class="ml-4 mt-3">
<p id="e-message-content">@errorMessage</p>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
</div>
@inject NavigationManager navManager;
@code {
LoginRequest Model = new();
string errorMessage = string.Empty;
bool failed;
async Task LoginAsync()
{
Model.ReturnUrl="/fetchdata";
var authResult = await authenticationService.LoginAsync(Model);
if(authResult.Succeeded)
{
navManager.NavigateTo($"/login?key={authResult.Key}",true);
}else
{
failed = true;
errorMessage = authResult.Message;
StateHasChanged();
}
}
}
That's it. For more info see <a href="https://github.com/izzyjere/SimpleAuthentication" target="_blank">Git Hub</a>
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- Microsoft.AspNetCore.Authorization (>= 6.0.14)
- Microsoft.AspNetCore.Components.Authorization (>= 6.0.12)
- Microsoft.AspNetCore.Identity (>= 2.2.0)
- Microsoft.AspNetCore.Identity.EntityFrameworkCore (>= 6.0.12)
- Microsoft.Extensions.Identity.Core (>= 6.0.12)
- Newtonsoft.Json (>= 13.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.