Delen via


Zelfstudie: Gebruikers aanmelden bij een React-app met één pagina met behulp van systeemeigen verificatie (preview)

Van toepassing op: Groene cirkel met een wit vinkje dat aangeeft dat de volgende inhoud van toepassing is op externe tenants. Externe tenants (meer informatie)

In deze zelfstudie leert u hoe u gebruikers kunt aanmelden bij een React-app met één pagina (SPA) met behulp van systeemeigen verificatie.

In deze handleiding leert u:

  • Werk de React-app bij om gebruikers aan te melden met gebruikersnaam(e-mailadres) en wachtwoord.
  • Aanmeldingsstroom testen.

Voorwaarden

Typen aanroepen definiëren die door de app worden uitgevoerd naar de systeemeigen verificatie-API

Tijdens de aanmeldingsstroom voert de app meerdere aanroepen uit naar de systeemeigen verificatie-API, zoals het starten van een aanmeldingsaanvraag, het selecteren van een verificatiemethode en het aanvragen van beveiligingstokens.

Als u deze aanroepen wilt definiëren, opent u het bestand scr/client/RequestTypes.ts en voegt u het volgende codefragment toe:

   export interface TokenRequestType {
        continuation_token: string;
        client_id: string;
        grant_type: string;
        scope: string;
        password?: string;
        oob?: string;
        challenge_type?: string;
    }

    // Sign in
    export interface TokenSignInType {
        continuation_token: string;
        grant_type: string;
        password?: string;
        oob?: string;
    }

    export interface ChallengeRequest {
        client_id: string;
        challenge_type: string;
        continuation_token: string;
    }

    export interface SignInStartRequest {
        client_id: string;
        challenge_type: string;
        username: string;
    }

    export interface SignInTokenRequest {
        client_id: string;
        grant_type: string;
        continuation_token: string;
        scope: string;
        challenge_type?: string;
        password?: string;
        oob?: string;
    }

Het type antwoorden definiëren dat de app ontvangt van de systeemeigen verificatie-API

Als u het type antwoorden wilt definiëren dat de app kan ontvangen van de systeemeigen verificatie-API voor de aanmeldingsbewerking, opent u het bestand src/client/ResponseTypes.ts en voegt u vervolgens het volgende codefragment toe:

    export interface TokenResponseType {
        token_type: string;
        scope: string;
        expires_in: number;
        access_token: string;
        refresh_token: string;
        id_token: string;
    }

Aanmeldingsaanvragen verwerken

In deze sectie voegt u code toe waarmee aanmeldingsstroomaanvragen worden verwerkt. Voorbeelden van deze aanvragen zijn het starten van een aanmeldingsstroom, het selecteren van een verificatiemethode of het aanvragen van een beveiligingstoken.

Hiervoor maakt u een bestand met de naam src/client/SignInService.tsen voegt u het volgende codefragment toe:

    import { CLIENT_ID, ENV } from "../config";
    import { postRequest } from "./RequestClient";
    import { ChallengeRequest, SignInStartRequest, TokenRequestType, TokenSignInType } from "./RequestTypes";
    import { TokenResponseType } from "./ResponseTypes";

    export const signInStart = async ({ username }: { username: string }) => {
        const payloadExt: SignInStartRequest = {
            username,
            client_id: CLIENT_ID,
            challenge_type: "password oob redirect",
        };

        return await postRequest(ENV.urlOauthInit, payloadExt);
    };

    export const signInChallenge = async ({ continuation_token }: { continuation_token: string }) => {
        const payloadExt: ChallengeRequest = {
            continuation_token,
            client_id: CLIENT_ID,
            challenge_type: "password oob redirect",
        };

        return await postRequest(ENV.urlOauthChallenge, payloadExt);
    };

    export const signInTokenRequest = async (request: TokenSignInType): Promise<TokenResponseType> => {
        const payloadExt: TokenRequestType = {
            ...request,
            client_id: CLIENT_ID,
            challenge_type: "password oob redirect",
            scope: "openid offline_access",
        };

        if (request.grant_type === "password") {
            payloadExt.password = request.password;
        }

        if (request.grant_type === "oob") {
            payloadExt.oob = request.oob;
        }

        return await postRequest(ENV.urlOauthToken, payloadExt);
    };

De eigenschap challenge_type toont de verificatiemethoden die door de client-app worden ondersteund. Deze app meldt zich aan met e-mail met een wachtwoord, dus de waarde van het vraagtype is omleiding van het wachtwoord. Lees meer over uitdagingstypen.

UI-onderdelen maken

