De knop Aanmelding voor Microsoft-verificatie toevoegen aan een toepassing met één pagina

Voeg Microsoft-verificatie toe in deze TypeScript-zelfstudie om een aanmeldings-/logout-knop op te geven. Ontwikkel de toepassing met de Azure-SDK aan de clientzijde, @azure/msal-browser , om verificatiefunctionaliteit te bieden.

Toepassingsarchitectuur en -functionaliteit

De spa die in deze zelfstudie is gebouwd, is een React-app (create-react-app) met de volgende taken:

  • Meld u aan met een door Microsoft ondersteunde aanmelding, zoals Office 365 of Outlook.com
  • Afmelden bij de toepassing

Voor een snelle en eenvoudige toepassing met één pagina maakt het voorbeeld gebruik van create-react-app met TypeScript. Dit front-end-framework biedt verschillende snelkoppelingen in typische clientontwikkeling met Azure SDK's:

  • Bundeling, vereist voor Azure SDK's die worden gebruikt in een clienttoepassing
  • Omgevingsvariabelen in het .env bestand

1. Ontwikkelomgeving instellen

Controleer of de volgende software is geïnstalleerd op uw lokale computer.

2. Waarde behouden voor omgevingsvariabele

Plaats een plaats waar u de client-id van uw app-registratie kunt kopiëren, zoals een tekstbestand. U krijgt deze client-id in stap 5 van de volgende sectie. De waarde wordt gebruikt als een omgevingsvariabele voor de web-app.

3. App-registratie voor verificatie maken

  1. Meld u aan Azure Portal voor de standaardmap van App-registraties.

  2. Selecteer + Nieuwe registratie.

  3. Voer uw app-registratiegegevens in met behulp van de volgende tabel:

    Veld Waarde Beschrijving
    Name Simple Auth Tutorial Dit is de naam die gebruikers van de app zien op het machtigingsformulier wanneer ze zich aanmelden bij uw app.
    Ondersteunde accounttypen Accounts in elke organisatiemap (elke Azure AD-directory - multitenant) en persoonlijke Microsoft-accounts Dit heeft betrekking op de meeste accounttypen.
    Omleidings-URI-type Toepassing met één pagina
    Omleidings-URI-waarde http://localhost:3000 De URL om naar terug te keren nadat de verificatie is geslaagd of mislukt.

    Nieuwe Azure-app-registratie.

  4. Selecteer Registreren. Wacht tot het registratieproces van de app is voltooid.

  5. Kopieer de toepassings-id (client-id) uit de sectie Overzicht van de app-registratie. U voegt deze waarde later toe aan uw omgevingsvariabele voor de client-app.

4. Een toepassing React één pagina maken voor TypeScript

  1. Maak in een Bash-shell een create-react-app met behulp van TypeScript als taal:

    npx create-react-app tutorial-demo-login-button --template typescript
    
  2. Wijzig in de nieuwe map en installeer het @azure/msal-browser verificatiepakket:

    cd tutorial-demo-login-button && npm install @azure/msal-browser
    
  3. Maak een .env bestand op hoofdniveau en voeg de volgende regel toe:

    REACT_APP_AZURE_ACTIVE_DIRECTORY_APP_CLIENT_ID=
    

    Het .env bestand wordt gelezen als onderdeel van het framework create-react-app. In dit bestand kunt u de client-id opslaan voor lokale ontwikkeling.

  4. Kopieer de toepassings-id (client-id) naar de waarde .

