教學:使用原生認證 JavaScript SDK 註冊使用者加入 Angular 單頁應用程式

適用於: 帶有白色核取記號符號的綠色圓圈,表示下列內容適用於外部租用戶。 外部租用戶 (深入瞭解)

在本教學課程中,您將瞭解如何建置 Angular 單頁應用程式,以使用原生驗證的 JavaScript SDK 來註冊使用者。

在本教學課程中,您會:

  • 建立 Angular Next.js 專案。
  • 將 MSAL JS SDK 新增至其中。
  • 新增應用程式的UI元件。
  • 設定專案以註冊使用者。

先決條件

建立 React 專案並安裝相依性

在計算機中選擇的位置中,執行下列命令以建立名為 reactspa 的新 Angular 專案,流覽至專案資料夾,然後安裝套件:

ng new angularspa
cd angularspa

成功執行命令之後,您應該會有具有下列結構的應用程式:

angularspa/
└──node_modules/
   └──...
└──public/
   └──...
└──src/
   └──app/
      └──app.component.html
      └──app.component.scss
      └──app.component.ts
      └──app.modules.ts
      └──app.config.ts
      └──app.routes.ts
   └──index.html
   └──main.ts
   └──style.scss
└──angular.json
└──package-lock.json
└──package.json
└──README.md
└──tsconfig.app.json
└──tsconfig.json
└──tsconfig.spec.json

將 JavaScript SDK 新增至您的專案

若要在應用程式中使用原生驗證 JavaScript SDK,請使用您的終端機,使用下列命令進行安裝:

npm install @azure/msal-browser

原生驗證功能是 azure-msal-browser 程式庫的一部分。 若要使用原生驗證功能,您可以從 匯入 @azure/msal-browser/custom-auth。 例如:

  import CustomAuthPublicClientApplication from "@azure/msal-browser/custom-auth";

新增客戶端設定

在本節中,您會定義原生驗證公用用戶端應用程式的組態,使其能夠與 SDK 的介面互動。 若要這樣做,

  1. 建立名為 src/app/config/auth-config.ts 的檔案,然後新增下列程式代碼:

    export const customAuthConfig: CustomAuthConfiguration = {
        customAuth: {
            challengeTypes: ["password", "oob", "redirect"],
            authApiProxyUrl: "http://localhost:3001/api",
        },
        auth: {
            clientId: "Enter_the_Application_Id_Here",
            authority: "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com",
            redirectUri: "/",
            postLogoutRedirectUri: "/",
            navigateToLoginRequestUrl: false,
        },
        cache: {
            cacheLocation: "sessionStorage",
        },
        system: {
            loggerOptions: {
                loggerCallback: (level: LogLevel, message: string, containsPii: boolean) => {
                    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;
                    }
                },
            },
        },
    };
    

    在程式碼中,找出預留位置:

    • Enter_the_Application_Id_Here 然後將其替換為您先前註冊之應用程式的應用程式(用戶端)識別碼。

    • Enter_the_Tenant_Subdomain_Here 然後將其替換為您 Microsoft Entra 系統管理中心中的租用戶子網域。 例如,如果您的租戶主要網域為 contoso.onmicrosoft.com,則請使用 contoso。 如果您沒有租用戶名稱,請了解如何讀取租用戶詳細資料。

  2. 建立名為 src/app/services/auth.service.ts 的檔案,然後新增下列程式代碼:

    import { Injectable } from '@angular/core';
    import { CustomAuthPublicClientApplication, ICustomAuthPublicClientApplication } from '@azure/msal-browser/custom-auth';
    import { customAuthConfig } from '../config/auth-config';
    
    @Injectable({ providedIn: 'root' })
    export class AuthService {
      private authClientPromise: Promise<ICustomAuthPublicClientApplication>;
      private authClient: ICustomAuthPublicClientApplication | null = null;
    
      constructor() {
        this.authClientPromise = this.init();
      }
    
      private async init(): Promise<ICustomAuthPublicClientApplication> {
        this.authClient = await CustomAuthPublicClientApplication.create(customAuthConfig);
        return this.authClient;
      }
    
      getClient(): Promise<ICustomAuthPublicClientApplication> {
        return this.authClientPromise;
      }
    }
    

建立註冊元件

  1. 建立名為 /app/components 的目錄。

  2. 執行下列命令,使用 Angular CLI 為 components 資料夾內的註冊頁面產生新的元件:

    cd components
    ng generate component sign-up
    
  3. 開啟註冊/sign-up.component.ts檔案,然後將其內容取代為 sign-up.component 中的內容

  4. 開啟 註冊/sign-up.component.html 檔案,並在 html 檔案中新增程序代碼。

    • sign-up.component.ts檔案中的下列邏輯會決定用戶在啟動註冊程序之後需要執行哪些動作。 視結果而定,它會在 sign-up.component.html 中顯示密碼表單或驗證碼表單,讓使用者可以繼續註冊流程:

         const attributes: UserAccountAttributes = {
                     givenName: this.firstName,
                     surname: this.lastName,
                     jobTitle: this.jobTitle,
                     city: this.city,
                     country: this.country,
                 };
         const result = await client.signUp({
                     username: this.email,
                     attributes,
                 });
      
         if (result.isPasswordRequired()) {
             this.showPassword = true;
             this.showCode = false;
         } else if (result.isCodeRequired()) {
             this.showPassword = false;
             this.showCode = true;
         }
      

      SDK 的實例方法會 signUp() 啟動註冊流程。

    • 如果您希望使用者在註冊完成後立即啟動登入流程,請使用此代碼段:

      <div *ngIf="isSignedUp">
          <p>The user has been signed up, please click <a href="/sign-in">here</a> to sign in.</p>
      </div>
      
  5. 打開 src/app/app.component.scss 檔案,然後新增以下 的 styles 檔案。

