Nowoczesne aplikacje w coraz większym stopniu odchodzą od tradycyjnych haseł na rzecz metod uwierzytelniania bez hasła, które są zarówno bezpieczniejsze, jak i łatwiejsze dla użytkowników. W tym poście pokażę, jak uwierzytelniać użytkowników w aplikacji ASP.NET Core wygenerowanej przez sztuczną inteligencję przy użyciu FoxIDs z OpenID Connect i umożliwić logowanie się całkowicie bez hasła przy użyciu jednorazowych kodów dostarczanych pocztą elektroniczną.

Zaczniemy od czystego środowiska FoxIDs, stworzymy nową aplikację internetową ASP.NET Core, połączymy ją z OpenID Connect, a na koniec umożliwimy logowanie passwordless za pomocą OTP opartego na e-mailu.

Tworzenie środowiska deweloperskiego FoxIDs

Zacząłem od stworzenia nowego, pustego środowiska programistycznego w FoxIDs. Czyste środowisko ułatwia skonfigurowanie uwierzytelniania od podstaw i zapewnia możliwość powtórzenia tych kroków we własnym tenancie.

Puste środowisko FoxIDs

Jeśli nie korzystałeś wcześniej z FoxIDs, możesz stworzyć darmowy tenant pod adresem:

https://www.foxids.com

Każdy tenant ma dwa gotowe do użycia środowiska, dzięki czemu możesz swobodnie eksperymentować.

Skonfiguruj uwierzytelnianie

Zacznij od configuring, jak użytkownicy powinni się logować. W tym przypadku chcemy, aby użytkownicy logowali się bez hasła, używając jedynie adresu e-mail i przesłanego im hasła jednorazowego (OTP).

  1. Wybierz zakładkę Uwierzytelnianie w swoim środowisku FoxIDs.
  2. Kliknij Domyślny — interfejs logowania użytkownika.
  3. W sekcji Uwierzytelnianie wyłącz Uwierzytelnianie hasłem i włącz Bez hasła za pomocą poczty elektronicznej (hasło jednorazowe).
  4. Kliknij Aktualizuj, aby zapisać zmiany.
Skonfiguruj metodę logowania uwierzytelniającego

Umożliwia to użytkownikom utworzenie nowego konta i zapewnia obsługę bez hasła, podczas której uwierzytelniają się, po prostu wprowadzając swój adres e-mail i otrzymany OTP.

Wygeneruj aplikację ASP.NET Core

Następnie potrzebujemy aplikacji do uwierzytelnienia. Możesz użyć podpowiedzi AI do wygenerowania nowej aplikacji ASP.NET Core Razor Pages przeznaczonej dla .NET 10 lub dodać OpenID Connect do istniejącej aplikacji.

Przeczytaj post „Uwierzytelnianie bez hasła w ASP.NET Core za pomocą FoxIDs i OTP”, jeśli chcesz ręcznie utworzyć aplikację ASP.NET Core.

Na potrzeby tego przewodnika generuję prostą aplikację ASP.NET Core w VS Code z Codexem. Możesz także użyć Copilot.

Jesteś ekspertem programisty ASP.NET Core.

Cel: Utworzyć (lub zaktualizować) aplikację internetową ASP.NET Core, która uwierzytelnia użytkowników za pomocą FoxIDs przy użyciu OpenID Connect (przepływ kodu autoryzacyjnego), używając uwierzytelniania plików cookie dla sesji lokalnej i OIDC jako schematu wyzwania.

### Tryb (wybierz jeden)
- MODE = "NEW_APP" -> utwórz nową aplikację Razor Pages
- MODE = "EXISTING_APP" -> zmodyfikuj bieżące rozwiązanie bez przerywania istniejących tras/stron

MODE: {{MODE}}