5. Knoppen voor aanmelden en aanmelden toevoegen

  1. Maak in de map een submap met de naam azure voor de azure-specifieke ./src bestanden.

  2. Maak een nieuw bestand voor verificatieconfiguratie in de map met de azure naam en kopieer de volgende azure-authentication-config.ts code:

    import { Configuration, LogLevel } from "@azure/msal-browser";
    
    const AzureActiveDirectoryAppClientId: any =
      process.env.REACT_APP_AZURE_ACTIVE_DIRECTORY_APP_CLIENT_ID;
    
    export const MSAL_CONFIG: Configuration = {
      auth: {
        clientId: AzureActiveDirectoryAppClientId,
      },
      cache: {
        cacheLocation: "sessionStorage",
        storeAuthStateInCookie: false,
      },
      system: {
        loggerOptions: {
          loggerCallback: (level, message, containsPii) => {
            if (containsPii) {
              return;
            }
            switch (level) {
              case LogLevel.Error:
                console.error(message);
                return;
              case LogLevel.Info:
                console.info(message);
                return;
              case LogLevel.Verbose:
                console.debug(message);
                return;
              case LogLevel.Warning:
                console.warn(message);
                return;
            }
          },
        },
      },
    };
    

    Dit bestand leest uw toepassings-id uit het bestand, stelt de sessie in als de browseropslag in plaats van cookies en biedt logboekregistratie die rekening .env houden met persoonlijke gegevens.

  3. Maak een nieuw bestand voor de Azure-verificatie-middleware in de map met de naam azure en kopieer de volgende azure-authentication-context.ts code:

    import {
      PublicClientApplication,
      AuthenticationResult,
      AccountInfo,
      EndSessionRequest,
      RedirectRequest,
      PopupRequest,
    } from "@azure/msal-browser";
    
    import { MSAL_CONFIG } from "./azure-authentication-config";
    
    export class AzureAuthenticationContext {
      private myMSALObj: PublicClientApplication = new PublicClientApplication(
        MSAL_CONFIG
      );
      private account?: AccountInfo;
      private loginRedirectRequest?: RedirectRequest;
      private loginRequest?: PopupRequest;
    
      public isAuthenticationConfigured = false;
    
      constructor() {
        // @ts-ignore
        this.account = null;
        this.setRequestObjects();
        if (MSAL_CONFIG?.auth?.clientId) {
          this.isAuthenticationConfigured = true;
        }
      }
    
      private setRequestObjects(): void {
        this.loginRequest = {
          scopes: [],
          prompt: "select_account",
        };
    
        this.loginRedirectRequest = {
          ...this.loginRequest,
          redirectStartPage: window.location.href,
        };
      }
    
      login(signInType: string, setUser: any): void {
        if (signInType === "loginPopup") {
          this.myMSALObj
            .loginPopup(this.loginRequest)
            .then((resp: AuthenticationResult) => {
              this.handleResponse(resp, setUser);
            })
            .catch((err) => {
              console.error(err);
            });
        } else if (signInType === "loginRedirect") {
          this.myMSALObj.loginRedirect(this.loginRedirectRequest);
        }
      }
    
      logout(account: AccountInfo): void {
        const logOutRequest: EndSessionRequest = {
          account,
        };
    
        this.myMSALObj.logout(logOutRequest);
      }
      handleResponse(response: AuthenticationResult, incomingFunction: any) {
        if(response !==null && response.account !==null) {
          this.account = response.account;
        } else {
          this.account = this.getAccount();
        }
    
        if (this.account) {
          incomingFunction(this.account);
        }
      }
      private getAccount(): AccountInfo | undefined {
        console.log(`loadAuthModule`);
        const currentAccounts = this.myMSALObj.getAllAccounts();
        if (currentAccounts === null) {
          // @ts-ignore
          console.log("No accounts detected");
          return undefined;
        }
    
        if (currentAccounts.length > 1) {
          // TBD: Add choose account code here
          // @ts-ignore
          console.log(
            "Multiple accounts detected, need to add choose account code."
          );
          return currentAccounts[0];
        } else if (currentAccounts.length === 1) {
          return currentAccounts[0];
        }
      }
    }
    
    export default AzureAuthenticationContext;
    

    Dit bestand biedt de verificatie naar Azure voor een gebruiker met de login functies logout en .

  4. Maak een nieuw bestand voor het onderdeelbestand van de gebruikersinterfaceknop in de map met de naam azure en kopieer de volgende azure-authentication-component.tsx code:

    import React, { useState } from "react";
    import AzureAuthenticationContext from "./azure-authentication-context";
    import { AccountInfo } from "@azure/msal-browser";
    
    const ua = window.navigator.userAgent;
    const msie = ua.indexOf("MSIE ");
    const msie11 = ua.indexOf("Trident/");
    const isIE = msie > 0 || msie11 > 0;
    
    // Log In, Log Out button
    const AzureAuthenticationButton = ({ onAuthenticated }: any): JSX.Element => {
      // Azure client context
      const authenticationModule: AzureAuthenticationContext = new AzureAuthenticationContext();
    
      const [authenticated, setAuthenticated] = useState<Boolean>(false);
      const [user, setUser] = useState<AccountInfo>();
    
      const logIn = (method: string): any => {
        const typeName = "loginPopup";
        const logInType = isIE ? "loginRedirect" : typeName;
    
        // Azure Login
        authenticationModule.login(logInType, returnedAccountInfo);
      };
      const logOut = (): any => {
        if (user) {
          onAuthenticated(undefined);
          // Azure Logout
          authenticationModule.logout(user);
        }
      };
    
      const returnedAccountInfo = (user: AccountInfo) => {
        // set state
        setAuthenticated(user?.name ? true : false);
        onAuthenticated(user);
        setUser(user);
      };
    
      const showLogInButton = (): any => {
        return (
          <button id="authenticationButton" onClick={() => logIn("loginPopup")}>
            Log in
          </button>
        );
      };
    
      const showLogOutButton = (): any => {
        return (
          <div id="authenticationButtonDiv">
            <div id="authentication">
              <button id="authenticationButton" onClick={() => logOut()}>
                Log out
              </button>
            </div>
          </div>
        );
      };
    
      const showButton = (): any => {
        return authenticated ? showLogOutButton() : showLogInButton();
      };
    
      return (
        <div id="authentication">
          {authenticationModule.isAuthenticationConfigured ? (
            showButton()
          ) : (
            <div>Authentication Client ID is not configured.</div>
          )}
        </div>
      );
    };
    
    export default AzureAuthenticationButton;
    

    Dit knoponderdeel meldt een gebruiker aan en geeft het gebruikersaccount door aan het aanroepen/bovenliggende onderdeel.

    De knoptekst en functionaliteit worden in-/uitschakelen op basis van of de gebruiker momenteel is aangemeld, vastgelegd met de functie als een eigenschap die wordt doorgegeven onAuthenticated aan het onderdeel.

    Wanneer een gebruiker zich aanmeldt, roept de knop de methode van de Azure-verificatiebibliotheek aan, authenticationModule.login met returnedAccountInfo als de callback-functie. Het geretourneerde gebruikersaccount wordt vervolgens met de functie teruggestuurd naar het onAuthenticated bovenliggende onderdeel.

  5. Open het ./src/App.tsx bestand en vervang alle code door de volgende code om het onderdeel aanmeldings-/logout-knop op te nemen:

    import React, { useState } from "react";
    import AzureAuthenticationButton from "./azure/azure-authentication-component";
    import { AccountInfo } from "@azure/msal-browser";
    
    function App() {
      // current authenticated user
      const [currentUser, setCurrentUser] = useState<AccountInfo>();
    
      // authentication callback
      const onAuthenticated = async (userAccountInfo: AccountInfo) => {
        setCurrentUser(userAccountInfo);
      };
    
      // Render JSON data in readable format
      const PrettyPrintJson = ({ data }: any) => {
        return (
          <div>
            <pre>{JSON.stringify(data, null, 2)}</pre>
          </div>
        );
      };
    
      // Quick link - user revokes app's permission
      const ShowPermissionRevokeLinks = () => {
        return (
          <div>
            <div><a href="https://myapps.microsoft.com" target="_blank" rel="noopener">Revoke AAD permission</a></div>
            <div><a href="https://account.live.com/consent/manage" target="_blank" rel="noopener">Revoke Consumer permission</a></div>
          </div>
        );
      };
    
      return (
        <div id="App">
          <h2>Microsoft Login Button application</h2>
          <AzureAuthenticationButton onAuthenticated={onAuthenticated} />
          {currentUser && (
            <div>
              <PrettyPrintJson data={currentUser} />
              <ShowPermissionRevokeLinks />
            </div>
          )}
        </div>
      );
    }
    
    export default App;
    

    Nadat een gebruiker zich heeft aanmeldt en de verificatie wordt teruggeleid naar deze app, wordt het object currentUser weergegeven.