註冊時請收集用戶名(別名)

你可以讓用戶除了電子郵件外,還能用用戶名(別名)註冊。 用戶名(別名)是另一種登入識別碼,例如客戶 ID、帳號或其他你選擇的數值。

註冊時,使用者名稱(電子郵件)始終是主要識別碼,使用者名稱(別名)不會取代它。 預設情況下,使用者名稱(別名)是可選的,但管理員可依需求設定。 你的應用程式一律會收集使用者名稱(電子郵件地址),並將別名連同電子郵件一起收集為屬性。 登入時,使用者可以使用使用者名稱(電子郵件)或使用者名稱(別名)登入。 欲了解使用者 名稱 屬性如何設定為可選或必需,請參閱 「設定使用者輸入類型與頁面佈局」。

註冊時要收集用戶名(別名):

  1. 請確保你的註冊使用者流程中啟用了使用者 名稱 內建屬性。 有關步驟,請參閱 登入識別碼政策中的啟用使用者名稱。

  2. 在註冊元件中加入 flatUsername 欄位,然後在你傳遞給 signUp() 的 UserAccountAttributes 中加入 flatusername 屬性:

    flatUsername = "";
    
    const attributes: UserAccountAttributes = {
        givenName: this.firstName,
         //...
        flatusername: this.flatUsername,
    };
    
  3. 在 sign-up.component.html 中,於現有欄位旁新增別名輸入欄位:

    <input type="text" [(ngModel)]="flatUsername" name="flatUsername" placeholder="Username (alias)" />
    
  4. 處理與使用者名稱(別名)相關的錯誤:

    • result.error?.isUserAlreadyExists() 涵蓋重複的電子郵件 或 重複的使用者名稱(別名)。 請相應地更新訊息,例如,已有 使用此電子郵件或使用者名稱的帳號存在。
    • 無效用戶名(別名)會透過 result.error?.isAttributesValidationFailed() 浮現,而非 result.error?.isInvalidUsername()。 使用這個方法進行分支處理,以顯示使用者名稱專屬的訊息。

註冊後自動登入 (選擇性)

您可以在成功註冊之後自動登入使用者,而不需啟動全新的登入流程。 若要這樣做,請使用下列代碼段。 請參閱 註冊/sign-up.component.ts的完整範例:

    if (this.signUpState instanceof SignUpCompletedState) {
        const result = await this.signUpState.signIn();
    
        if (result.isFailed()) {
            this.error = result.error?.errorData?.errorDescription || "An error occurred during auto sign-in";
        }
    
        if (result.isCompleted()) {
            this.userData = result.data;
            this.signUpState = result.state;
            this.isSignedUp = true;
            this.showCode = false;
            this.showPassword = false;
        }
    }

當您自動將使用者登入時,請在 sign-up/sign-up.component.html HTML 檔案中使用下列程式碼片段。

    <div *ngIf="userData && !isSignedIn">
        <p>Signed up complete, and signed in as {{ userData?.getAccount()?.username }}</p>
    </div>
    <div *ngIf="isSignedUp && !userData">
        <p>Sign up completed! Signing you in automatically...</p>
    </div>

更新應用程式路由

  1. 開啟 src/app/app.route.ts 檔案,然後新增註冊元件的路由:

    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { SignUpComponent } from './components/sign-up/sign-up.component';
    import { AuthService } from './services/auth.service';
    import { AppComponent } from './app.component';
    
    export const routes: Routes = [
        { path: 'sign-up', component: SignUpComponent },
    ];
    
    @NgModule({
        imports: [
            RouterModule.forRoot(routes),
            SignUpComponent,
        ],
        providers: [AuthService],
        bootstrap: [AppComponent]
    })
    export class AppRoutingModule { }
    

測試註冊流程

  1. 若要啟動 CORS Proxy 伺服器,請在終端機中執行下列命令:

    npm run cors
    
  2. 若要啟動您的應用程式,請在終端機中執行下列命令:

    npm start
    
  3. 開啟 web 瀏覽器並巡覽至 http://localhost:4200/sign-up。 註冊表單出現。

  4. 若要註冊帳戶,請輸入您的詳細數據,選取 [ 繼續 ] 按鈕,然後遵循提示。

後續步驟