Tijdens het aanmeldingsproces verzamelt deze app de inloggegevens van de gebruiker, waaronder hun gebruikersnaam (e-mailadres) en wachtwoord, om de gebruiker aan te melden. Nadat de gebruiker zich heeft aangemeld, worden de gegevens van de gebruiker weergegeven in de app.

  1. Maak een map met de naam /pages/signin in de map src.

  2. Als u het aanmeldingsformulier wilt maken, weergeven en verzenden, maakt u een bestand src/pages/signin/SignIn.tsxen voegt u de volgende code toe:

        import React, { useState } from "react";
        import { Link as LinkTo, useNavigate } from "react-router-dom";
        import { signInStart, signInChallenge, signInTokenRequest } from "../../client/SignInService";
        import { ErrorResponseType } from "../../client/ResponseTypes";
    
        export const SignIn: React.FC = () => {
          const [email, setEmail] = useState<string>("");
          const [password, setPassword] = useState<string>("");
          const [error, setError] = useState<string>("");
          const [isLoading, setIsloading] = useState<boolean>(false);
    
          const navigate = useNavigate();
          const validateEmail = (email: string): boolean => {
            const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
            return re.test(String(email).toLowerCase());
          };
    
          const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
            e.preventDefault();
            if (!validateEmail(email)) {
              setError("Invalid email format");
              return;
            }
            setError("");
            setIsloading(true);
            try {
              const res1 = await signInStart({
                username: email,
              });
              const res2 = await signInChallenge({ continuation_token: res1.continuation_token });
              const res3 = await signInTokenRequest({
                continuation_token: res2.continuation_token,
                grant_type: "password",
                password: password,
              });
              navigate("/user", { state: res3 });
            } catch (err) {
              setError("An error has occured " + (err as ErrorResponseType).error_description);
            } finally {
              setIsloading(false);
            }
          };
    
          return (
            <div className="login-form">
              <form onSubmit={handleSubmit}>
                <h2>Login</h2>
                <div className="form-group">
                  <label>Email:</label>
                  <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
                </div>
                <div className="form-group">
                  <label>Password:</label>
                  <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} required />
                </div>
                {error && <div className="error">{error}</div>}
                {isLoading && <div className="warning">Sending request...</div>}
                <button type="submit" disabled={isLoading}>Login</button>
              </form>
            </div>
          );
        };
    
  3. De details van de gebruiker weergeven na een geslaagde aanmelding:

    1. Maak een bestand met de naam client/Utils.tsen voeg vervolgens het volgende codefragment toe:

          export function parseJwt(token: string) {
              var base64Url = token.split(".")[1];
              var base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
              var jsonPayload = decodeURIComponent(
                  window
                  .atob(base64)
                  .split("")
                  .map(function (c) {
                      return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
                  })
                  .join("")
              );
              return JSON.parse(jsonPayload);
          }
      
    2. Maak een map met de naam gebruiker in de map src/pages.

    3. Maak een bestand met de naam src/pages/user/UserInfo.tsxen voeg vervolgens het volgende codefragment toe:

      // User.tsx
      import React from "react";
      import { useLocation } from "react-router-dom";
      import { parseJwt } from "../../client/Utils";
      
      export const UserInfo: React.FC = () => {
        const { state } = useLocation();
        const decodedToken = parseJwt(state.access_token);
        const { given_name, scp, family_name, unique_name: email } = decodedToken;
      
        console.log(decodedToken);
        const familyName = family_name;
        const givenName = given_name;
        const tokenExpireTime = state.expires_in;
        const scopes = state.scope;
      
        return (
          <div className="user-info">
            <h2>User Information</h2>
            <div className="info-group">
              <label>Given Name:</label>
              <span>{givenName}</span>
            </div>
            <div className="info-group">
              <label>Family Name:</label>
              <span>{familyName}</span>
            </div>
            <div className="info-group">
              <label>Email:</label>
              <span>{email}</span>
            </div>
            <div className="info-group">
              <label>Token Expire Time:</label>
              <span>{tokenExpireTime}</span>
            </div>
            <div className="info-group">
              <label>Scopes:</label>
              <span>{scopes}</span>
            </div>
            <div className="info-group">
              <label>Token payload:</label>
              <span><pre>{JSON.stringify(decodedToken, null, 2)}</pre></span>
            </div>
          </div>
        );
      };
      

App-routes toevoegen

Open het bestand src/AppRoutes.tsx en vervang de inhoud door de volgende code:

import { Route, Routes } from "react-router-dom";
import { SignIn } from "./pages/SignIn/SignIn";
import { UserInfo } from "./pages/User/UserInfo";
import { SignUp } from "./pages/SignUp/SignUp";
import { SignUpChallenge } from "./pages/SignUp/SignUpChallenge";
import { SignUpCompleted } from "./pages/SignUp/SignUpCompleted";
//For password reset
//import { ResetPassword } from "./pages/ResetAccount/ResetPassword";

export const AppRoutes = () => {
  return (
    <Routes>
      <Route path="/" element={<SignUp />} />
      <Route path="/signin" element={<SignIn />} />
      <Route path="/user" element={<UserInfo />} />
      <Route path="/signup" element={<SignUp />} />
      <Route path="/signup/challenge" element={<SignUpChallenge />} />
      <Route path="/signup/completed" element={<SignUpCompleted />} />
      //For password reset
      //<Route path="/reset" element={<ResetPassword />} />
    </Routes>
  );
};

Uw app uitvoeren en testen

Gebruik de stappen in De app uitvoeren en testen om uw app uit te voeren, maar test deze keer het aanmeldproces met het gebruikersaccount dat u eerder registreerde.

Aanmelden met een alias of gebruikersnaam inschakelen

U kunt gebruikers toestaan die zich aanmelden met een e-mailadres en wachtwoord, zich ook aan te melden met een gebruikersnaam en wachtwoord. De gebruikersnaam wordt ook wel een alternatieve aanmeldings-id genoemd, kan een klant-id, accountnummer of een andere id zijn die u als gebruikersnaam wilt gebruiken.

U kunt gebruikersnamen handmatig toewijzen aan het gebruikersaccount via het Microsoft Entra-beheercentrum of deze automatiseren in uw app via de Microsoft Graph API.

Gebruik de stappen in Aanmelden met een alias of gebruikersnaam-artikel om uw gebruikers toe te staan zich aan te melden met behulp van een gebruikersnaam in uw toepassing:

  1. Schakel gebruikersnaam in bij het inloggen.
  2. Maak gebruikers aan met een gebruikersnaam in het beheercentrum of werk bestaande gebruikers bij door een gebruikersnaam toe te voegen. Je kunt ook het aanmaken en updaten van gebruikers in je app automatiseren door gebruik te maken van de Microsoft Graph API.

Volgende stap