Moderne Anwendungen entfernen sich zunehmend von herkömmlichen Passwörtern und hin zu passwortlosen Authentifizierungsmethoden, die sowohl sicherer als auch für Benutzer einfacher sind. In diesem Beitrag zeige ich, wie man Benutzer in einer ASP.NET Core-Anwendung mit FoxIDs mit OpenID Connect authentifiziert und ein vollständig passwortloses Anmeldeerlebnis mit per E-Mail zugestellten Einmalcodes ermöglicht.

Wir beginnen mit einer sauberen FoxIDs Umgebung, erstellen eine neue ASP.NET Core-Webanwendung, verbinden sie mit OpenID Connect und aktivieren schließlich die passwordless-Anmeldung mit der E-Mail-basierten OTP.

Erstellen einer FoxIDs Entwicklungsumgebung

Ich begann damit, eine neue leere Entwicklungsumgebung in FoxIDs zu erstellen. Eine saubere Umgebung erleichtert die Einrichtung der Authentifizierung von Grund auf und stellt sicher, dass Sie diese Schritte in Ihrem eigenen Tenant replizieren können.

Leere FoxIDs Umgebung

Wenn Sie FoxIDs noch nicht verwendet haben, können Sie unter folgender Adresse einen kostenlosen Tenant erstellen:

https://www.foxids.com

Jeder Tenant wird mit zwei gebrauchsfertigen Umgebungen geliefert, sodass Sie frei experimentieren können.

Konfigurieren Sie die Authentifizierung

Beginnen Sie mit der Konfiguration, wie sich Benutzer anmelden sollen. In diesem Fall möchten wir, dass sich Benutzer ohne Passwort anmelden und nur ihre E-Mail-Adresse und ein ihnen zugesandtes Einmalpasswort (OTP) verwenden.

  1. Wählen Sie in Ihrer FoxIDs Umgebung die Registerkarte Authentifizierungen aus.
  2. Klicken Sie auf Standard – Benutzeroberfläche für die Benutzeranmeldung.
  3. Deaktivieren Sie im Abschnitt Authentifizierung die Passwortauthentifizierung und aktivieren Sie Passwortlos mit E-Mail (Einmalpasswort).
  4. Klicken Sie auf Aktualisieren, um die Änderungen zu speichern.
Konfigurieren Sie die Anmeldemethode für die Authentifizierung

Dies ermöglicht Benutzern die Erstellung eines neuen Kontos und bietet ein passwortloses Erlebnis, bei dem sie sich einfach durch Eingabe ihrer E-Mail-Adresse und des erhaltenen OTP authentifizieren.

Erstellen der ASP.NET Core-Anwendung

Als nächstes benötigen wir eine Anwendung zur Authentifizierung. Sie können entweder Visual Studio oder VS Code verwenden – alles, was die Standardentwicklung ASP.NET Core unterstützt.

Lesen Sie den Beitrag „Passwortlose Authentifizierung in einer KI-generierten ASP.NET Core-App mit FoxIDs und E-Mail-basiertem OTP“, wenn Sie die ASP.NET Core-Anwendung mit einer KI-Eingabeaufforderung generieren möchten.

Für diese exemplarische Vorgehensweise erstelle ich eine einfache ASP.NET Core Razor Pages-Anwendung für .NET 10 in Visual Studio, aber der gleiche Ansatz funktioniert für MVC, eine Blazor-Web-App oder jedes andere ASP.NET Core-Projekt.

Erstellen Sie die Standard-App ASP.NET

Führen Sie die App aus; Die Beispiel-App läuft lokal auf https://localhost:7283/

Führen Sie die Standard-App ASP.NET aus

Den Beispielcode finden Sie unter: https://github.com/ITfoxtec/dotnet.samples/tree/main/WebAppPasswordLessEmail

Konfigurieren Sie die Webanwendung in FoxIDs

Da wir nun die lokale Adresse der Webanwendung kennen, können wir sie in FoxIDs registrieren, damit Benutzer über OpenID Connect authentifiziert werden können.

  1. Wählen Sie in Ihrer FoxIDs Umgebung die Registerkarte Anwendungen.
  2. Wählen Sie Neue Anwendung und dann Webanwendung – OpenID Connect.
  3. Geben Sie unter Name einen Namen ein, zum Beispiel: ASP.NET Webanwendung.
  4. Fügen Sie im Umleitungs-URI die Basisadresse der Anwendung hinzu: https://localhost:7283/ Standardmäßig ermöglicht FoxIDs die Weiterleitung zu jeder nachfolgenden Seite unter dieser Basis-URL. Wenn Sie eine strengere Validierung bevorzugen, können Sie absolute Weiterleitungs-URIs verlangen.
  5. Klicken Sie auf Erstellen.
