Partilhar via


Ativar a autenticação na sua própria Aplicação Angular com o Azure Active Directory B2C

Este artigo mostra-lhe como adicionar a autenticação do Azure Active Directory B2C (Azure AD B2C) à sua própria aplicação de página única (SPA) Angular. Saiba como integrar uma aplicação Angular na biblioteca de autenticação MSAL para Angular.

Utilize este artigo com o artigo relacionado intitulado Configurar a autenticação num exemplo Angular aplicação de página única. Substitua a aplicação de Angular de exemplo pela sua própria aplicação Angular. Depois de concluir os passos neste artigo, a sua aplicação aceitará inícios de sessão através do Azure AD B2C.

Pré-requisitos

Conclua os passos no artigo Configurar autenticação num exemplo Angular aplicação de página única.

Criar um projeto de aplicação Angular

Pode utilizar um projeto de aplicação Angular existente ou criar um novo. Para criar um novo projeto, execute os seguintes comandos.

Os comandos:

  1. Instale o Angular CLI com o gestor de pacotes npm.
  2. Crie uma área de trabalho Angular com um módulo de encaminhamento. O nome da aplicação é msal-angular-tutorial. Pode alterá-lo para qualquer nome de aplicação Angular válido, como contoso-car-service.
  3. Mude para a pasta do diretório da aplicação.
npm install -g @angular/cli 
ng new msal-angular-tutorial --routing=true --style=css --strict=false
cd msal-angular-tutorial

Instalar as dependências

Para instalar as bibliotecas msAL Browser e MSAL Angular na sua aplicação, execute o seguinte comando na shell de comandos:

npm install @azure/msal-browser @azure/msal-angular

Instale a biblioteca de componentes Angular Material (opcional, para IU):

npm install @angular/material @angular/cdk

Adicionar os componentes de autenticação

O código de exemplo consiste nos seguintes componentes:

Componente Tipo Description
auth-config.ts Constantes Este ficheiro de configuração contém informações sobre o seu Azure AD fornecedor de identidade B2C e o serviço de API Web. A aplicação Angular utiliza estas informações para estabelecer uma relação de confiança com Azure AD B2C, iniciar sessão e terminar sessão do utilizador, adquirir tokens e validar os tokens.
app.module.ts módulo Angular Este componente descreve como as partes da aplicação se encaixam. Este é o módulo de raiz utilizado para iniciar o programa de arranque e abrir a aplicação. Nestas instruções, vai adicionar alguns componentes ao módulo app.module.ts e iniciar a biblioteca MSAL com o objeto de configuração MSAL.
app-routing.module.ts Angular módulo de encaminhamento Este componente permite a navegação ao interpretar um URL do browser e ao carregar o componente correspondente. Nestas instruções, vai adicionar alguns componentes ao módulo de encaminhamento e proteger os componentes com o MSAL Guard. Apenas os utilizadores autorizados podem aceder aos componentes protegidos.
app.component.* componente Angular O ng new comando criou um projeto Angular com um componente raiz. Nestas instruções, vai alterar o componente da aplicação para alojar a barra de navegação superior. A barra de navegação contém vários botões, incluindo botões de início de sessão e de início de sessão. A app.component.ts classe processa os eventos de início de sessão e fim de sessão.
home.component.* componente Angular Nestas instruções, vai adicionar o componente raiz para compor a home page para acesso anónimo. Este componente demonstra como verificar se um utilizador iniciou sessão.
profile.component.* componente Angular Nestas instruções, vai adicionar o componente de perfil para saber como ler as afirmações de token de ID.
webapi.component.* componente Angular Nestas instruções, vai adicionar o componente webapi para saber como chamar uma API Web.

Para adicionar os seguintes componentes à sua aplicação, execute os seguintes comandos Angular CLI. Os generate component comandos:

  1. Crie uma pasta para cada componente. A pasta contém os ficheiros typeScript, HTML, CSS e de teste.
  2. Atualize os app.module.ts ficheiros e app-routing.module.ts com referências aos novos componentes.
ng generate component home
ng generate component profile
ng generate component webapi

Adicionar as definições da aplicação

As definições do Azure AD fornecedor de identidade B2C e da API Web são armazenadas no ficheiro auth-config.ts. Na pasta src/app , crie um ficheiro com o nome auth-config.ts que contenha o seguinte código. Em seguida, altere as definições conforme descrito em 3.1 Configurar o exemplo de Angular.

import { LogLevel, Configuration, BrowserCacheLocation } from '@azure/msal-browser';

const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1;
 
export const b2cPolicies = {
     names: {
         signUpSignIn: "b2c_1_susi_reset_v2",
         editProfile: "b2c_1_edit_profile_v2"
     },
     authorities: {
         signUpSignIn: {
             authority: "https://your-tenant-name.b2clogin.com/your-tenant-name.onmicrosoft.com/b2c_1_susi_reset_v2",
         },
         editProfile: {
             authority: "https://your-tenant-name.b2clogin.com/your-tenant-name.onmicrosoft.com/b2c_1_edit_profile_v2"
         }
     },
     authorityDomain: "your-tenant-name.b2clogin.com"
 };
 
 
export const msalConfig: Configuration = {
     auth: {
         clientId: '<your-MyApp-application-ID>',
         authority: b2cPolicies.authorities.signUpSignIn.authority,
         knownAuthorities: [b2cPolicies.authorityDomain],
         redirectUri: '/', 
     },
     cache: {
         cacheLocation: BrowserCacheLocation.LocalStorage,
         storeAuthStateInCookie: isIE, 
     },
     system: {
         loggerOptions: {
            loggerCallback: (logLevel, message, containsPii) => {
                console.log(message);
             },
             logLevel: LogLevel.Verbose,
             piiLoggingEnabled: false
         }
     }
 }

export const protectedResources = {
  todoListApi: {
    endpoint: "http://localhost:5000/api/todolist",
    scopes: ["https://your-tenant-name.onmicrosoft.com/api/tasks.read"],
  },
}
export const loginRequest = {
  scopes: []
};

Iniciar as bibliotecas de autenticação

As aplicações cliente públicas não são consideradas fidedignas para manter os segredos da aplicação em segurança, pelo que não têm segredos do cliente. Na pasta src/app , abra app.module.ts e faça as seguintes alterações:

  1. Importe as bibliotecas MSAL Angular e MSAL Browser.
  2. Importe o Azure AD módulo de configuração B2C.
  3. Importar HttpClientModule. O cliente HTTP é utilizado para chamar APIs Web.
  4. Importe o Angular intercetor HTTP. A MSAL utiliza o intercetor para injetar o token de portador no cabeçalho de autorização HTTP.
  5. Adicione os materiais de Angular essenciais.
  6. Instanciar a MSAL com o objeto de aplicação cliente público de várias contas. A inicialização do MSAL inclui a transmissão:
    1. O objeto de configuração para auth-config.ts.
    2. O objeto de configuração da proteção de encaminhamento.
    3. O objeto de configuração do intercetor MSAL. A classe de intercetor adquire automaticamente tokens para pedidos de saída que utilizam a classe Angular HttpClient para recursos protegidos conhecidos.
  7. Configure os HTTP_INTERCEPTORSfornecedores e MsalGuard Angular.
  8. Adicione MsalRedirectComponent ao Angular bootstrap.

Na pasta src/app , edite app.module.ts e faça as modificações apresentadas no fragmento de código seguinte. As alterações são sinalizadas com "As alterações começam aqui" e "As alterações terminam aqui".

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

/* Changes start here. */
// Import MSAL and MSAL browser libraries. 
import { MsalGuard, MsalInterceptor, MsalModule, MsalRedirectComponent } from '@azure/msal-angular';
import { InteractionType, PublicClientApplication } from '@azure/msal-browser';

// Import the Azure AD B2C configuration 
import { msalConfig, protectedResources } from './auth-config';

// Import the Angular HTTP interceptor. 
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { ProfileComponent } from './profile/profile.component';
import { HomeComponent } from './home/home.component';
import { WebapiComponent } from './webapi/webapi.component';

// Add the essential Angular materials.
import { MatButtonModule } from '@angular/material/button';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatListModule } from '@angular/material/list';
import { MatTableModule } from '@angular/material/table';
/* Changes end here. */

