Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Applies to:
External tenants (learn more)
In this tutorial, you learn how to build an Angular single-page app that signs up users by using native authentication's JavaScript SDK.
In this tutorial, you:
- Create an Angular Next.js project.
- Add MSAL JS SDK to it.
- Add UI components of the app.
- Setup the project to sign up users.
Prerequisites
- Complete the steps in Quickstart: Sign in users in an Angular single-page app by using native authentication JavaScript SDK. This quickstart shows you run a sample Angular code sample.
- Complete the steps in Set up CORS proxy server to manage CORS headers for native authentication.
- Visual Studio Code or another code editor.
- Node.js.
- Angular CLI.
Create a React project and install dependencies
In a location of choice in your computer, run the following commands to create a new Angular project with the name reactspa, navigate into the project folder, then install packages:
ng new angularspa
cd angularspa
After you successfully run the commands, you should have an app with the following structure:
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
Add JavaScript SDK to your project
To use the native authentication JavaScript SDK in your app, use your terminal to install it by using the following command:
npm intall @azure/msal-browser
The native authentication capabilities are part of the azure-msal-browser library. To use native authentication features, you import from @azure/msal-browser/custom-auth. For example:
import CustomAuthPublicClientApplication from "@azure/msal-browser/custom-auth";
Add client configuration
In this section, you define a configuration for native authentication public client application to enable it to interact with the interface of the SDK. To do so,
Create a file called src/app/config/auth-config.ts, then add the following code:
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; } }, }, }, };In the code, find the placeholder:
Enter_the_Application_Id_Herethen replace it with the Application (client) ID of the app you registered earlier.Enter_the_Tenant_Subdomain_Herethen replace it with the tenant subdomain in your Microsoft Entra admin center. For example, if your tenant primary domain iscontoso.onmicrosoft.com, usecontoso. If you don't have your tenant name, learn how to read your tenant details.
Create a file called src/app/services/auth.service.ts, then add the following code:
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; } }
Create a sign-up component
Create a directory called /app/components.
Use Angular CLI to generate a new component for the sign-up page inside the components folder by running the following command:
cd components ng generate component sign-upOpen sign-up/sign-up.component.ts file, then replace its contents with the contents in sign-up.component
Open sign-up/sign-up.component.html file and add the code in html file.
The following logic in the sign-up.component.ts file determines what the user needs to do next after starting the sign-up process. Depending on the result, it shows either the password form or the verification code form in sign-up.component.html so the user can continue with the sign-up flow:
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; }The SDK's instance method,
signUp()starts the sign-up flow.If you want the user to start sign-in flow immediately after sign-up is completed, use this snippet:
<div *ngIf="isSignedUp"> <p>The user has been signed up, please click <a href="/sign-in">here</a> to sign in.</p> </div>
Open the sign-up/sign-up.component.scss file, then add the following styles file.
Automatically sign-in after sign-up (optional)
You can automatically sign in your users after a successful sign-up without starting a fresh sign-in flow. To do so, use the following code snippet. See a complete example at sign-up/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;
}
}
When you autosign in a user, use the following snippet in your sign-up/sign-up.component.html html file.
<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>
Update app routing
Open the src/app/app.route.ts file, then add the route for the sign-up component:
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 { }
Test the sign-up flow
To start the CORS proxy server, run the following command in your terminal:
npm run corsTo start your application, run the following command in your terminal:
npm startOpen a web browser and navigate to
http://localhost:4200/sign-up. A sign-up form appears.To sign up for an account, input your details, select the Continue button, then follow the prompts.