Öğretici: Kimlik doğrulama kod akışını kullanarak kullanıcıları oturum açma ve Angular tek sayfalı uygulamadan (SPA) Microsoft Graph API'sini çağırma
Bu öğreticide, kullanıcılarda oturum açıp PKCE ile yetkilendirme kodu akışını kullanarak Microsoft Graph API'sini çağıran bir Angular tek sayfalı uygulama (SPA) oluşturacaksınız. Oluşturduğunuz SPA, Angular v2 için Microsoft Kimlik Doğrulama Kitaplığı'nı (MSAL) kullanır.
Bu öğreticide:
- Uygulamayı Microsoft Entra yönetim merkezine kaydetme
- ile Angular projesi oluşturma
npm
- Kullanıcı oturum açma ve oturum kapatmayı desteklemek için kod ekleme
- Microsoft Graph API'sini çağırmak için kod ekleme
- Uygulamayı test etme
MSAL Angular v2, kimlik doğrulama kodu akışını örtük verme akışı yerine tarayıcıda PKCE ile destekleyerek MSAL Angular v1'de geliştirir. Tek sayfalı uygulamalar (SPA' lar) için PKCE ile yetkilendirme kodu akışını kullanmanızı öneririz çünkü örtük akıştan daha güvenlidir. MSAL Angular v2 örtük akışı DESTEKLEMEZ .
Önkoşullar
- Yerel bir web sunucusu çalıştırmak için Node.js.
- Proje dosyalarını değiştirmek için Visual Studio Code veya başka bir düzenleyici.
Örnek uygulama nasıl çalışır?
Bu öğreticide oluşturulan örnek uygulama, Angular SPA'nın Microsoft Graph API'sini veya Microsoft kimlik platformu tarafından verilen belirteçleri kabul eden bir web API'sini sorgulamasını sağlar. MSAL.js v2 kitaplığının sarmalayıcısı olan Angular v2 için Microsoft Kimlik Doğrulama Kitaplığı'nı (MSAL) kullanır. MSAL Angular, Angular 9+ uygulamalarının Microsoft Entra ID kullanarak kurumsal kullanıcıların ve ayrıca Microsoft hesapları ve Facebook, Google ve LinkedIn gibi sosyal kimliklere sahip kullanıcıların kimliğini doğrulamasını sağlar. Kitaplık ayrıca uygulamaların Microsoft bulut hizmetlerine ve Microsoft Graph'a erişmesini sağlar.
Bu senaryoda, bir kullanıcı oturum açtığında, yetkilendirme üst bilgisi aracılığıyla bir erişim belirteci istenir ve HTTP isteklerine eklenir. Belirteç alma ve yenileme MSAL tarafından işlenir.
Kitaplıklar
Bu öğreticide aşağıdaki kitaplıklar kullanılır:
Kitaplık | Açıklama |
---|---|
MSAL Angular | JavaScript Angular Sarmalayıcısı için Microsoft Kimlik Doğrulama Kitaplığı |
MSAL Tarayıcısı | JavaScript v2 tarayıcı paketi için Microsoft Kimlik Doğrulama Kitaplığı |
Tüm MSAL.js kitaplıklarının kaynak kodunu GitHub'daki depoda microsoft-authentication-library-for-js
bulabilirsiniz.
Tamamlanmış kod örneğini alma
Bunun yerine bu öğretici için tamamlanmış örnek projeyi indirmeyi tercih ediyor musunuz? ms-identity-javascript-angular-spa'yı kopyalama
git clone https://github.com/Azure-Samples/ms-identity-javascript-angular-spa.git
Öğreticiye devam etmek ve uygulamayı kendiniz oluşturmak için, uygulamayı kaydetme ve kayıt tanımlayıcıları başlıklı sonraki bölüme geçin.
Uygulama ve kayıt tanımlayıcılarını kaydetme
İpucu
Bu makaledeki adımlar, başladığınız portala göre biraz değişiklik gösterebilir.
Kaydı tamamlamak için uygulamaya bir ad verin, desteklenen hesap türlerini belirtin ve yeniden yönlendirme URI'sini ekleyin. Kaydedildikten sonra, uygulamaya Genel Bakış bölmesinde uygulama kaynak kodunda gereken tanımlayıcılar görüntülenir.
- Microsoft Entra yönetim merkezinde en azından Uygulama Geliştiricisi olarak oturum açın.
- Birden çok kiracıya erişiminiz varsa, dizinler + abonelikler menüsünden uygulamayı kaydetmek istediğiniz kiracıya geçmek için üst menüdeki Ayarlar simgesini kullanın.
- Kimlik>Uygulamaları'na> göz atın Uygulama kayıtları.
- Yeni kayıt öğesini seçin.
- Uygulama için Angular-SPA-auth-code gibi bir Ad girin.
- Desteklenen hesap türleri için Yalnızca bu kuruluş dizinindeki Hesaplar'ı seçin. Farklı hesap türleri hakkında bilgi için Bana yardım et seçeneğini belirleyin.
- Yeniden Yönlendirme URI'sinin (isteğe bağlı) altında, açılan menüyü kullanarak Tek sayfalı uygulama (SPA) öğesini seçin ve metin kutusuna girin
http://localhost:4200
. - Kaydet'i seçin.
- Kayıt tamamlandığında uygulamanın Genel Bakış bölmesi görüntülenir. Uygulama kaynak kodunuzda kullanılacak Dizin (kiracı) kimliğini ve Uygulama (istemci) kimliğini kaydedin.
Projenizi oluşturun
Visual Studio Code'ı açın, Dosya>Klasör Aç... öğesini seçin. Adresine gidin ve projenizin oluşturulacağı konumu seçin.
Terminal>Yeni Terminal'i seçerek yeni bir terminal açın.
- Terminal türlerini değiştirmeniz gerekebilir. Terminaldeki simgenin + yanındaki aşağı oku ve ardından Komut İstemi'ni seçin.
adlı
msal-angular-tutorial
yeni bir Angular projesi oluşturmak için aşağıdaki komutları çalıştırın, Angular Malzeme bileşen kitaplıklarını, MSAL Browser'ı, MSAL Angular'ı yükleyin ve ev ve profil bileşenleri oluşturun.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
Uygulamayı yapılandırma ve temel kullanıcı arabirimini düzenleme
src/app/app.module.ts açın. ve öğesinin
MsalModule
sabitleisIE
birlikte eklenmesiimports
MsalInterceptor
gerekir. Ayrıca malzeme modüllerini de ekleyeceksiniz. Dosyanın tüm içeriğini aşağıdaki kod parçacığıyla değiştirin: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 {}
Aşağıdaki değerleri Microsoft Entra yönetim merkezinden alınan değerlerle değiştirin. Kullanılabilir yapılandırılabilir seçenekler hakkında daha fazla bilgi için bkz . İstemci uygulamalarını başlatma.
clientId
- İstemci olarak da adlandırılan uygulamanın tanımlayıcısı. değerini, kayıtlı uygulamanın genel bakış sayfasından daha önce kaydedilen Uygulama (istemci) Kimliği değeriyle değiştirinEnter_the_Application_Id_Here
.authority
- Bu iki bölümden oluşur:- Örnek, bulut sağlayıcısının uç noktasıdır. Ana veya genel Azure bulutu için girin
https://login.microsoftonline.com
. Ulusal bulutlardaki farklı kullanılabilir uç noktaları denetleyin. - Kiracı Kimliği, uygulamanın kayıtlı olduğu kiracının tanımlayıcısıdır. değerini
_Enter_the_Tenant_Info_Here
, kayıtlı uygulamanın genel bakış sayfasından daha önce kaydedilen Dizin (kiracı) kimliği değeriyle değiştirin.
- Örnek, bulut sağlayıcısının uç noktasıdır. Ana veya genel Azure bulutu için girin
redirectUri
- uygulama başarıyla yetkilendirildikten ve yetkilendirme kodu veya erişim belirteci verildikten sonra yetkilendirme sunucusunun kullanıcıyı gönderdiği konum.Enter_the_Redirect_Uri_Here
öğesinihttp://localhost:4200
ile değiştirin.
src/app/app-routing.module.ts açın ve giriş ve profil bileşenlerine yollar ekleyin. Dosyanın tüm içeriğini aşağıdaki kod parçacığıyla değiştirin:
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 {}
src/app/app.component.html açın ve var olan kodu aşağıdakilerle değiştirin:
<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>
CSS'yi tanımlamak için src/style.css açın:
@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%; }
Uygulamaya CSS stili eklemek için src/app/app.component.css açın:
.toolbar-spacer { flex: 1 1 auto; } a.title { color: white; }
Açılır pencereleri kullanarak oturum açma
src/app/app.component.ts dosyasını açın ve açılır pencere kullanarak bir kullanıcıda oturum açmak için dosyanın içeriğini aşağıdakiyle değiştirin:
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; } }
Yeniden yönlendirmeleri kullanarak oturum açma
src/app/app.module.ts'ı önyüklemek için güncelleştirin.
MsalRedirectComponent
Bu, yeniden yönlendirmeleri işleyen ayrılmış bir yeniden yönlendirme bileşenidir.MsalModule
İçeri aktarma veAppComponent
önyükleme ayarlarını aşağıdakine benzer şekilde değiştirin:... import { MsalModule, MsalRedirectComponent } from '@azure/msal-angular'; // Updated import ... bootstrap: [AppComponent, MsalRedirectComponent] // MsalRedirectComponent bootstrapped here ...
src/index.html açın ve dosyanın tüm içeriğini seçiciyi ekleyen
<app-redirect>
aşağıdaki kod parçacığıyla değiştirin:<!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>
src/app/app.component.ts açın ve tam çerçeve yeniden yönlendirme kullanarak bir kullanıcıda oturum açmak için kodu aşağıdakilerle değiştirin:
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; } }
src/app/home/home.component.ts adresine gidin ve olaya abone olmak
LOGIN_SUCCESS
için dosyanın tüm içeriğini aşağıdaki kod parçacığıyla değiştirin: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); }); } }
Koşullu işleme
Belirli Kullanıcı Arabirimini (UI) yalnızca kimliği doğrulanmış kullanıcılar için işlemek için, bileşenlerin kullanıcıların oturum açıp açmadığını ve etkileşimin MsalBroadcastService
tamamlanıp tamamlanmadığını görmek için öğesine abone olması gerekir.
MsalBroadcastService
src/app/app.component.ts öğesine ekleyin ve kullanıcı arabirimini işlemeden önce etkileşimininProgress$
tamamlanıp tamamlanmadiğini ve bir hesabın oturum açıp açmadiğini denetlemek için gözlemlenebilir öğesine abone olun. Kodunuz şimdi şöyle görünmelidir: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(); } }
Kullanıcı arabirimini güncelleştirmeden önce etkileşimin tamamlanacağını denetlemek için src/app/home/home.component.ts içindeki kodu güncelleştirin. Kodunuz şimdi şöyle görünmelidir:
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; } }
src/app/home/home.component.html içindeki kodu aşağıdaki koşullu görüntülerle değiştirin:
<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>
Angular Guard Uygulama
sınıfı MsalGuard
, korumalı yola erişmeden önce yolları korumak ve kimlik doğrulaması gerektirmek için kullanabileceğiniz sınıftır. Aşağıdaki adımlar yolunu MsalGuard
Profile
ekler. Yolu korumak Profile
, bir kullanıcı düğmeyi Login
kullanarak oturum açmasa bile, yola erişmeye Profile
veya düğmeyi seçmeye Profile
çalışırsa, MsalGuard
sayfayı göstermeden önce kullanıcıdan açılır pencere veya yeniden yönlendirme yoluyla kimlik doğrulaması istemesi Profile
anlamına gelir.
MsalGuard
, kullanıcı deneyimini geliştirmek için kullanabileceğiniz bir kolaylık sınıfıdır, ancak güvenlik için bu sınıfa güvenilmemelidir. Saldırganlar potansiyel olarak istemci tarafı korumalarını kullanabilir ve sunucunun kullanıcının erişmemesi gereken verileri döndürmediğinden emin olmanız gerekir.
MsalGuard
src/app/app.module.ts içinde sınıfını uygulamanıza sağlayıcı olarak ekleyin ve içinMsalGuard
yapılandırmaları ekleyin. Belirteçleri daha sonra almak için gereken kapsamlar içindeauthRequest
sağlanabilir ve Guard'ın etkileşim türü veyaPopup
olarakRedirect
ayarlanabilir. Kodunuz aşağıdaki gibi görünmelidir: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
src/app/app-routing.module.ts içinde korumak istediğiniz yolları ayarlayın: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 {}
src/app/app.component.ts oturum açma çağrılarını, koruma yapılandırmalarındaki kümeyi
authRequest
hesaba katacak şekilde ayarlayın. Kodunuz şimdi aşağıdaki gibi görünmelidir: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(); } }
Belirteç alma
Angular Kesme Noktası
MSAL Angular, Angular http
istemcisini kullanan giden istekler için belirteçleri bilinen korumalı kaynaklara otomatik olarak alan bir Interceptor
sınıf sağlar.
Interceptor
src/app/app.module.ts'da sınıfını yapılandırmalarıyla uygulamanıza sağlayıcı olarak ekleyin. Kodunuz şimdi aşağıdaki gibi görünmelidir: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 {}
Korumalı kaynaklar olarak
protectedResourceMap
sağlanır. KoleksiyondaprotectedResourceMap
sağladığınız URL'ler büyük/küçük harfe duyarlıdır. Her kaynak için erişim belirtecinde döndürülmesini istenen kapsamları ekleyin.Örneğin:
["user.read"]
Microsoft Graph için["<Application ID URL>/scope"]
özel web API'leri için (yani )api://<Application ID>/access_as_user
içindeki
protectedResourceMap
değerleri burada açıklandığı gibi değiştirin:Enter_the_Graph_Endpoint_Here
, uygulamanın iletişim kurması gereken Microsoft Graph API örneğidir. Genel Microsoft Graph API uç noktası için bu dizeyi ilehttps://graph.microsoft.com
değiştirin. Ulusal bulut dağıtımlarındaki uç noktalar için Microsoft Graph belgelerindeki Ulusal bulut dağıtımları bölümüne bakın.
Kullanıcının profilini HTTP isteğiyle almak için src/app/profile/profile.component.ts içindeki kodu değiştirin ve değerini Microsoft Graph uç noktasıyla değiştirin
GRAPH_ENDPOINT
: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; }); } }
profil bilgilerini görüntülemek için src/app/profile/profile.component.html kullanıcı arabirimini değiştirin:
<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>
Oturumu kapat
bir düğmeyi koşullu olarak görüntülemek
Logout
için src/app/app.component.html kodunu güncelleştirin:<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>
Yeniden yönlendirmeleri kullanarak oturumu kapatma
Yeniden yönlendirmeleri kullanarak kullanıcının oturumunu kapatmak için src/app/app.component.ts içindeki kodu güncelleştirin:
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(); } }
Açılır pencereleri kullanarak oturumu kapatma
Src/app/app.component.ts içindeki kodu, açılır pencereleri kullanarak bir kullanıcının oturumunu kapatmak için güncelleştirin:
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(); } }
Kodunuza test etme
Uygulama klasöründen bir komut satırı isteminde aşağıdaki komutları çalıştırarak bağlantı noktasını dinlemek için web sunucusunu başlatın:
npm install npm start
Tarayıcınızda yazın
http://localhost:4200
ve aşağıdakine benzer bir sayfa görmeniz gerekir.Profilinize uygulama izinleri vermek için Kabul Et'i seçin. Bu, ilk kez oturum açmaya başladığınızda gerçekleşir.
Onay verdikten sonra, aşağıdaki İstenen izinleri onaylarsanız web uygulaması başarılı bir oturum açma sayfası gösterir.
Microsoft Graph API'sine yapılan çağrıdan yanıtta döndürülen kullanıcı profili bilgilerini görüntülemek için Profil'i seçin:
Kapsamlar ve temsilci izinleri ekleme
Microsoft Graph API'sinde bir kullanıcının profilini okumak için User.Read kapsamı gerekir. User.Read kapsamı her uygulama kaydına otomatik olarak eklenir. Microsoft Graph için diğer API'ler ve arka uç sunucunuz için özel API'ler başka kapsamlar gerektirebilir. Örneğin, Microsoft Graph API'sinde kullanıcının e-postasını listelemek için Mail.Read kapsamı gerekir.
Kapsam eklediğinizde, kullanıcılarınızdan eklenen kapsamlar için ek onay vermesi istenebilir.
Not
Kapsam sayısını artırdığınızda kullanıcıdan ek onaylar istenebilir.
Yardım ve destek
Yardıma ihtiyacınız varsa, bir sorunu bildirmek veya destek seçenekleriniz hakkında bilgi edinmek istiyorsanız bkz . Geliştiriciler için yardım ve destek.
Sonraki adımlar
- Aşağıdaki çok bölümlü öğretici serisinde kullanıcılara oturum açmanızı sağlayan bir React Tek sayfalı uygulama (SPA) oluşturarak daha fazla bilgi edinin.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin