Moderne applikationer bevæger sig i stigende grad væk fra traditionelle adgangskoder og over mod adgangskodefri autentificeringsmetoder, der både kan styrke sikkerheden og gøre login lettere for brugerne. I denne artikel viser jeg, hvordan brugere autentificeres i en AI-genereret ASP.NET Core applikation med FoxIDs og OpenID Connect, så de kan logge ind helt uden adgangskode med engangskoder sendt via e-mail.

Vi begynder med et tomt FoxIDs miljø, opretter en ny ASP.NET Core webapplikation, forbinder den med OpenID Connect og aktiverer til sidst adgangskodefrit login med e-mailbaseret OTP.

Opret et FoxIDs udviklingsmiljø

Jeg begyndte med at oprette et nyt, tomt udviklingsmiljø i FoxIDs. Et tomt miljø gør det overskueligt at konfigurere autentifikation fra bunden og gentage trinnene i jeres egen tenant.

Tomt FoxIDs miljø

Hvis I ikke har brugt FoxIDs før, kan I oprette en gratis tenant her:

https://www.foxids.com

Hver tenant indeholder to miljøer, der er klar til brug, så I frit kan afprøve opsætningen.

Konfigurér autentifikation

Begynd med at konfigurere, hvordan brugerne skal logge ind. Her skal brugerne logge ind uden adgangskode og kun bruge deres e-mailadresse og et engangskodeord (OTP), som sendes til dem.

  1. Vælg fanen Authentications i FoxIDs miljøet.
  2. Vælg Default — User Login UI.
  3. Deaktivér Password authentication under Authentication, og aktivér Passwordless with email (one-time password).
  4. Vælg Update for at gemme ændringerne.
Konfiguration af loginmetoden

Brugerne kan nu oprette en ny konto og logge ind uden adgangskode ved blot at indtaste deres e-mailadresse og den OTP, de modtager.

Generér ASP.NET Core applikationen

Nu skal vi bruge en applikation, som skal autentificere brugere. I kan bruge AI-prompten til at generere en ny ASP.NET Core Razor Pages applikation til .NET 10 eller føje OpenID Connect til en eksisterende applikation.

Læs artiklen “Adgangskodefri autentifikation i ASP.NET Core med FoxIDs og e-mail OTP”, hvis I vil oprette ASP.NET Core applikationen manuelt.

I denne vejledning genererer jeg en enkel ASP.NET Core applikation i VS Code med Codex. Copilot kan også bruges. Promptens instruktioner er oversat til dansk. Tekniske identifikatorer, filnavne, konfigurationsnøgler, faste kodeværdier og pladsholdere er bevaret uændret, så prompten fortsat kan kopieres direkte.

Du er en erfaren ASP.NET Core udvikler.

Mål: Opret (eller opdatér) en ASP.NET Core webapplikation, der autentificerer brugere med FoxIDs via OpenID Connect (authorization code flow). Brug cookiebaseret autentifikation til den lokale session og OIDC som challenge scheme.

### Tilstand (vælg én)
- MODE = "NEW_APP"  -> opret en ny Razor Pages applikation
- MODE = "EXISTING_APP"  -> tilpas den aktuelle solution uden at ødelægge eksisterende ruter eller sider

MODE: {{MODE}}

### Applikationsoplysninger
- ProjectName: {{PROJECT_NAME}}  (bruges kun, hvis MODE = "NEW_APP")
- TargetFramework: net10.0 (eller behold det eksisterende, hvis det er nyere)
- Lokal HTTPS URL (skal svare til basisadressen for FoxIDs Redirect URI): {{APP_BASE_URL}}  (eksempel: https://localhost:7283/)

### FoxIDs OIDC konfiguration
Skriv ikke Authority, ClientId eller ClientSecret direkte i koden eller i denne prompt.
Gør i stedet følgende:
- Læs dem fra konfigurationsnøglerne:
  - "IdentitySettings:Authority"
  - "IdentitySettings:ClientId"
  - "IdentitySettings:ClientSecret"
- Det endelige svar skal tydeligt forklare brugeren, hvor og hvordan konfigurationsværdierne angives, eksempelvis i appsettings.json, miljøvariabler eller user-secrets.

### Implementeringskrav

1) Tilføj autentifikation i Program.cs:
   - Konfigurér autentifikation:
     - DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme
     - DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme
   - Tilføj cookiebaseret autentifikation.
   - Tilføj OpenID Connect autentifikation:
     - Authority fra konfigurationen: "IdentitySettings:Authority"
     - ClientId fra konfigurationen: "IdentitySettings:ClientId"
     - ClientSecret fra konfigurationen: "IdentitySettings:ClientSecret"
     - ResponseType = "code"
     - SaveTokens = true
     - Scopes: "openid", "profile", "email", "offline_access"
     - MapInboundClaims = false
     - TokenValidationParameters:
       - NameClaimType = "sub"
       - RoleClaimType = "role"
   - Tilføj OpenIdConnectEvents med:
     - OnAuthenticationFailed: Returnér kun i Development et enkelt svar i ren tekst med undtagelsesbeskeden til fejlsøgning. Vis aldrig detaljer om undtagelsen eller PII i produktion.
   - Sørg for, at middleware er registreret:
     - app.UseAuthentication() kaldes før app.UseAuthorization().