App in FoxIDs hinzufügen

FoxIDs zeigt jetzt die Verbindungsdetails für Ihre neue Anwendung an, einschließlich:

  • Authority
  • Kunden-ID
  • Client-Geheimnis
App erstellt in FoxIDs

Kopieren Sie Authority und Client-ID in den Abschnitt IdentitySettings des Projekts. Speichern Sie das Client-Geheimnis in den Benutzergeheimnissen .NET lokal oder in einer sicheren Umgebungsvariablen oder einem geheimen Speicher in der Produktion.

Konfigurieren Sie die Authentifizierung in der Anwendung ASP.NET

Nachdem die Anwendung FoxIDs erstellt wurde, besteht der nächste Schritt darin, die Authentifizierung im Projekt ASP.NET Core zu konfigurieren. Wir verwenden die Cookie-Authentifizierung für die lokale Sitzung und OpenID Connect für die Kommunikation mit FoxIDs.

Öffnen Sie Program.cs und fügen Sie die Authentifizierungskonfiguration mit (builder.Services.AddAuthentication... und app.UseAuthentication()😉 hinzu:

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

Fügen Sie die nicht geheimen Verbindungsdetails FoxIDs zu appsettings.json hinzu. Halten Sie das Client-Geheimnis von der Quellcodeverwaltung fern und laden Sie es während der lokalen Entwicklung aus .NET Benutzergeheimnissen oder aus einer sicheren Umgebungsvariablen oder einem geheimen Speicher in der Produktion.

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

Speichern Sie den geheimen Clientschlüssel lokal, ohne ihn in appsettings.json zu schreiben:

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

Ersetzen Sie die Beispielwerte durch Authority, Client-ID und Client-Geheimnis aus Ihrer eigenen FoxIDs Umgebung. Geben Sie niemals das wahre Geheimnis preis.

Claims auf der Hauptseite anzeigen

Für dieses Beispiel werden Claims auf der Hauptseite angezeigt. Öffnen Sie Index.cshtml und ändern Sie den Inhalt:

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

Fügen Sie der Anwendung ein Anmeldemenü hinzu

Damit sich Benutzer anmelden können, fügen wir eine Teilansicht für Anmelde- und Abmeldekontrollen hinzu.

Erstellen Sie eine neue Datei:Pages/Shared/_LoginPartial.cshtml mit dem Inhalt:

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

Fügen Sie dann den Login-Teil in das Navigationsmenü ein. Fügen Sie in Pages/Shared/_Layout.cshtml das Teil-Login-Element am Ende der Navigationsleiste hinzu:

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

Fügen Sie dann eine Landingpage für die Anmelde- und Abmeldeanfragen hinzu. Erstellen Sie einen Controller-Ordner und erstellen Sie eine neue Controller-Datei im Ordner: Controllers/AuthController.cs mit dem Inhalt:

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

Führen Sie die Anwendung aus und laden Sie sie neu. Im oberen Menü wird nun die Option Anmelden angezeigt.

Beispielanwendung

Einloggen

Klicken Sie auf Anmelden und Sie werden zum FoxIDs Anmeldebildschirm weitergeleitet.

Wählen Sie Benutzer erstellen.

FoxIDs Anmeldebildschirm

Füllen Sie das Formular Benutzer erstellen mit Ihrer E-Mail-Adresse (oder einer Test-E-Mail, auf die Sie Zugriff haben), Ihrem Vor- und Nachnamen aus und klicken Sie dann auf Erstellen.

Erstellen Sie einen Testbenutzer

Geben Sie das Einmalpasswort (OTP) ein, das Sie per E-Mail erhalten haben, und klicken Sie dann auf Anmelden.

Login mit Einmalpasswort (OTP)

Sie sind angemeldet und die Claims Ihres Testbenutzers werden angezeigt.

Eingeloggt, Claims anzeigen

Versuchen Sie als Nächstes, sich abzumelden und erneut anzumelden, um den kennwortlosen Anmeldevorgang per E-Mail OTP zu erleben.