### Szczegóły aplikacji
- ProjectName: {{PROJECT_NAME}} (używane tylko wtedy, gdy MODE = "NEW_APP")
- TargetFramework: net10.0 (lub zachowaj istniejący, jeśli jest nowszy)
- Lokalny adres URL HTTPS (musi pasować do adresu bazowego URI przekierowania FoxIDs): {{APP_BASE_URL}} (przykład: https://localhost:7283/)

### Konfiguracja FoxIDs OIDC
Nie koduj na stałe Authority, ClientId ani ClientSecret w kodzie ani w tym wierszu.
Zamiast:
- Przeczytaj je z kluczy konfiguracyjnych:
  - "IdentitySettings:Authority"
  - "IdentitySettings:ClientId"
  - "IdentitySettings:ClientSecret"
- Ostateczna odpowiedź musi jasno wyjaśniać użytkownikowi, gdzie i jak ustawić te wartości konfiguracyjne (na przykład w appsettings.json, zmienne środowiskowe lub sekrety użytkownika).

### Wymagania wdrożeniowe

1) Dodaj uwierzytelnianie w Program.cs:
   - Skonfiguruj uwierzytelnianie:
     - DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme
     - DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme
   - Dodaj uwierzytelnianie plików cookie.
   - Dodaj uwierzytelnianie OpenID Connect:
     - Authority z konfiguracji: "IdentitySettings:Authority"
     - ClientId z konfiguracji: "IdentitySettings:ClientId"
     - ClientSecret z konfiguracji: "IdentitySettings:ClientSecret"
     - ResponseType = "code"
     - SaveTokens = true
     - Scopes: "openid", "profile", "email", "offline_access"
     - MapInboundClaims = false
     - TokenValidationParameters:
       - NameClaimType = "sub"
       - RoleClaimType = "role"
   - Dodaj OpenIdConnectEvents za pomocą:
     - OnAuthenticationFailed: tylko w Development, zwraca prostą odpowiedź w postaci zwykłego tekstu z komunikatem o wyjątku na potrzeby debugowania. Nigdy nie ujawniaj szczegółów wyjątków ani PII w produkcji.
   - Upewnij się, że oprogramowanie pośrednie jest zarejestrowane:
     - app.UseAuthentication() jest wywoływany przed app.UseAuthorization().

2) Dodaj okablowanie konfiguracyjne:
   - Dodaj sekcję `IdentitySettings` w appsettings.json zawierającą tylko nietajne wartości zastępcze, na przykład:
     - "Authority": "https://your-foxids-authority/"
     - "ClientId": "your-client-id"
   - Odczytaj "IdentitySettings:ClientSecret" z konfiguracji, ale zapisz jego wartość w kluczach użytkownika .NET na potrzeby lokalnego programowania lub zmiennej środowiskowej lub zabezpiecz magazyn tajnych sekretów w środowisku produkcyjnym.
   - Jeśli MODE = "EXISTING_APP", połącz tę sekcję z istniejącą konfiguracją bez nadpisywania niepowiązanych ustawień.
   - Dodaj komentarze lub tekst wyjaśniający do ostatecznej odpowiedzi, że:
     - Wartości te użytkownik musi zastąpić ich rzeczywistymi wartościami FoxIDs Authority, ClientId i ClientSecret.
     - Wpisów tajnych nie wolno zapisywać w appsettings.json ani przekazywać do kontroli źródła.

3) Dodaj punkty końcowe logowania/wylogowania:
   - Utwórz `Controllers/AuthController.cs` ze standardowym kontrolerem MVC:
     - Użyj wzoru trasy `[controller]/[action]`.
   - Akcja logowania (GET):
     - Jeśli użytkownik jest już uwierzytelniony, przekieruj do "/".
     - W przeciwnym razie wyślij Challenge, używając OpenIdConnectDefaults.AuthenticationScheme z RedirectUri = "/".
   - Akcja wylogowania (POST, z [ValidateAntiForgeryToken]):
     - Jeśli użytkownik nie jest uwierzytelniony, przekieruj do "/".
     - W przeciwnym razie SignOut z:
       - CookieAuthenticationDefaults.AuthenticationScheme i
       - OpenIdConnectDefaults.AuthenticationScheme