@NgModule({
  declarations: [
    AppComponent,
    ProfileComponent,
    HomeComponent,
    WebapiComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    /* Changes start here. */
    // Import the following Angular materials. 
    MatButtonModule,
    MatToolbarModule,
    MatListModule,
    MatTableModule,
    // Import the HTTP client. 
    HttpClientModule,

    // Initiate the MSAL library with the MSAL configuration object
    MsalModule.forRoot(new PublicClientApplication(msalConfig),
      {
        // The routing guard configuration. 
        interactionType: InteractionType.Redirect,
        authRequest: {
          scopes: protectedResources.todoListApi.scopes
        }
      },
      {
        // MSAL interceptor configuration.
        // The protected resource mapping maps your web API with the corresponding app scopes. If your code needs to call another web API, add the URI mapping here.
        interactionType: InteractionType.Redirect,
        protectedResourceMap: new Map([
          [protectedResources.todoListApi.endpoint, protectedResources.todoListApi.scopes]
        ])
      })
    /* Changes end here. */
  ],
  providers: [
    /* Changes start here. */
    {
      provide: HTTP_INTERCEPTORS,
      useClass: MsalInterceptor,
      multi: true
    },
    MsalGuard
    /* Changes end here. */
  ],
  bootstrap: [
    AppComponent,
    /* Changes start here. */
    MsalRedirectComponent
    /* Changes end here. */
  ]
})
export class AppModule { }

Configurar rotas

Nesta secção, configure as rotas para a sua aplicação Angular. Quando um utilizador seleciona uma ligação na página para se mover na sua aplicação de página única ou introduz um URL na barra de endereço, as rotas mapeiam o URL para um componente Angular. A interface canActivate do encaminhamento do Angular utiliza o MSAL Guard para verificar se o utilizador tem sessão iniciada. Se o utilizador não tiver sessão iniciada, a MSAL leva o utilizador a Azure AD B2C para se autenticar.

Na pasta src/app , edite app-routing.module.ts efetue as modificações apresentadas no fragmento de código seguinte. As alterações são sinalizadas com "As alterações começam aqui" e "As alterações terminam aqui".

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MsalGuard } from '@azure/msal-angular';
import { HomeComponent } from './home/home.component';
import { ProfileComponent } from './profile/profile.component';
import { WebapiComponent } from './webapi/webapi.component';

const routes: Routes = [
  /* Changes start here. */
  {
    path: 'profile',
    component: ProfileComponent,
    // The profile component is protected with MSAL Guard.
    canActivate: [MsalGuard]
  },
  {
    path: 'webapi',
    component: WebapiComponent,
    // The profile component is protected with MSAL Guard.
    canActivate: [MsalGuard]
  },
  {
    // The home component allows anonymous access
    path: '',
    component: HomeComponent
  }
  /* Changes end here. */
];


@NgModule({
  /* Changes start here. */
  // Replace the following line with the next one
  //imports: [RouterModule.forRoot(routes)],
  imports: [RouterModule.forRoot(routes, {
    initialNavigation:'enabled'
  })],
  /* Changes end here. */
  exports: [RouterModule]
})
export class AppRoutingModule { }

Adicionar os botões de início de sessão e de início de sessão

Nesta secção, vai adicionar os botões de início de sessão e de início de sessão ao componente da aplicação . Na pasta src/app , abra o ficheiro app.component.ts e faça as seguintes alterações:

  1. Importe os componentes necessários.

  2. Altere a classe para implementar o método OnInit. O OnInit método subscreve o evento observável MSAL MsalBroadcastServiceinProgress$ . Utilize este evento para saber o estado das interações do utilizador, especialmente para verificar se as interações estão concluídas.

    Antes das interações com o objeto da conta MSAL, verifique se a InteractionStatus propriedade devolve InteractionStatus.None. O subscribe evento chama o setLoginDisplay método para verificar se o utilizador está autenticado.

  3. Adicione variáveis de classe.

  4. Adicione o método que inicia o login fluxo de autorização.

  5. Adicione o logout método que termina a sessão do utilizador.

  6. Adicione o setLoginDisplay método que verifica se o utilizador está autenticado.

  7. Adicione o método ngOnDestroy para limpar o inProgress$ evento de subscrição.

Após as alterações, o código deverá ter o seguinte aspeto:

import { Component, OnInit, 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']
})

/* Changes start here. */
export class AppComponent implements OnInit{
  title = 'msal-angular-tutorial';
  loginDisplay = false;
  private readonly _destroying$ = new Subject<void>();

  constructor(@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration, private broadcastService: MsalBroadcastService, private authService: MsalService) { }

  ngOnInit() {

    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() { 
    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();
  }
  /* Changes end here. */
}

Na pasta src/app , edite app.component.html e faça as seguintes alterações:

  1. Adicione uma ligação para os componentes da API Web e do perfil.
  2. Adicione o botão de início de sessão com o atributo click event definido para o login() método . Este botão só é apresentado se a variável de loginDisplay classe for false.
  3. Adicione o botão logout com o atributo click event definido para o logout() método . Este botão só é apresentado se a variável de loginDisplay classe for true.
  4. Adicione um elemento router-outlet .

Após as alterações, o código deverá ter o seguinte aspeto:

<mat-toolbar color="primary">
  <a class="title" href="/">{{ title }}</a>

  <div class="toolbar-spacer"></div>

  <a mat-button [routerLink]="['profile']">Profile</a>
  <a mat-button [routerLink]="['webapi']">Web API</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">
  <router-outlet></router-outlet>
</div>

Opcionalmente, atualize o ficheiro app.component.css com o seguinte fragmento CSS:

.toolbar-spacer {
    flex: 1 1 auto;
  }

  a.title {
    color: white;
  }

Processar os redirecionamentos da aplicação

Quando estiver a utilizar redirecionamentos com a MSAL, tem de adicionar a diretiva de redirecionamento de aplicações para index.html. Na pasta src , edite index.html conforme mostrado no seguinte fragmento de código:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MsalAngularTutorial</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>
  <!-- Changes start here -->
  <app-redirect></app-redirect>
  <!-- Changes end here -->
</body>
</html>

Definir CSS da aplicação (opcional)

Na pasta /src , atualize o ficheiro styles.css com o seguinte fragmento 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%; }

Dica

Neste momento, pode executar a sua aplicação e testar a experiência de início de sessão. Para executar a sua aplicação, veja a secção Executar a aplicação Angular.

Verificar se um utilizador está autenticado

O ficheiro home.component demonstra como verificar se o utilizador está autenticado. Na pasta src/app/home , atualize home.component.ts com o seguinte fragmento de código.

O código:

  1. Subscreve o MSAL MsalBroadcastServicemsalSubject$ e inProgress$ eventos observáveis.
  2. Garante que o msalSubject$ evento escreve o resultado da autenticação na consola do browser.
  3. Garante que o inProgress$ evento verifica se um utilizador está autenticado. O getAllAccounts() método devolve um ou mais objetos.
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;
  }
}

Na pasta src/app/home , atualize home.component.html com o seguinte fragmento HTML. A diretiva *ngIf verifica a variável de loginDisplay classe para mostrar ou ocultar as mensagens de boas-vindas.

<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>

Ler as afirmações de token de ID

O ficheiro profile.component demonstra como aceder às afirmações de token de ID do utilizador. Na pasta src/app/profile , atualize profile.component.ts com o seguinte fragmento de código.

O código:

  1. Importa os componentes necessários.
  2. Subscreve o evento observável MSAL MsalBroadcastServiceinProgress$ . O evento carrega a conta e lê as afirmações do token de ID.
  3. Garante que o checkAndSetActiveAccount método verifica e define a conta ativa. Esta ação é comum quando a aplicação interage com vários Azure AD fluxos de utilizador B2C ou políticas personalizadas.
  4. Garante que o getClaims método obtém as afirmações de token de ID do objeto de conta MSAL ativo. Em seguida, o método adiciona as afirmações à dataSource matriz. A matriz é composta para o utilizador com o enlace de modelo do componente.
import { Component, OnInit } from '@angular/core';
import { MsalBroadcastService, MsalService } from '@azure/msal-angular';
import { EventMessage, EventType, InteractionStatus } from '@azure/msal-browser';
import { Subject } from 'rxjs';
import { filter, takeUntil } from 'rxjs/operators';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})

export class ProfileComponent implements OnInit {
  displayedColumns: string[] = ['claim', 'value'];
  dataSource: Claim[] = [];
  private readonly _destroying$ = new Subject<void>();
  
  constructor(private authService: MsalService, private msalBroadcastService: MsalBroadcastService) { }

  ngOnInit(): void {

    this.msalBroadcastService.inProgress$
      .pipe(
        filter((status: InteractionStatus) =>  status === InteractionStatus.None || status === InteractionStatus.HandleRedirect),
        takeUntil(this._destroying$)
      )
      .subscribe(() => {
        this.checkAndSetActiveAccount();
        this.getClaims(this.authService.instance.getActiveAccount()?.idTokenClaims)
      })
  }

  checkAndSetActiveAccount() {

    let activeAccount = this.authService.instance.getActiveAccount();

    if (!activeAccount && this.authService.instance.getAllAccounts().length > 0) {
      let accounts = this.authService.instance.getAllAccounts();
      this.authService.instance.setActiveAccount(accounts[0]);
    }
  }

  getClaims(claims: any) {

    let list: Claim[]  =  new Array<Claim>();

    Object.keys(claims).forEach(function(k, v){
      
      let c = new Claim()
      c.id = v;
      c.claim = k;
      c.value =  claims ? claims[k]: null;
      list.push(c);
    });
    this.dataSource = list;

  }

  ngOnDestroy(): void {
    this._destroying$.next(undefined);
    this._destroying$.complete();
  }
}

export class Claim {
  id: number;
  claim: string;
  value: string;
}

Na pasta src/app/profile , atualize profile.component.html com o seguinte fragmento HTML:

<h1>ID token claims:</h1>

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

  <!-- Claim Column -->
  <ng-container matColumnDef="claim">
    <th mat-header-cell *matHeaderCellDef> Claim </th>
    <td mat-cell *matCellDef="let element"> {{element.claim}} </td>
  </ng-container>

  <!-- Value Column -->
  <ng-container matColumnDef="value">
    <th mat-header-cell *matHeaderCellDef> Value </th>
    <td mat-cell *matCellDef="let element"> {{element.value}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

Chamar uma API Web

Para chamar uma API Web de autorização baseada em tokens, a aplicação precisa de ter um token de acesso válido. O fornecedor do MsalInterceptor adquire automaticamente tokens para pedidos de saída que utilizam a classe Angular HttpClient para recursos protegidos conhecidos.

Importante

O método de inicialização MSAL (na app.module.ts classe) mapeia recursos protegidos, como APIs Web, com os âmbitos de aplicação necessários através do protectedResourceMap objeto . Se o código precisar de chamar outra API Web, adicione o URI da API Web e o método HTTP da API Web, com os âmbitos correspondentes, ao protectedResourceMap objeto. Para obter mais informações, veja Mapa de Recursos Protegidos.

Quando o objeto HttpClient chama uma API Web, o fornecedor msalInterceptor executa os seguintes passos:

  1. Adquire um token de acesso com as permissões (âmbitos) necessárias para o ponto final da API Web.

  2. Transmite o token de acesso como um token de portador no cabeçalho de autorização do pedido HTTP com este formato:

    Authorization: Bearer <access-token>
    

O ficheiro webapi.component demonstra como chamar uma API Web. Na pasta src/app/webapi , atualize webapi.component.ts com o seguinte fragmento de código.

O código:

  1. Utiliza o Angular classe HttpClient para chamar a API Web.
  2. Lê o auth-config elemento da protectedResources.todoListApi.endpoint classe. Este elemento especifica o URI da API Web. Com base no URI da API Web, o intercetor MSAL adquire um token de acesso com os âmbitos correspondentes.
  3. Obtém o perfil a partir da API Web e define a variável de profile classe.
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { protectedResources } from '../auth-config';

type ProfileType = {
  name?: string
};

@Component({
  selector: 'app-webapi',
  templateUrl: './webapi.component.html',
  styleUrls: ['./webapi.component.css']
})
export class WebapiComponent implements OnInit {
  todoListEndpoint: string = protectedResources.todoListApi.endpoint;
  profile!: ProfileType;

  constructor(
    private http: HttpClient
  ) { }

  ngOnInit() {
    this.getProfile();
  }

  getProfile() {
    this.http.get(this.todoListEndpoint)
      .subscribe(profile => {
        this.profile = profile;
      });
  }
}

Na pasta src/app/webapi , atualize webapi.component.html com o seguinte fragmento HTML. O modelo do componente compõe o nome que a API Web devolve. Na parte inferior da página, o modelo compõe o endereço da API Web.

<h1>The web API returns:</h1>
<div>
    <p><strong>Name: </strong> {{profile?.name}}</p>
</div>

<div class="footer-text">
    Web API: {{todoListEndpoint}}
</div>

Opcionalmente, atualize o ficheiro webapi.component.css com o seguinte fragmento CSS:

.footer-text {
    position: absolute;
    bottom: 50px;
    color: gray;
}

Executar a aplicação Angular

Execute o seguinte comando:

npm start

A janela da consola apresenta o número da porta onde a aplicação está alojada.

Listening on port 4200...

Dica

Em alternativa, para executar o npm start comando, utilize o depurador do Visual Studio Code. O depurador ajuda a acelerar o ciclo de edição, compilação e depuração.

Aceda a http://localhost:4200 no browser para ver a aplicação.

Passos seguintes