Moderne applikasjoner beveger seg i økende grad bort fra tradisjonelle passord og mot passordløse autentiseringsmetoder som er både sikrere og enklere for brukerne. I dette innlegget skal jeg vise hvordan du autentiserer brukere i en ASP.NET Core-applikasjon ved å bruke FoxIDs med OpenID Connect og aktiverer en fullstendig passordløs påloggingsopplevelse ved å bruke en påloggingskode.

Vi starter fra et rent FoxIDs miljø, oppretter en ny ASP.NET Core nettapp, kobler den til OpenID Connect og aktiverer til slutt passwordless-pålogging med e-postbasert OTP.

Opprette et FoxIDs Dev-miljø

Jeg begynte med å lage et nytt tomt dev-miljø i FoxIDs. Et rent miljø gjør det enkelt å sette opp autentisering fra bunnen av og sikrer at du kan replikere disse trinnene i din egen tenant.

Tomt FoxIDs miljø

Hvis du ikke har brukt FoxIDs før, kan du opprette en gratis tenant på:

https://www.foxids.com

Hver tenant kommer med to klare til bruk miljøer slik at du kan eksperimentere fritt.

Konfigurer autentisering

Start med å konfigurere hvordan brukere skal logge på . I dette tilfellet vil vi at brukerne skal logge på uten passord, kun bruke e-postadressen deres og et engangspassord (OTP) sendt til dem.

  1. Velg kategorien Autentiseringer i ditt FoxIDs miljø.
  2. Klikk på Standard — User Login UI.
  3. I delen Autentisering, deaktiver Passordautentisering og aktiver Passordløs med e-post (engangspassord).
  4. Klikk Oppdater for å lagre endringene.
Konfigurer påloggingsmetode for autentisering

Dette gjør det mulig for brukere å opprette en ny konto og gir en passordløs opplevelse der de autentiserer ganske enkelt ved å skrive inn e-postadressen og OTP de mottar.

Opprette ASP.NET Core-applikasjonen

Deretter trenger vi en applikasjon for å autentisere. Du kan bruke enten Visual Studio eller VS Code - alt som støtter standard ASP.NET Core-utvikling.

Les "Passordløs autentisering i en AI-generert ASP.NET Core-app med FoxIDs og e-postbasert OTP"-innlegget hvis du vil generere ASP.NET Core-applikasjonen med en AI-prompt.

For denne gjennomgangen lager jeg en enkel ASP.NET Core Razor Pages-applikasjon rettet mot .NET 10 i Visual Studio, men den samme tilnærmingen fungerer for MVC, en Blazor Web App eller et hvilket som helst annet ASP.NET Core-prosjekt.

Opprett standard ASP.NET app

Kjør appen; eksempelappen kjører lokalt på https://localhost:7283/

Kjør standard ASP.NET app

Du finner eksempelkoden i: https://github.com/ITfoxtec/dotnet.samples/tree/main/WebAppPasswordLessEmail

Konfigurer webapplikasjonen i FoxIDs

Nå som vi kjenner nettapplikasjonens lokale adresse, kan vi registrere den i FoxIDs slik at den kan autentisere brukere gjennom OpenID Connect.

  1. Velg kategorien Applikasjoner i ditt FoxIDs miljø.
  2. Velg Ny applikasjon, og velg deretter Webapplikasjon — OpenID Connect.
  3. I Navn skriver du inn et navn, for eksempel: ASP.NET nettapplikasjon.
  4. I Redirect URI legger du til applikasjonens basisadresse: https://localhost:7283/ Som standard tillater FoxIDs omdirigering til enhver påfølgende side under denne basis-URLen. Hvis du foretrekker strengere validering, kan du kreve absolutte omdirigerings-URIer.
  5. Klikk på Opprett.
Legg til app i FoxIDs

FoxIDs viser nå tilkoblingsdetaljene for din nye applikasjon, inkludert:

  • Authority
  • Kunde-ID
  • Kundehemmelighet
App laget i FoxIDs

Kopier Authority og Client ID inn i prosjektets IdentitySettings-seksjon. Lagre Client Secret i .NET brukerhemmeligheter lokalt eller i en sikker miljøvariabel eller hemmelig butikk i produksjon.

Konfigurer autentisering i ASP.NET applikasjonen

Med FoxIDs applikasjonen opprettet, er neste trinn å konfigurere autentisering i ASP.NET Core-prosjektet. Vi vil bruke informasjonskapselautentisering for den lokale økten og OpenID Connect for å kommunisere med FoxIDs.

Åpne Program.cs og legg til autentiseringskonfigurasjonen med (builder.Services.AddAuthentication... og 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();

Legg til de ikke-hemmelige FoxIDs tilkoblingsdetaljene til appsettings.json. Hold klienthemmeligheten utenfor kildekontroll og last den fra .NET brukerhemmeligheter under lokal utvikling eller fra en sikker miljøvariabel eller hemmelig butikk i produksjon.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "IdentitySettings": {
    "Authority": "https://foxids.com/{tenant}/{environment}/{application}/",
    "ClientId": "your-client-id"
  }
}

Lagre klienthemmeligheten lokalt uten å skrive den til appsettings.json:

dotnet user-secrets init
dotnet user-secrets set "IdentitySettings:ClientSecret" "your-client-secret"

Erstatt eksempelverdiene med Authority, klient-ID og klienthemmelighet fra ditt eget FoxIDs miljø. Begå aldri den virkelige hemmeligheten.

Vis claims på hovedsiden

For formålet med denne prøven viser claims på hovedsiden. Åpne Index.cshtml endre innholdet:

@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>
}

Legg til en påloggingsmeny til applikasjonen

For å la brukere logge på, legger vi til en delvis visning for påloggings- og utloggingskontroller.

Opprett en ny fil:Pages/Shared/_LoginPartial.cshtml med innholdet:

@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>
}

Ta deretter med innloggingsdelen i navigasjonsmenyen. I Pages/Shared/_Layout.cshtml legger du til det delvise påloggingselementet på slutten av navigasjonslinjen:

<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>

Legg deretter til en landingsside for påloggings- og utloggingsforespørslene. Opprett en kontroller-mappe og opprett en ny kontroller-fil i mappen: Controllers/AuthController.cs med innholdet:

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);
        }
    }
}

Kjør og last inn applikasjonen på nytt, og du vil nå se et Logg inn-alternativ i toppmenyen.

Eksempel på søknad

Logg inn

Klikk på Logg inn og du blir omdirigert til FoxIDs påloggingsskjermen.

Velg Opprett bruker.

FoxIDs påloggingsskjerm

Fyll ut Opprett bruker-skjemaet med e-posten din (eller en test-e-post du har tilgang til), fornavn og etternavn, og klikk deretter på Opprett.

Opprett en testbruker

Skriv inn engangspassordet (OTP) du mottok på e-post, og klikk deretter på Logg inn.

Logg på med engangspassord (OTP)

Du er logget på og testbrukerens claims vises.

Innlogget, vis claims

Prøv deretter å logge av og logge på igjen for å oppleve den passordløse påloggingsflyten ved å bruke e-post OTP.