z RedirectUri = "/".

4) Dodaj częściowe logowanie do interfejsu użytkownika:
   - Utwórz `Pages/Shared/_LoginPartial.cshtml`.
   - Zachowanie:
     - Jeśli użytkownik jest uwierzytelniony:
       - Wyświetl przycisk „Wyloguj”, który wysyła wiadomość do `Auth/Logout` z tokenem zabezpieczającym przed fałszerstwem.
     - Jeśli użytkownik nie jest uwierzytelniony:
       - Pokaż łącze „Zaloguj się” wskazujące na `Auth/Login`.

5) Dodaj część do układu:
   - Zaktualizuj `Pages/Shared/_Layout.cshtml`, aby uwzględnić:
     - `<partial name="_LoginPartial" />` w obszarze paska nawigacyjnego, najlepiej wyrównanego do prawej strony paska nawigacyjnego.
   - Nie usuwaj istniejącej zawartości układu.

6) Zachowanie strony głównej (w przypadku wyświetlania claims):
   - Jeśli MODE = "NEW_APP" lub jeśli istniejąca strona główna jest faktycznie pusta (tylko szablon lub brak znaczącej treści):
     - Zaimplementuj prostą stronę główną, która:
       - Wita użytkownika.
       - Jeśli użytkownik jest uwierzytelniony, wyświetla listę lub tabelę claims użytkownika (typ i wartość).
       - Jeśli użytkownik nie jest uwierzytelniony, wyświetla komunikat „Nie jesteś zalogowany” i podpowiedź, aby kliknąć link logowania.
   - Jeśli MODE = "EXISTING_APP" i strona główna zawiera już znaczącą treść:
     - Nie modyfikuj istniejącej strony głównej w celu dodania wyświetlania claims.
     - Pozostaw istniejącą treść strony głównej nienaruszoną.

### Oczekiwania wyjściowe

1) Zmiany w kodzie i pliku:
   - Wyświetl listę wszystkich utworzonych lub zmodyfikowanych plików.
   - Dla każdego pliku wypisz całą zawartość pliku (lub bardzo wyraźną różnicę, jeśli plik jest duży).
   - Upewnij się, że projekt można skompilować i uruchomić za pomocą `dotnet run` (lub zwyczajowego polecenia dla wybranej platformy docelowej).

2) Umiejscowienie konfiguracji i wskazówki:
   - Wyraźnie pokaż, gdzie w kodzie odczytywane są wartości konfiguracyjne Authority, ClientId i ClientSecret (sekcja IdentitySettings).
   - Wyjaśnij użytkownikowi:
     - Że muszą ustawić te wartości po wygenerowaniu kodu.
     - Jak ustawić Authority i ClientId w appsettings.json.
     - Jak ustawić ClientSecret w kluczach użytkownika lokalnie lub w zmiennej środowiskowej lub zabezpieczyć tajny magazyn w środowisku produkcyjnym.

3) Informacje o punkcie końcowym aplikacji:
   - W ostatecznej odpowiedzi skierowanej do użytkownika wyraźnie określ:
     - Adres URL lokalnego punktu końcowego, na którym nasłuchuje aplikacja (na przykład: `{{APP_BASE_URL}}` lub adres URL używany przez szablon).
     - Krótka, jasna instrukcja informująca użytkownika:
       - "Skonfiguruj swoje FoxIDs Authority i ClientId w sekcji IdentitySettings. Przechowuj ClientSecret w kluczach użytkownika lokalnie lub w zmiennej środowiskowej lub bezpiecznym magazynie sekretów w środowisku produkcyjnym, aby można było je odczytać w czasie wykonywania bez konieczności zatwierdzania. "