2) Tilføj konfigurationsopsætning:
   - Tilføj en `IdentitySettings` sektion i appsettings.json, som kun indeholder ikke-fortrolige pladsholderværdier, eksempelvis:
     - "Authority": "https://your-foxids-authority/"
     - "ClientId": "your-client-id"
   - Læs "IdentitySettings:ClientSecret" fra konfigurationen, men gem værdien i .NET user-secrets under lokal udvikling eller i en miljøvariabel eller et sikkert hemmelighedslager i produktion.
   - Hvis MODE = "EXISTING_APP", skal sektionen flettes ind i den eksisterende konfiguration uden at overskrive andre indstillinger.
   - Tilføj kommentarer eller forklarende tekst i det endelige svar om, at:
     - Brugeren skal erstatte værdierne med den rigtige FoxIDs Authority, ClientId og ClientSecret.
     - Fortrolige værdier ikke må skrives i appsettings.json eller tilføjes til versionsstyring.

3) Tilføj endpoints til login og logout:
   - Opret `Controllers/AuthController.cs` med en almindelig MVC controller:
     - Brug route-mønstret `[controller]/[action]`.
   - Login action (GET):
     - Hvis brugeren allerede er autentificeret, skal der omdirigeres til "/".
     - Ellers skal der udstedes en Challenge med OpenIdConnectDefaults.AuthenticationScheme og RedirectUri = "/".
   - Logout action (POST, med [ValidateAntiForgeryToken]):
     - Hvis brugeren ikke er autentificeret, skal der omdirigeres til "/".
     - Ellers skal der udføres SignOut fra:
       - CookieAuthenticationDefaults.AuthenticationScheme og
       - OpenIdConnectDefaults.AuthenticationScheme
       med RedirectUri = "/".

4) Tilføj en login partial til brugergrænsefladen:
   - Opret `Pages/Shared/_LoginPartial.cshtml`.
   - Funktion:
     - Hvis brugeren er autentificeret:
       - Vis knappen "Log ud", som poster til `Auth/Logout` med et antiforgery-token.
     - Hvis brugeren ikke er autentificeret:
       - Vis linket "Log ind", som peger på `Auth/Login`.

5) Føj partialen til layoutet:
   - Opdatér `Pages/Shared/_Layout.cshtml`, så den indeholder:
     - `<partial name="_LoginPartial" />` i navigationsområdet, helst højrestillet i navbaren.
   - Fjern ikke eksisterende indhold fra layoutet.

6) Forsidens funktion (visning af claims):
   - Hvis MODE = "NEW_APP", eller hvis den eksisterende forside reelt er tom og kun indeholder boilerplate eller intet meningsfuldt indhold:
     - Implementér en enkel forside, der:
       - Byder brugeren velkommen.
       - Viser en liste eller tabel med brugerens claims (type og værdi), hvis brugeren er autentificeret.
       - Viser en besked som "Du er ikke logget ind" og en opfordring til at vælge loginlinket, hvis brugeren ikke er autentificeret.
   - Hvis MODE = "EXISTING_APP", og forsiden allerede har meningsfuldt indhold:
     - Tilføj ikke visning af claims på den eksisterende forside.
     - Bevar forsidens eksisterende indhold uændret.

### Krav til output

1) Kode- og filændringer:
   - Angiv alle filer, der er oprettet eller ændret.
   - Vis hele filindholdet for hver fil eller en meget tydelig diff, hvis filen er stor.
   - Sørg for, at projektet kan bygges og køres med `dotnet run` eller den sædvanlige kommando for det valgte target framework.

2) Placering og vejledning til konfiguration:
   - Vis tydeligt og præcist, hvor konfigurationsværdierne Authority, ClientId og ClientSecret læses i koden (`IdentitySettings` sektionen).
   - Forklar brugeren:
     - At værdierne skal angives, efter koden er genereret.
     - Hvordan Authority og ClientId angives i appsettings.json.
     - Hvordan ClientSecret gemmes lokalt i user-secrets eller i en miljøvariabel eller et sikkert hemmelighedslager i produktion.

3) Oplysninger om applikationens endpoint:
   - Angiv udtrykkeligt i det endelige svar til brugeren:
     - Den lokale endpoint URL, som applikationen lytter på, eksempelvis `{{APP_BASE_URL}}` eller den URL, som skabelonen bruger.
     - En kort og tydelig instruktion til brugeren:
       - “Konfigurér FoxIDs Authority og ClientId i `IdentitySettings` sektionen. Gem ClientSecret lokalt i user-secrets eller i en miljøvariabel eller et sikkert hemmelighedslager i produktion, så værdien kan læses under kørsel uden at blive tilføjet til versionsstyring.”

4) Afgrænsning:
   - Foretag ikke refaktorering, der ikke vedrører opgaven.
   - Fjern ikke eksisterende funktionalitet ud over det, der er strengt nødvendigt for at integrere OIDC med FoxIDs.
   - Hold løsningen fokuseret på:
     - Tilføjelse af cookie + OIDC autentifikation,
     - AuthController,
     - Login partial,
     - De beskrevne minimale ændringer af forsiden.

Implementér nu alt ovenstående.

AI-svaret skal forklare, hvor Authority, Client ID og Client Secret konfigureres.

Kør nu applikationen for at finde dens endpoint.

Min eksempelapplikation kører lokalt på https://localhost:7154/.

AI-genereret ASP.NET Core applikation med OpenID Connect

Den AI-genererede eksempelkode findes på GitHub.

Konfigurér webapplikationen i FoxIDs

Nu kender vi webapplikationens lokale adresse og kan registrere den i FoxIDs, så den kan autentificere brugere gennem OpenID Connect.

  1. Vælg fanen Applications i FoxIDs miljøet.
  2. Vælg New application og derefter Web application — OpenID Connect.
  3. Angiv et navn under Name, eksempelvis ASP.NET web application.
  4. Tilføj applikationens basisadresse under Redirect URI: https://localhost:7154/ FoxIDs tillader som standard omdirigering til efterfølgende sider under denne basisadresse. I kan kræve absolutte redirect URI'er, hvis valideringen skal være mere restriktiv.
  5. Vælg Create.
Tilføj applikation i FoxIDs

FoxIDs viser nu forbindelsesoplysningerne til den nye applikation, herunder:

  • Authority
  • Client ID
  • Client Secret
Applikation oprettet i FoxIDs

Kopiér Authority og Client ID til projektets IdentitySettings sektion. Gem Client Secret lokalt i .NET user-secrets eller i en sikker miljøvariabel eller secret store i produktion.

Konfigurér autentifikation i ASP.NET applikationen

Når FoxIDs applikationen er oprettet, skal autentifikation konfigureres i ASP.NET Core projektet.

Tilføj de ikke-fortrolige FoxIDs forbindelsesoplysninger i appsettings.json:

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

Gem client secret lokalt uden at føje den til appsettings.json:

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

Erstat eksempelværdierne med værdierne fra jeres eget FoxIDs miljø, og commit aldrig den rigtige client secret.

Log ind

Vælg Log in. I bliver omdirigeret til FoxIDs loginskærmen.

Vælg Create user.

FoxIDs loginskærm

Udfyld formularen Create user med jeres e-mailadresse eller en testadresse, I har adgang til, samt fornavn og efternavn. Vælg derefter Create.

Opret en testbruger

Indtast det engangskodeord (OTP), I har modtaget via e-mail, og vælg Log in.

Login med engangskodeord (OTP)

I er nu logget ind, og testbrugerens claims vises.

Brugeren er logget ind, og claims vises

Prøv til sidst at logge ud og ind igen for at gennemføre det adgangskodefri loginflow med e-mail OTP.