Självstudie: Logga in användare och anropa Microsoft Graph API från ett Angular-ensidesprogram (SPA) med hjälp av autentiseringskodflöde
I den här självstudien skapar du ett Angular-ensidesprogram (SPA) som loggar in användare och anropar Microsoft Graph API med hjälp av auktoriseringskodflödet med PKCE. Det SPA som du skapar använder Microsoft Authentication Library (MSAL) för Angular v2.
I den här självstudien:
- Registrera programmet i administrationscentret för Microsoft Entra
- Skapa ett Angular-projekt med
npm
- Lägga till kod för att stödja användarinloggning och utloggning
- Lägga till kod för att anropa Microsoft Graph API
- Testa appen
MSAL Angular v2 förbättrar MSAL Angular v1 genom att stödja auktoriseringskodflödet i webbläsaren i stället för det implicita beviljandeflödet. MSAL Angular v2 stöder INTE det implicita flödet.
Förutsättningar
- Node.js för att köra en lokal webbserver.
- Visual Studio Code eller annan redigerare för att ändra projektfiler.
Så här fungerar exempelappen
Exempelprogrammet som skapades i den här självstudien gör att ett Angular SPA kan köra frågor mot Microsoft Graph API eller ett webb-API som accepterar token som utfärdats av Microsofts identitetsplattform. Den använder Microsoft Authentication Library (MSAL) för Angular v2, en omslutning av MSAL.js v2-biblioteket. MSAL Angular gör det möjligt för Angular 9+-program att autentisera företagsanvändare med hjälp av Microsoft Entra-ID, och även användare med Microsoft-konton och sociala identiteter som Facebook, Google och LinkedIn. Biblioteket gör det också möjligt för program att få åtkomst till Microsofts molntjänster och Microsoft Graph.
I det här scenariot, efter att en användare har loggat in, begärs en åtkomsttoken och läggs till i HTTP-begäranden via auktoriseringshuvudet. Anskaffning och förnyelse av token hanteras av MSAL.
Bibliotek
I den här självstudien används följande bibliotek:
Bibliotek | beskrivning |
---|---|
MSAL Angular | Microsoft Authentication Library for JavaScript Angular Wrapper |
MSAL-webbläsare | Microsoft Authentication Library for JavaScript v2-webbläsarpaket |
Du hittar källkoden för alla MSAL.js bibliotek på microsoft-authentication-library-for-js
lagringsplatsen på GitHub.
Hämta det färdiga kodexemplet
Föredrar du att ladda ned det slutförda exempelprojektet för den här självstudien i stället? Klona ms-identity-javascript-angular-spa
git clone https://github.com/Azure-Samples/ms-identity-javascript-angular-spa.git
Om du vill fortsätta med självstudien och skapa programmet själv går du vidare till nästa avsnitt, Registrerar programmet och registrerar identifierare.
Registrera program- och postidentifierare
Dricks
Stegen i den här artikeln kan variera något beroende på vilken portal du börjar från.
För att slutföra registreringen anger du ett namn för programmet, anger vilka kontotyper som stöds och lägger till en omdirigerings-URI. När programmets översiktsfönster har registrerats visas de identifierare som behövs i programmets källkod.
- Logga in på administrationscentret för Microsoft Entra som minst programutvecklare.
- Om du har åtkomst till flera klienter använder du ikonen Inställningar på den översta menyn för att växla till den klientorganisation där du vill registrera programmet från menyn Kataloger + prenumerationer.
- Bläddra till Identitetsprogram>> Appregistreringar.
- Välj Ny registrering.
- Ange ett namn för programmet, till exempel Angular-SPA-auth-code.
- För Kontotyper som stöds väljer du Endast konton i den här organisationskatalogen. Om du vill ha information om olika kontotyper väljer du alternativet Hjälp mig .
- Under Omdirigerings-URI (valfritt) använder du den nedrullningsbara menyn för att välja Enkelsidigt program (SPA) och ange
http://localhost:4200
i textrutan. - Välj Registrera.
- Programmets översiktsfönster visas när registreringen är klar. Registrera katalog-ID:t (klient)-ID:t och program-ID:t (klient) som ska användas i programmets källkod.
Skapa projektet
Öppna Visual Studio Code, välj Arkiv>Öppna mapp.... Navigera till och välj den plats där projektet ska skapas.
Öppna en ny terminal genom att välja Terminal>Ny terminal.
- Du kan behöva byta terminaltyper. Välj nedåtpilen + bredvid ikonen i terminalen och välj Kommandotolken.
Kör följande kommandon för att skapa ett nytt Angular-projekt med namnet
msal-angular-tutorial
, installera Komponentbibliotek för Angular Material, MSAL Browser, MSAL Angular och generera hem- och profilkomponenter.npm install -g @angular/cli ng new msal-angular-tutorial --routing=true --style=css --strict=false cd msal-angular-tutorial npm install @angular/material @angular/cdk npm install @azure/msal-browser @azure/msal-angular ng generate component home ng generate component profile
Konfigurera programmet och redigera basgränssnittet
Öppna src/app/app.module.ts. Och
MsalModule
MsalInterceptor
måste läggas tillimports
tillsammans med konstantenisIE
. Du kommer också att lägga till materialmodulerna. Ersätt hela innehållet i filen med följande kodfragment:import { BrowserModule } from "@angular/platform-browser"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { NgModule } from "@angular/core"; import { MatButtonModule } from "@angular/material/button"; import { MatToolbarModule } from "@angular/material/toolbar"; import { MatListModule } from "@angular/material/list"; import { AppRoutingModule } from "./app-routing.module"; import { AppComponent } from "./app.component"; import { HomeComponent } from "./home/home.component"; import { ProfileComponent } from "./profile/profile.component"; import { MsalModule, MsalRedirectComponent } from "@azure/msal-angular"; import { PublicClientApplication } from "@azure/msal-browser"; const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1; @NgModule({ declarations: [AppComponent, HomeComponent, ProfileComponent], imports: [ BrowserModule, BrowserAnimationsModule, AppRoutingModule, MatButtonModule, MatToolbarModule, MatListModule, MsalModule.forRoot( new PublicClientApplication({ auth: { clientId: "Enter_the_Application_Id_here", // Application (client) ID from the app registration authority: "Enter_the_Cloud_Instance_Id_Here/Enter_the_Tenant_Info_Here", // The Azure cloud instance and the app's sign-in audience (tenant ID, common, organizations, or consumers) redirectUri: "Enter_the_Redirect_Uri_Here", // This is your redirect URI }, cache: { cacheLocation: "localStorage", storeAuthStateInCookie: isIE, // Set to true for Internet Explorer 11 }, }), null, null ), ], providers: [], bootstrap: [AppComponent, MsalRedirectComponent], }) export class AppModule {}
Ersätt följande värden med de värden som hämtas från administrationscentret för Microsoft Entra. Mer information om tillgängliga konfigurerbara alternativ finns i Initiera klientprogram.
clientId
- Identifieraren för programmet, även kallad klienten. ErsättEnter_the_Application_Id_Here
med det program-ID-värde (klient) som registrerades tidigare från översiktssidan för det registrerade programmet.authority
- Detta består av två delar:- Instansen är slutpunkten för molnleverantören. För huvudmolnet eller det globala Azure-molnet anger du
https://login.microsoftonline.com
. Kontrollera med de olika tillgängliga slutpunkterna i nationella moln. - Klientorganisations-ID:t är identifieraren för den klientorganisation där programmet är registrerat.
_Enter_the_Tenant_Info_Here
Ersätt med det katalog-ID-värde (klientorganisation) som registrerades tidigare från översiktssidan för det registrerade programmet.
- Instansen är slutpunkten för molnleverantören. För huvudmolnet eller det globala Azure-molnet anger du
redirectUri
– den plats där auktoriseringsservern skickar användaren när appen har godkänts och beviljats en auktoriseringskod eller åtkomsttoken. ErsättEnter_the_Redirect_Uri_Here
medhttp://localhost:4200
Öppna src/app/app-routing.module.ts och lägg till vägar till hem - och profilkomponenterna . Ersätt hela innehållet i filen med följande kodfragment:
import { NgModule } from "@angular/core"; import { Routes, RouterModule } from "@angular/router"; import { BrowserUtils } from "@azure/msal-browser"; import { HomeComponent } from "./home/home.component"; import { ProfileComponent } from "./profile/profile.component"; const routes: Routes = [ { path: "profile", component: ProfileComponent, }, { path: "", component: HomeComponent, }, ]; const isIframe = window !== window.parent && !window.opener; @NgModule({ imports: [ RouterModule.forRoot(routes, { // Don't perform initial navigation in iframes or popups initialNavigation: !BrowserUtils.isInIframe() && !BrowserUtils.isInPopup() ? "enabledNonBlocking" : "disabled", // Set to enabledBlocking to use Angular Universal }), ], exports: [RouterModule], }) export class AppRoutingModule {}
Öppna src/app/app.component.html och ersätt den befintliga koden med följande:
<mat-toolbar color="primary"> <a class="title" href="/">{{ title }}</a> <div class="toolbar-spacer"></div> <a mat-button [routerLink]="['profile']">Profile</a> <button mat-raised-button *ngIf="!loginDisplay" (click)="login()">Login</button> </mat-toolbar> <div class="container"> <!--This is to avoid reload during acquireTokenSilent() because of hidden iframe --> <router-outlet *ngIf="!isIframe"></router-outlet> </div>
Öppna src/style.css för att definiera CSS:
@import "~@angular/material/prebuilt-themes/deeppurple-amber.css"; html, body { height: 100%; } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } .container { margin: 1%; }
Öppna src/app/app.component.css för att lägga till CSS-formatering i programmet:
.toolbar-spacer { flex: 1 1 auto; } a.title { color: white; }
Logga in med popup-fönster
Öppna src/app/app.component.ts och ersätt innehållet i filen med följande för att logga in en användare med ett popup-fönster:
import { MsalService } from '@azure/msal-angular'; import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'msal-angular-tutorial'; isIframe = false; loginDisplay = false; constructor(private authService: MsalService) { } ngOnInit() { this.isIframe = window !== window.parent && !window.opener; } login() { this.authService.loginPopup() .subscribe({ next: (result) => { console.log(result); this.setLoginDisplay(); }, error: (error) => console.log(error) }); } setLoginDisplay() { this.loginDisplay = this.authService.instance.getAllAccounts().length > 0; } }
Logga in med omdirigeringar
Uppdatera src/app/app.module.ts för att starta
MsalRedirectComponent
. Det här är en dedikerad omdirigeringskomponent som hanterar omdirigeringar. Ändra import ochMsalModule
AppComponent
bootstrap så att de ser ut ungefär så här:... import { MsalModule, MsalRedirectComponent } from '@azure/msal-angular'; // Updated import ... bootstrap: [AppComponent, MsalRedirectComponent] // MsalRedirectComponent bootstrapped here ...
Öppna src/index.html och ersätt hela innehållet i filen med följande kodfragment, som lägger till väljaren
<app-redirect>
:<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>msal-angular-tutorial</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <body> <app-root></app-root> <app-redirect></app-redirect> </body> </html>
Öppna src/app/app.component.ts och ersätt koden med följande för att logga in en användare med en fullständig omdirigering:
import { MsalService } from '@azure/msal-angular'; import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'msal-angular-tutorial'; isIframe = false; loginDisplay = false; constructor(private authService: MsalService) { } ngOnInit() { this.isIframe = window !== window.parent && !window.opener; } login() { this.authService.loginRedirect(); } setLoginDisplay() { this.loginDisplay = this.authService.instance.getAllAccounts().length > 0; } }
Gå till src/app/home/home.component.ts och ersätt hela innehållet i filen med följande kodfragment för att
LOGIN_SUCCESS
prenumerera på händelsen:import { Component, OnInit } from '@angular/core'; import { MsalBroadcastService, MsalService } from '@azure/msal-angular'; import { EventMessage, EventType, InteractionStatus } from '@azure/msal-browser'; import { filter } from 'rxjs/operators'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] }) export class HomeComponent implements OnInit { constructor(private authService: MsalService, private msalBroadcastService: MsalBroadcastService) { } ngOnInit(): void { this.msalBroadcastService.msalSubject$ .pipe( filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS), ) .subscribe((result: EventMessage) => { console.log(result); }); } }
Villkorsstyrd återgivning
För att endast kunna återge vissa användargränssnitt (användargränssnitt) för autentiserade MsalBroadcastService
användare måste komponenterna prenumerera på för att se om användarna har loggats in och interaktionen har slutförts.
MsalBroadcastService
Lägg till i src/app/app.component.ts och prenumerera på det observerbara för att kontrollera om interaktioneninProgress$
är klar och ett konto loggas in innan användargränssnittet återges. Koden bör nu se ut så här:import { Component, OnInit, OnDestroy } from '@angular/core'; import { MsalService, MsalBroadcastService } from '@azure/msal-angular'; import { InteractionStatus } from '@azure/msal-browser'; import { Subject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { title = 'msal-angular-tutorial'; isIframe = false; loginDisplay = false; private readonly _destroying$ = new Subject<void>(); constructor(private broadcastService: MsalBroadcastService, private authService: MsalService) { } ngOnInit() { this.isIframe = window !== window.parent && !window.opener; this.broadcastService.inProgress$ .pipe( filter((status: InteractionStatus) => status === InteractionStatus.None), takeUntil(this._destroying$) ) .subscribe(() => { this.setLoginDisplay(); }) } login() { this.authService.loginRedirect(); } setLoginDisplay() { this.loginDisplay = this.authService.instance.getAllAccounts().length > 0; } ngOnDestroy(): void { this._destroying$.next(undefined); this._destroying$.complete(); } }
Uppdatera koden i src/app/home/home.component.ts för att även kontrollera om interaktionen ska slutföras innan användargränssnittet uppdateras. Koden bör nu se ut så här:
import { Component, OnInit } from '@angular/core'; import { MsalBroadcastService, MsalService } from '@azure/msal-angular'; import { EventMessage, EventType, InteractionStatus } from '@azure/msal-browser'; import { filter } from 'rxjs/operators'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] }) export class HomeComponent implements OnInit { loginDisplay = false; constructor(private authService: MsalService, private msalBroadcastService: MsalBroadcastService) { } ngOnInit(): void { this.msalBroadcastService.msalSubject$ .pipe( filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS), ) .subscribe((result: EventMessage) => { console.log(result); }); this.msalBroadcastService.inProgress$ .pipe( filter((status: InteractionStatus) => status === InteractionStatus.None) ) .subscribe(() => { this.setLoginDisplay(); }) } setLoginDisplay() { this.loginDisplay = this.authService.instance.getAllAccounts().length > 0; } }
Ersätt koden i src/app/home/home.component.html med följande villkorsstyrda skärmar:
<div *ngIf="!loginDisplay"> <p>Please sign-in to see your profile information.</p> </div> <div *ngIf="loginDisplay"> <p>Login successful!</p> <p>Request your profile information by clicking Profile above.</p> </div>
Implementera Angular Guard
Klassen MsalGuard
är en som du kan använda för att skydda vägar och kräva autentisering innan du kommer åt den skyddade vägen. Följande steg lägger till i MsalGuard
Profile
vägen. Profile
Att skydda vägen innebär att även om en användare inte loggar in med Login
knappen uppmanas användaren att autentisera MsalGuard
via popup-fönster eller omdirigering innan sidan Profile
visas om de försöker komma åt Profile
vägen eller välja Profile
knappen.
MsalGuard
är en bekvämlighetsklass som du kan använda för att förbättra användarupplevelsen, men den bör inte användas för säkerhet. Angripare kan potentiellt komma runt skydd på klientsidan och du bör se till att servern inte returnerar några data som användaren inte ska komma åt.
MsalGuard
Lägg till klassen som leverantör i ditt program i src/app/app.module.ts och lägg till konfigurationerna förMsalGuard
. Omfång som behövs för att hämta token senare kan anges iauthRequest
, och typen av interaktion för Guard kan anges tillRedirect
ellerPopup
. Koden bör se ut så här:import { BrowserModule } from "@angular/platform-browser"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { NgModule } from "@angular/core"; import { MatButtonModule } from "@angular/material/button"; import { MatToolbarModule } from "@angular/material/toolbar"; import { MatListModule } from "@angular/material/list"; import { AppRoutingModule } from "./app-routing.module"; import { AppComponent } from "./app.component"; import { HomeComponent } from "./home/home.component"; import { ProfileComponent } from "./profile/profile.component"; import { MsalModule, MsalRedirectComponent, MsalGuard, } from "@azure/msal-angular"; // MsalGuard added to imports import { PublicClientApplication, InteractionType, } from "@azure/msal-browser"; // InteractionType added to imports const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1; @NgModule({ declarations: [AppComponent, HomeComponent, ProfileComponent], imports: [ BrowserModule, BrowserAnimationsModule, AppRoutingModule, MatButtonModule, MatToolbarModule, MatListModule, MsalModule.forRoot( new PublicClientApplication({ auth: { clientId: "Enter_the_Application_Id_here", authority: "Enter_the_Cloud_Instance_Id_Here/Enter_the_Tenant_Info_Here", redirectUri: "Enter_the_Redirect_Uri_Here", }, cache: { cacheLocation: "localStorage", storeAuthStateInCookie: isIE, }, }), { interactionType: InteractionType.Redirect, // MSAL Guard Configuration authRequest: { scopes: ["user.read"], }, }, null ), ], providers: [ MsalGuard, // MsalGuard added as provider here ], bootstrap: [AppComponent, MsalRedirectComponent], }) export class AppModule {}
MsalGuard
Ange på de vägar som du vill skydda i src/app/app-routing.module.ts:import { NgModule } from "@angular/core"; import { Routes, RouterModule } from "@angular/router"; import { BrowserUtils } from "@azure/msal-browser"; import { HomeComponent } from "./home/home.component"; import { ProfileComponent } from "./profile/profile.component"; import { MsalGuard } from "@azure/msal-angular"; const routes: Routes = [ { path: "profile", component: ProfileComponent, canActivate: [MsalGuard], }, { path: "", component: HomeComponent, }, ]; const isIframe = window !== window.parent && !window.opener; @NgModule({ imports: [ RouterModule.forRoot(routes, { // Don't perform initial navigation in iframes or popups initialNavigation: !BrowserUtils.isInIframe() && !BrowserUtils.isInPopup() ? "enabledNonBlocking" : "disabled", // Set to enabledBlocking to use Angular Universal }), ], exports: [RouterModule], }) export class AppRoutingModule {}
Justera inloggningsanropen i src/app/app.component.ts för att ta
authRequest
hänsyn till uppsättningen i skyddskonfigurationerna. Koden bör nu se ut så här:import { Component, OnInit, OnDestroy, Inject } from '@angular/core'; import { MsalService, MsalBroadcastService, MSAL_GUARD_CONFIG, MsalGuardConfiguration } from '@azure/msal-angular'; import { InteractionStatus, RedirectRequest } from '@azure/msal-browser'; import { Subject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { title = 'msal-angular-tutorial'; isIframe = false; loginDisplay = false; private readonly _destroying$ = new Subject<void>(); constructor(@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration, private broadcastService: MsalBroadcastService, private authService: MsalService) { } ngOnInit() { this.isIframe = window !== window.parent && !window.opener; this.broadcastService.inProgress$ .pipe( filter((status: InteractionStatus) => status === InteractionStatus.None), takeUntil(this._destroying$) ) .subscribe(() => { this.setLoginDisplay(); }) } login() { if (this.msalGuardConfig.authRequest){ this.authService.loginRedirect({...this.msalGuardConfig.authRequest} as RedirectRequest); } else { this.authService.loginRedirect(); } } setLoginDisplay() { this.loginDisplay = this.authService.instance.getAllAccounts().length > 0; } ngOnDestroy(): void { this._destroying$.next(undefined); this._destroying$.complete(); } }
Hämta en token
Angular Interceptor
MSAL Angular tillhandahåller en Interceptor
klass som automatiskt hämtar token för utgående begäranden som använder Angular-klienten http
till kända skyddade resurser.
Interceptor
Lägg till klassen som leverantör i ditt program i src/app/app.module.ts med dess konfigurationer. Koden bör nu se ut så här:import { BrowserModule } from "@angular/platform-browser"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { NgModule } from "@angular/core"; import { HTTP_INTERCEPTORS, HttpClientModule } from "@angular/common/http"; // Import import { MatButtonModule } from "@angular/material/button"; import { MatToolbarModule } from "@angular/material/toolbar"; import { MatListModule } from "@angular/material/list"; import { AppRoutingModule } from "./app-routing.module"; import { AppComponent } from "./app.component"; import { HomeComponent } from "./home/home.component"; import { ProfileComponent } from "./profile/profile.component"; import { MsalModule, MsalRedirectComponent, MsalGuard, MsalInterceptor, } from "@azure/msal-angular"; // Import MsalInterceptor import { InteractionType, PublicClientApplication, } from "@azure/msal-browser"; const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1; @NgModule({ declarations: [AppComponent, HomeComponent, ProfileComponent], imports: [ BrowserModule, BrowserAnimationsModule, AppRoutingModule, MatButtonModule, MatToolbarModule, MatListModule, HttpClientModule, MsalModule.forRoot( new PublicClientApplication({ auth: { clientId: "Enter_the_Application_Id_Here", authority: "Enter_the_Cloud_Instance_Id_Here/Enter_the_Tenant_Info_Here", redirectUri: "Enter_the_Redirect_Uri_Here", }, cache: { cacheLocation: "localStorage", storeAuthStateInCookie: isIE, }, }), { interactionType: InteractionType.Redirect, authRequest: { scopes: ["user.read"], }, }, { interactionType: InteractionType.Redirect, // MSAL Interceptor Configuration protectedResourceMap: new Map([ ["Enter_the_Graph_Endpoint_Here/v1.0/me", ["user.read"]], ]), } ), ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true, }, MsalGuard, ], bootstrap: [AppComponent, MsalRedirectComponent], }) export class AppModule {}
De skyddade resurserna tillhandahålls som en
protectedResourceMap
. Url:erna som du anger iprotectedResourceMap
samlingen är skiftlägeskänsliga. För varje resurs lägger du till omfång som begärs att returneras i åtkomsttoken.Till exempel:
["user.read"]
för Microsoft Graph["<Application ID URL>/scope"]
för anpassade webb-API:er (det vill:api://<Application ID>/access_as_user
)
Ändra värdena i enligt beskrivningen
protectedResourceMap
här:Enter_the_Graph_Endpoint_Here
är instansen av Microsoft Graph API som programmet ska kommunicera med. För den globala Microsoft Graph API-slutpunkten ersätter du den här strängen medhttps://graph.microsoft.com
. Slutpunkter i nationella molndistributioner finns i Nationella molndistributioner i Microsoft Graph-dokumentationen.
Ersätt koden i src/app/profile/profile.component.ts för att hämta en användares profil med en HTTP-begäran och ersätt
GRAPH_ENDPOINT
med Microsoft Graph-slutpunkten:import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; const GRAPH_ENDPOINT = 'Enter_the_Graph_Endpoint_Here/v1.0/me'; type ProfileType = { givenName?: string, surname?: string, userPrincipalName?: string, id?: string }; @Component({ selector: 'app-profile', templateUrl: './profile.component.html', styleUrls: ['./profile.component.css'] }) export class ProfileComponent implements OnInit { profile!: ProfileType; constructor( private http: HttpClient ) { } ngOnInit() { this.getProfile(); } getProfile() { this.http.get(GRAPH_ENDPOINT) .subscribe(profile => { this.profile = profile; }); } }
Ersätt användargränssnittet i src/app/profile/profile.component.html för att visa profilinformation:
<div> <p><strong>First Name: </strong> {{profile?.givenName}}</p> <p><strong>Last Name: </strong> {{profile?.surname}}</p> <p><strong>Email: </strong> {{profile?.userPrincipalName}}</p> <p><strong>Id: </strong> {{profile?.id}}</p> </div>
Logga ut
Uppdatera koden i src/app/app.component.html för att villkorligt visa en
Logout
knapp:<mat-toolbar color="primary"> <a class="title" href="/">{{ title }}</a> <div class="toolbar-spacer"></div> <a mat-button [routerLink]="['profile']">Profile</a> <button mat-raised-button *ngIf="!loginDisplay" (click)="login()">Login</button> <button mat-raised-button *ngIf="loginDisplay" (click)="logout()">Logout</button> </mat-toolbar> <div class="container"> <!--This is to avoid reload during acquireTokenSilent() because of hidden iframe --> <router-outlet *ngIf="!isIframe"></router-outlet> </div>
Logga ut med omdirigeringar
Uppdatera koden i src/app/app.component.ts för att logga ut en användare med omdirigeringar:
import { Component, OnInit, OnDestroy, Inject } from '@angular/core'; import { MsalService, MsalBroadcastService, MSAL_GUARD_CONFIG, MsalGuardConfiguration } from '@azure/msal-angular'; import { InteractionStatus, RedirectRequest } from '@azure/msal-browser'; import { Subject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { title = 'msal-angular-tutorial'; isIframe = false; loginDisplay = false; private readonly _destroying$ = new Subject<void>(); constructor(@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration, private broadcastService: MsalBroadcastService, private authService: MsalService) { } ngOnInit() { this.isIframe = window !== window.parent && !window.opener; this.broadcastService.inProgress$ .pipe( filter((status: InteractionStatus) => status === InteractionStatus.None), takeUntil(this._destroying$) ) .subscribe(() => { this.setLoginDisplay(); }) } login() { if (this.msalGuardConfig.authRequest){ this.authService.loginRedirect({...this.msalGuardConfig.authRequest} as RedirectRequest); } else { this.authService.loginRedirect(); } } logout() { // Add log out function here this.authService.logoutRedirect({ postLogoutRedirectUri: 'http://localhost:4200' }); } setLoginDisplay() { this.loginDisplay = this.authService.instance.getAllAccounts().length > 0; } ngOnDestroy(): void { this._destroying$.next(undefined); this._destroying$.complete(); } }
Logga ut med popup-fönster
Uppdatera koden i src/app/app.component.ts för att logga ut en användare med popup-fönster:
import { Component, OnInit, OnDestroy, Inject } from '@angular/core'; import { MsalService, MsalBroadcastService, MSAL_GUARD_CONFIG, MsalGuardConfiguration } from '@azure/msal-angular'; import { InteractionStatus, PopupRequest } from '@azure/msal-browser'; import { Subject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit, OnDestroy { title = 'msal-angular-tutorial'; isIframe = false; loginDisplay = false; private readonly _destroying$ = new Subject<void>(); constructor(@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration, private broadcastService: MsalBroadcastService, private authService: MsalService) { } ngOnInit() { this.isIframe = window !== window.parent && !window.opener; this.broadcastService.inProgress$ .pipe( filter((status: InteractionStatus) => status === InteractionStatus.None), takeUntil(this._destroying$) ) .subscribe(() => { this.setLoginDisplay(); }) } login() { if (this.msalGuardConfig.authRequest){ this.authService.loginPopup({...this.msalGuardConfig.authRequest} as PopupRequest) .subscribe({ next: (result) => { console.log(result); this.setLoginDisplay(); }, error: (error) => console.log(error) }); } else { this.authService.loginPopup() .subscribe({ next: (result) => { console.log(result); this.setLoginDisplay(); }, error: (error) => console.log(error) }); } } logout() { // Add log out function here this.authService.logoutPopup({ mainWindowRedirectUri: "/" }); } setLoginDisplay() { this.loginDisplay = this.authService.instance.getAllAccounts().length > 0; } ngOnDestroy(): void { this._destroying$.next(undefined); this._destroying$.complete(); } }
Testa koden
Starta webbservern för att lyssna på porten genom att köra följande kommandon i en kommandotolk från programmappen:
npm install npm start
I webbläsaren anger du
http://localhost:4200
, och du bör se en sida som ser ut så här.Välj Acceptera för att bevilja appen behörighet till din profil. Detta sker första gången du börjar logga in.
Efter medgivande visar webbprogrammet en lyckad inloggningssida om du godkänner de begärda behörigheterna.
Välj Profil för att visa användarprofilinformationen som returneras i svaret från anropet till Microsoft Graph-API:et:
Lägga till omfång och delegerade behörigheter
Microsoft Graph-API:et kräver user.Read-omfånget för att läsa en användares profil. User.Read-omfånget läggs automatiskt till i varje appregistrering. Andra API:er för Microsoft Graph och anpassade API:er för serverdelsservern kan kräva andra omfång. Till exempel kräver Microsoft Graph API-omfånget Mail.Read för att kunna visa användarens e-post.
När du lägger till omfång kan användarna uppmanas att ge extra medgivande för de tillagda omfången.
Kommentar
Användaren kan uppmanas att ange ytterligare medgivanden när du ökar antalet omfång.
Hjälp och support
Om du behöver hjälp, vill rapportera ett problem eller vill lära dig mer om dina supportalternativ kan du läsa Hjälp och support för utvecklare.
Nästa steg
- Läs mer genom att skapa ett React-program med en sida (SPA) som loggar in användare i följande självstudieserie i flera delar.