Le applicazioni moderne si allontanano sempre più dalle password tradizionali e si orientano verso metodi di autenticazione senza password, più sicuri e più semplici per gli utenti. In questo post, mostrerò come autenticare gli utenti in un'applicazione ASP.NET Core utilizzando FoxIDs con OpenID Connect e abilitare un'esperienza di accesso completamente senza password utilizzando codici monouso inviati via email.
Inizieremo da un ambiente FoxIDs pulito, creeremo una nuova app Web ASP.NET Core, la collegheremo a OpenID Connect e infine abiliteremo l'accesso passwordless con OTP basato su e-mail.
Creazione di un ambiente di sviluppo FoxIDs
Ho iniziato creando un nuovo ambiente di sviluppo vuoto in FoxIDs. Un ambiente pulito semplifica la configurazione dell'autenticazione da zero e garantisce la possibilità di replicare questi passaggi nel tuo tenant.
Se non hai mai utilizzato FoxIDs, puoi creare un tenant gratuito all'indirizzo:
Ogni tenant viene fornito con due ambienti pronti all'uso per consentirti di sperimentare liberamente.
Configura l'autenticazione
Inizia configurando come gli utenti devono accedere. In questo caso, vogliamo che gli utenti accedano senza password, utilizzando solo il loro indirizzo email e una password monouso (OTP) inviata loro.
- Seleziona la scheda Autenticazioni nel tuo ambiente FoxIDs.
- Fai clic su Predefinita: interfaccia utente di accesso utente.
- Nella sezione Autenticazione, disabilita Autenticazione tramite password e abilita Senza password con email (password monouso).
- Fai clic su Aggiorna per salvare le modifiche.
Ciò consente agli utenti di creare un nuovo account e fornisce un'esperienza senza password in cui si autenticano semplicemente inserendo il proprio indirizzo e-mail e il codice OTP che ricevono.
Creazione dell'applicazione ASP.NET Core
Successivamente, abbiamo bisogno di un'applicazione per l'autenticazione. Puoi utilizzare Visual Studio o VS Code: tutto ciò che supporta lo sviluppo ASP.NET Core standard.
Leggi il post "Autenticazione senza password in un'app ASP.NET Core generata dall'intelligenza artificiale con FoxIDs e OTP basata su e-mail" se desideri generare l'applicazione ASP.NET Core con un prompt AI.
Per questa procedura dettagliata, sto creando una semplice applicazione ASP.NET Core Razor Pages destinata a .NET 10 in Visual Studio, ma lo stesso approccio funziona per MVC, un'app Web Blazor o qualsiasi altro progetto ASP.NET Core.
Esegui l'app; l'app di esempio viene eseguita localmente su https://localhost:7283/
Puoi trovare il codice di esempio in: https://github.com/ITfoxtec/dotnet.samples/tree/main/WebAppPasswordLessEmail
Configurare l'applicazione web in FoxIDs
Ora che conosciamo l'indirizzo locale dell'applicazione web, possiamo registrarla in FoxIDs in modo che possa autenticare gli utenti tramite OpenID Connect.
- Seleziona la scheda Applicazioni nel tuo ambiente FoxIDs.
- Scegli Nuova applicazione, quindi seleziona Applicazione Web: OpenID Connect.
- Nel campo Nome, inserisci un nome, ad esempio: ASP.NET applicazione web.
- Nell'URI di reindirizzamento, aggiungi l'indirizzo di base dell'applicazione: https://localhost:7283/ Per impostazione predefinita, FoxIDs consente il reindirizzamento a qualsiasi pagina successiva sotto questo URL di base. Se preferisci una convalida più rigorosa, puoi richiedere URI di reindirizzamento assoluti.
- Fare clic su Crea.
FoxIDs ora visualizza i dettagli di connessione per la tua nuova applicazione, tra cui:
- Authority
- ID cliente
- Segreto del cliente
Copia Authority e ID cliente nella sezione IdentitySettings del progetto. Archivia il Segreto client nei segreti utente .NET localmente o in una variabile di ambiente protetta o in un archivio segreto in produzione.
Configurare l'autenticazione nell'applicazione ASP.NET
Una volta creata l'applicazione FoxIDs, il passaggio successivo è configurare l'autenticazione nel progetto ASP.NET Core. Utilizzeremo l'autenticazione tramite cookie per la sessione locale e OpenID Connect per comunicare con FoxIDs.
Apri Program.cs e aggiungi la configurazione di autenticazione con (builder.Services.AddAuthentication... e app.UseAuthentication()😉:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Logging;
var builder = WebApplication.CreateBuilder(args);
// Detailed authentication errors can help locally, but must not be enabled in production.
if (builder.Environment.IsDevelopment())
{
IdentityModelEventSource.ShowPII = true;
}
// Add authentication with cookie and OpenID Connect
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = builder.Configuration["IdentitySettings:Authority"];
options.ClientId = builder.Configuration["IdentitySettings:ClientId"];
options.ClientSecret = builder.Configuration["IdentitySettings:ClientSecret"];
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.Scope.Add("email");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
options.MapInboundClaims = false;
options.TokenValidationParameters.NameClaimType = "sub";
options.TokenValidationParameters.RoleClaimType = "role";
options.Events = new OpenIdConnectEvents
{
OnTokenValidated = async context =>
{
// Custom claims transformation or other logic can be added here.
await Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
if (!builder.Environment.IsDevelopment())
{
return Task.CompletedTask;
}
context.HandleResponse();
context.Response.StatusCode = 500;
context.Response.ContentType = "text/plain";
return context.Response.WriteAsync(context.Exception.ToString());
}
};
});
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllers();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapStaticAssets();
app.MapControllers();
app.MapRazorPages()
.WithStaticAssets();
app.Run();
Aggiungi i dettagli di connessione non segreti FoxIDs a appsettings.json. Mantieni il segreto del client fuori dal controllo del codice sorgente e caricalo dai segreti utente .NET durante lo sviluppo locale o da una variabile di ambiente sicura o da un archivio segreto in produzione.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"IdentitySettings": {
"Authority": "https://foxids.com/{tenant}/{environment}/{application}/",
"ClientId": "your-client-id"
}
}
Archivia il segreto client localmente senza scriverlo su appsettings.json:
dotnet user-secrets init
dotnet user-secrets set "IdentitySettings:ClientSecret" "your-client-secret"
Sostituisci i valori di esempio con Authority, ID client e Segreto client dal tuo ambiente FoxIDs. Non svelare mai il vero segreto.
Mostra claims nella pagina principale
Ai fini di questo esempio, mostrare i claims nella pagina principale. Apri Index.cshtml modifica il contenuto:
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
@if (User.Identity?.IsAuthenticated == true)
{
<h2 class="mt-4">Claims</h2>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Type</th>
<th>Value</th>
</tr>
</thead>
<tbody>
@foreach (var claim in User.Claims)
{
<tr>
<td>@claim.Type</td>
<td>@claim.Value</td>
</tr>
}
</tbody>
</table>
}
else
{
<p class="mt-4 text-muted">Not signed in.</p>
}
Aggiungi un menu di accesso all'applicazione
Per consentire agli utenti di accedere, aggiungiamo una visualizzazione parziale per i controlli di accesso e disconnessione.
Crea un nuovo file:Pages/Shared/_LoginPartial.cshtml con il contenuto:
@if (User.Identity?.IsAuthenticated == true)
{
<ul class="navbar-nav">
<li class="nav-item">
<form class="form-inline" asp-controller="Auth" asp-action="Logout" method="post">
@Html.AntiForgeryToken()
<button type="submit" class="nav-link btn btn-link text-dark">Log off</button>
</form>
</li>
</ul>
}
else
{
<ul class="navbar-nav navbar-right">
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Auth" asp-action="Login">Log in</a>
</li>
</ul>
}
Quindi includi il login parziale nel menu di navigazione. In Pages/Shared/_Layout.cshtml aggiungi l'elemento di accesso parziale alla fine della barra di navigazione:
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
Quindi aggiungi una pagina di destinazione per le richieste di accesso e disconnessione. Creare una cartella Controllers e creare un nuovo file controller nella cartella: Controllers/AuthController.cs con il contenuto:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace WebAppPasswordLessEmail.Controllers
{
[AllowAnonymous]
[Route("[controller]/[action]")]
public class AuthController : Controller
{
[HttpGet]
public IActionResult Login()
{
var redirectUri = Url.Content("~/");
if (User.Identity?.IsAuthenticated == true)
{
return LocalRedirect(redirectUri);
}
return Challenge(new AuthenticationProperties { RedirectUri = redirectUri },
OpenIdConnectDefaults.AuthenticationScheme);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Logout()
{
var redirectUri = Url.Content("~/");
if (User.Identity?.IsAuthenticated != true)
{
return LocalRedirect(redirectUri);
}
return SignOut(new AuthenticationProperties { RedirectUri = redirectUri },
CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme);
}
}
}
Esegui e ricarica l'applicazione e ora vedrai l'opzione Accedi nel menu in alto.
Login
Fai clic su Accedi e verrai reindirizzato alla schermata di accesso FoxIDs.
Seleziona Crea utente.
Compila il modulo Crea utente con il tuo indirizzo email (o un'email di prova a cui hai accesso), nome e cognome, quindi fai clic su Crea.
Inserisci la password monouso (OTP) che hai ricevuto via email, quindi fai clic su Accedi.
Hai effettuato l'accesso e vengono visualizzate i claims del tuo utente di prova.
Successivamente, prova a disconnetterti e ad accedere nuovamente per sperimentare il flusso di accesso senza password utilizzando l'e-mail OTP.