4) Poręcze:
   - Nie wprowadzaj niepowiązanej refaktoryzacji.
   - Nie usuwaj żadnych istniejących funkcji poza tym, co jest ściśle wymagane do integracji OIDC z FoxIDs.
   - Koncentruj się na rozwiązaniu:
     - Dodanie ciasteczka + uwierzytelnianie OIDC,
     - AuthController,
     - Logowanie częściowe,
     - Minimalne zmiany na stronie głównej zgodnie z opisem.

Teraz zastosuj wszystkie powyższe.

Odpowiedź AI powinna poinstruować Cię, gdzie skonfigurować Authority, identyfikator klienta i klucz tajny klienta.

Teraz spróbuj uruchomić aplikację, aby znaleźć punkt końcowy.

Moja przykładowa aplikacja działa lokalnie na https://localhost:7154/

AI wygenerowała podstawową aplikację ASP.NET za pomocą OpenID Connect

Przykładowy kod wygenerowany przez sztuczną inteligencję można znaleźć w: https://github.com/ITfoxtec/dotnet.samples/tree/main/WebAppPasswordLessEmailAI

Skonfiguruj aplikację internetową w FoxIDs

Teraz, gdy znamy lokalny adres aplikacji internetowej, możemy ją zarejestrować w FoxIDs, aby mogła uwierzytelniać użytkowników poprzez OpenID Connect.

  1. Wybierz zakładkę Aplikacje w swoim środowisku FoxIDs.
  2. Wybierz Nowa aplikacja, a następnie wybierz Aplikacja internetowa — OpenID Connect.
  3. W polu Nazwa wpisz nazwę, np.: Aplikacja internetowa ASP.NET.
  4. W Redirect URI dodaj adres bazowy aplikacji: https://localhost:7154/ Domyślnie FoxIDs umożliwia przekierowanie do dowolnej kolejnej strony pod tym bazowym adresem URL. Jeśli wolisz bardziej rygorystyczną weryfikację, możesz wymagać bezwzględnych identyfikatorów URI przekierowań.
  5. Kliknij Utwórz.
Dodaj aplikację w FoxIDs

FoxIDs wyświetla teraz szczegóły połączenia dla Twojej nowej aplikacji, w tym:

  • Authority
  • Identyfikator klienta
  • Tajemnica klienta
Aplikacja stworzona w FoxIDs

Skopiuj Authority i Identyfikator klienta do sekcji IdentitySettings projektu. Przechowuj Tajemnicę klienta w kluczach użytkownika .NET lokalnie lub w bezpiecznej zmiennej środowiskowej lub magazynie sekretów w środowisku produkcyjnym.

Skonfiguruj uwierzytelnianie w aplikacji ASP.NET

Po utworzeniu aplikacji FoxIDs kolejnym krokiem jest skonfigurowanie uwierzytelnienia w projekcie ASP.NET Core.

Dodaj niejawne szczegóły połączenia FoxIDs do appsettings.json:

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

Przechowuj klucz tajny klienta lokalnie, bez dodawania go do appsettings.json:

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

Zastąp przykładowe wartości wartościami z własnego środowiska FoxIDs i nigdy nie udostępniaj prawdziwego sekretu klienta.

Zaloguj się

Kliknij Zaloguj się, a nastąpi przekierowanie do ekranu logowania FoxIDs.

Wybierz Utwórz użytkownika.

Ekran logowania FoxIDs

Wypełnij formularz Utwórz użytkownika, podając swój adres e-mail (lub e-mail testowy, do którego masz dostęp), imię i nazwisko, a następnie kliknij Utwórz.

Utwórz użytkownika testowego

Wpisz hasło jednorazowe (OTP) otrzymane e-mailem, a następnie kliknij Zaloguj się.

Zaloguj się hasłem jednorazowym (OTP)

Jesteś zalogowany i wyświetlane są claims Twojego użytkownika testowego.

Zalogowany, pokaż claims

Następnie spróbuj się wylogować i zalogować ponownie, aby doświadczyć procesu logowania bez hasła przy użyciu adresu e-mail OTP.