6. Een React spa-app uitvoeren met de aanmeldknop

  1. Start de app Visual Studio de terminal code:

    npm run start
    

    Bekijk de geïntegreerde VSCode voor de mededeling dat de app volledig is gestart.

    Compiled successfully!
    
    You can now view js-e2e-client-azure-login-button in the browser.
    
      Local:            http://localhost:3000
      On Your Network:  http://x.x.x.x:3000
    
    Note that the development build is not optimized.
    To create a production build, use yarn build.
    
  2. Open de web-app in een browser, http://localhost:3000 .

  3. Selecteer de knop Aanmelden in de webbrowser.

    Selecteer de knop **Aanmelden**.

  4. Selecteer een gebruikersaccount. Het hoeft niet hetzelfde account te zijn dat u hebt gebruikt voor toegang tot de Azure Portal, maar het moet wel een account zijn dat Microsoft-verificatie biedt.

    Selecteer een gebruikersaccount. Het hoeft niet hetzelfde account te zijn dat u hebt gebruikt voor toegang tot de Azure Portal, maar het moet een account zijn dat Microsoft-verificatie biedt.

  5. Bekijk het pop-upoverzicht met de 1) gebruikersnaam, 2) app-naam, 3) machtigingen waarmee u akkoord gaat en selecteer vervolgens Ja.

    Bekijk het pop-upoverzicht met de gebruikersnaam 1, 2) de app-naam, 3) de machtigingen waarmee u akkoord gaat en selecteer vervolgens Ja.

  6. Controleer de gebruikersaccountgegevens.

    Controleer de gebruikersaccountgegevens.

  7. Selecteer de knop Logout in de app. De app biedt ook handige koppelingen naar de Microsoft-gebruikers-apps om machtigingen in te trekken.

7. Toepassingsspecifieke gebruikersgegevens opslaan

U kunt de gebruikers-id desgewenst opslaan in uw eigen toepassingsdatabase om te correleren tussen de identiteit van de Microsoft-provider en de gegevens van de gebruiker die zijn vereist in uw eigen toepassing. De tokenclaim bevat twee ID's die u mogelijk wilt bijhouden:

  • sub:de id die specifiek is voor de gebruiker, voor uw specifieke Active Directory-app-id. Dit is de id die u moet opslaan in uw eigen toepassingsdatabase als u de gegevens van uw aangepaste app wilt correleren met de gebruiker van uw Microsoft Identity Provider.
  • oid:dit is de universele gebruikers-id voor alle apps in de Microsoft Identity-provider. Sla deze waarde op als u uw gebruiker wilt bijhouden in verschillende apps in de id-provider.

8. Resources opschonen

Wanneer u klaar bent met deze zelfstudie, verwijdert u de toepassing uit de lijst Azure Portal App-registratie.

Als u de app wilt behouden maar de machtiging die uw specifieke gebruikersaccount aan de app heeft verleend, wilt intrekken, gebruikt u een van de volgende koppelingen:

Volgende stappen