Interceptador MSAL

O MSAL Angular fornece uma Interceptor classe que adquire automaticamente tokens para solicitações de saída que usam o cliente Angular http para recursos protegidos conhecidos. Este documento fornece mais informações sobre a configuração e o uso do MsalInterceptor.

Embora seja recomendável usar a MsalInterceptor API em vez de acquireTokenSilent diretamente, observe que usar a MsalInterceptor opção é opcional. Talvez seja melhor obter tokens explicitamente por meio das APIs acquireToken.

Observe que o MsalInterceptor é fornecido para sua conveniência e pode não se ajustar a todos os casos de uso. Recomendamos que você escreva seu próprio interceptor se tiver necessidades específicas que não sejam atendidas pelo MsalInterceptor.

Configuration

Configurando o MsalInterceptor no app.module.ts

O MsalInterceptor pode ser adicionado ao seu aplicativo como um provedor em app.module.ts, com sua configuração. As importações utilizam uma instância da MSAL, bem como dois objetos de configuração específicos do Angular. O terceiro argumento é um MsalInterceptorConfiguration objeto, que contém os valores para interactionType, a protectedResourceMape um opcional authRequest.

Sua configuração pode se parecer com a abaixo. Consulte nosso documento de configuração sobre outras maneiras de configurar o MSAL Angular para seu aplicativo.

import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS, HttpClientModule } from "@angular/common/http";
import { AppComponent } from './app.component';
import { MsalModule, MsalRedirectComponent, MsalGuard, MsalInterceptor } from '@azure/msal-angular'; // Import MsalInterceptor
import { InteractionType, PublicClientApplication } from '@azure/msal-browser';

@NgModule({
    declarations: [
        AppComponent,
    ],
    imports: [
        MsalModule.forRoot( new PublicClientApplication({
            // MSAL Configuration
        }), {
            // MSAL Guard Configuration
        }, {
            // MSAL Interceptor Configurations
            interactionType: InteractionType.Redirect,
            protectedResourceMap: new Map([ 
                ['Enter_the_Graph_Endpoint_Here/v1.0/me', ['user.read']]
            ])
        })
    ],
    providers: [
        {
            provide: HTTP_INTERCEPTORS, // Provides as HTTP Interceptor
            useClass: MsalInterceptor,
            multi: true
        },
        MsalGuard
    ],
    bootstrap: [AppComponent, MsalRedirectComponent]
})
export class AppModule { }

Tipo de Interação

Embora o MsalInterceptor tenha sido projetado para obter tokens silenciosamente, se uma solicitação em modo silencioso falhar, ele recorrerá à obtenção interativa de tokens. O InteractionType pode ser importado de @azure/msal-browser e definido como Popup ou Redirect.

{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map([ 
        ['Enter_the_Graph_Endpoint_Here/v1.0/me', ['user.read']]
    ])
}

Mapa de Recursos Protegidos

Os recursos protegidos e os escopos correspondentes são fornecidos como um protectedResourceMap na configuração MsalInterceptor.

As URLs fornecidas na coleção protectedResourceMap diferenciam maiúsculas de minúsculas. Para cada recurso, adicione escopos que estão sendo solicitados a serem retornados no token de acesso.

Por exemplo:

  • ["user.read"] para Microsoft Graph
  • ["<Application ID URL>/scope"] para APIs Web personalizadas (ou seja, api://<Application ID>/access_as_user)

Os escopos podem ser especificados para um recurso das seguintes maneiras:

  1. Uma matriz de escopos, que será adicionada a cada solicitação HTTP a esse recurso, independentemente do método HTTP.
{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map<string, Array<string> | null>([
        ["https://graph.microsoft.com/v1.0/me", ["user.read", "profile"]],
        ["https://myapplication.com/user/*", ["customscope.read"]]
    ]),
}
  1. Uma matriz de ProtectedResourceScopes, que anexará escopos somente para métodos HTTP específicos.
{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map<string, Array<string|ProtectedResourceScopes> | null>([
        ["https://graph.microsoft.com/v1.0/me", ["user.read"]],
        ["http://myapplication.com", [
            {
                httpMethod: "POST",
                scopes: ["write.scope"]
            }
        ]]
    ])
}

Observe que os escopos de um recurso podem conter uma combinação de cadeias de caracteres e ProtectedResourceScopes. No exemplo abaixo, uma solicitação GET terá os escopos "all.scope" e "read.scope", enquanto a PUT solicitação teria "all.scope"apenas .

{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map<string, Array<string|ProtectedResourceScopes> | null>([
        ["http://myapplication.com", [
            "all.scope",
            {
                httpMethod: "GET",
                scopes: ["read.scope"]
            },
            {
                httpMethod: "POST",
                scopes: ["info.scope"]
            }
        ]]
    ])
}
  1. Um valor de escopo de null, indicando que um recurso deve ser desprotegido e não obterá tokens. Os recursos não incluídos no protectedResourceMap não são protegidos por padrão. Especificar um recurso específico a ser desprotegido pode ser útil quando algumas rotas em um recurso devem ser protegidas e outras não. Observe que a ordem em protectedResourceMap importa, portanto, o recurso nulo deve ser colocado antes de quaisquer URLs base ou curingas semelhantes.
{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map<string, Array<string> | null>([
        ["https://graph.microsoft.com/v1.0/me", ["user.read", "profile"]],
        ["https://myapplication.com/unprotected", null],
        ["https://myapplication.com/unprotected/post", [{ httpMethod: 'POST', scopes: null }]],
        ["https://myapplication.com", ["custom.scope"]]
    ]),
}

Outras coisas a serem observadas em relação a protectedResourceMap:

  • Curingas: protectedResourceMap suporta o uso de * para curingas. Ao usar caracteres curinga, se várias entradas correspondentes forem encontradas no protectedResourceMap, a primeira correspondência encontrada será usada (com base na ordem do protectedResourceMap).
  • Caminhos relativos: se houver caminhos de recurso relativos em seu aplicativo, talvez seja necessário fornecer o caminho relativo no protectedResourceMap. Isso também se aplica a problemas que podem surgir com ngx-translate. Esteja ciente de que o caminho relativo em seu protectedResourceMap pode ou não precisar de uma barra inicial, dependendo do seu aplicativo, e pode ser necessário tentar ambas.

Correspondência estrita (strictMatching)

No msal-angular v5, a correspondência de padrões de componentes de URL para entradas protectedResourceMap usa semântica de correspondência estrita por padrão. O campo strictMatching em MsalInterceptorConfiguration controla esse comportamento.

Importante

Se o aplicativo definir chaves protectedResourceMap dinamicamente (por exemplo, a partir de arquivos de ambiente, APP_INITIALIZER ou configurações JSON) e essas chaves forem URLs base sem subcaminhos ou curingas, a correspondência estrita poderá impedir silenciosamente que o cabeçalho Authorization seja anexado. Isso resulta em erros 401 sem erro de tempo de compilação e sem aviso por solicitação — apenas um aviso de inicialização único se strictMatching não for configurado explicitamente. Consulte solução de problemas de correspondência estrita para obter detalhes.

Quais são as alterações na correspondência estrita?

Behavior Legado (strictMatching: false) Estrito (padrão na v5)
Escape de metacaracteres . e outros metacaracteres de expressões regulares não são escapados; eles atuam como operadores de expressões regulares. Todos os metacaracters (incluindo .) são tratados como literais
Ancoragem O padrão pode corresponder em qualquer lugar dentro da cadeia de caracteres O padrão deve corresponder à cadeia de caracteres completa (^…$)
Curinga de host (*) * corresponde a qualquer sequência de caracteres, incluindo . * corresponde a qualquer sequência de caracteres que não inclua . (curingas permanecem dentro de um único rótulo DNS)
Curinga de caminho/busca/hash (*) * corresponde a qualquer sequência de caracteres * corresponde a qualquer sequência de caracteres (inalterado)
? caractere Passado para a expressão regular subjacente. Tratado como um literal? (separador de string de consulta de URL, não um curinga).

Com correspondência estrita (o padrão v5):

  • Um padrão como *.contoso.com corresponde a app.contoso.com, mas nãoa.b.contoso.com (curingas não podem abranger separadores de ponto).
  • Um padrão como https://graph.microsoft.com/v1.0/me corresponde apenas à URL exata.

Padrões comuns de falha

Os seguintes padrões de chave protectedResourceMap funcionam com a correspondência legada, mas falham silenciosamente com a correspondência estrita:

Padrão de tecla URL da solicitação de saída Resultado com correspondência exata Corrigir
https://api.example.com https://api.example.com/v1/users Sem correspondência — a chave resolve para o caminho /, a solicitação tem o caminho /v1/users https://api.example.com/*
https://api.example.com/ https://api.example.com/v1/users Sem correspondência — a barra final ancora o padrão exatamente em / https://api.example.com/*
environment.apiConfig.uri (por exemplo, https://api.example.com) https://api.example.com/v1/users Sem correspondência — o mesmo que acima `${environment.apiConfig.uri}/*`

Comportamento padrão na v5 (nenhuma configuração necessária)

A correspondência estrita é habilitada por padrão. Nenhuma configuração adicional é necessária:

{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map([
        ["https://*.contoso.com/api", ["contoso.scope"]],
        ["https://graph.microsoft.com/v1.0/me", ["user.read"]]
    ])
    // strictMatching defaults to true in v5
}

Desativando a correspondência legada

Se os seus padrões dependem da correspondência menos restrita da v4, você pode definir strictMatching: false para manter temporariamente o comportamento legado:

Note

A correspondência legada (strictMatching: false) é fornecida para compatibilidade com versões anteriores e pode ser removida em uma futura versão principal. Recomendamos atualizar seus protectedResourceMap padrões para trabalhar com correspondência estrita.

{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map([
        ["https://*.contoso.com/api", ["contoso.scope"]],
        ["https://graph.microsoft.com/v1.0/me", ["user.read"]]
    ]),
    strictMatching: false  // Use legacy matching for backwards compatibility
}

Diretrizes para configurações controladas pelo ambiente

Se suas chaves protectedResourceMap fizerem referência a valores do Angular environment (por exemplo, environment.apiConfig.uri), verifique se esses valores são caminhos exatos (por exemplo, https://graph.microsoft.com/v1.0/me) ou URLs base simples (por exemplo, https://api.example.com). Os caminhos exatos funcionam corretamente com correspondência estrita e não precisam de tratamento especial:

export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
  const protectedResourceMap = new Map<string, Array<string>>();
  // environment.apiConfig.uri is an exact path (e.g. "https://graph.microsoft.com/v1.0/me")
  // — strict matching works correctly
  protectedResourceMap.set(environment.apiConfig.uri, environment.apiConfig.scopes);

  return {
    interactionType: InteractionType.Redirect,
    protectedResourceMap,
  };
}

Se o valor do ambiente for uma URL base simples e você precisar corresponder a subcaminhos, adicione um curinga /*:

  // environment.apiConfig.uri is a base URL (e.g. "https://api.example.com")
  // Append /* to match all sub-paths
  protectedResourceMap.set(`${environment.apiConfig.uri}/*`, environment.apiConfig.scopes);

Para configurações verdadeiramente dinâmicas em que a forma de chave não é conhecida no momento da compilação (por exemplo, APP_INITIALIZERJSON carregado via fetchou platformBrowserDynamic), defina strictMatching: false como um padrão seguro temporário. Consulte opções de correção — opção B para obter um exemplo de código.

Solução de problemas de correspondência estrita

Symptoms
  • As solicitações de API retornam 401 Não autorizadas após a atualização para v5 @azure/msal-angular (ou entre versões secundárias v5, como 5.0.x → 5.1.x).
  • O Authorization: Bearer <token> cabeçalho está ausente das solicitações HTTP de saída.
  • Nenhum erro de tempo de build ou de runtime é relatado— a falha é silenciosa.
  • O problema só pode aparecer em determinados ambientes (por exemplo, preparo/produção), em que a URL base da API difere do desenvolvimento.
Opções de correção

Opção A: Atualizar chaves para trabalhar com correspondência estrita (recomendado)

Atualize suas chaves protectedResourceMap para usar caminhos exatos ou curingas que correspondam às regras de correspondência estrita. Essa abordagem é preferencial porque a correspondência estrita é mais segura e previsível:

{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map([
        // Exact path — matches only this URL
        ["https://graph.microsoft.com/v1.0/me", ["user.read"]],
        // Wildcard — matches all sub-paths of the API
        ["https://api.example.com/v1/*", ["api.scope"]]
    ])
    // strictMatching defaults to true — no need to set it
}

Opção B: Definir strictMatching: false (fallback para configurações dinâmicas)

Se suas chaves protectedResourceMap forem carregadas dinamicamente em tempo de execução (por exemplo, de APP_INITIALIZER, configuração JSON ou platformBrowserDynamic) e você não puder garantir que elas contenham caminhos exatos ou curingas, defina strictMatching: false como um padrão seguro temporário:

{
    interactionType: InteractionType.Redirect,
    protectedResourceMap: new Map([
        [config.apiUri, config.apiScopes]
    ]),
    // Dynamic keys may be base URLs without wildcards.
    // Remove once keys are migrated to exact paths or wildcard patterns.
    strictMatching: false
}

Note

A correspondência legada (strictMatching: false) é fornecida para compatibilidade com versões anteriores e pode ser removida em uma futura versão principal.

Aviso de tempo de execução

MsalInterceptor emite um aviso de tempo de execução único por meio do logger MSAL durante a inicialização quando strictMatching não estiver explicitamente configurado. Se você vir esse aviso, siga as opções de correção acima.

authRequest opcional

Para obter mais informações sobre o authRequest opcional que pode ser definido no MsalInterceptorConfiguration, consulte nossa documentação multilocatária aqui.

Alterações de msal-angular v1 para v2

Note

O unprotectedResourceMap no MsalAngularConfiguration do MSAL Angular v1 foi descontinuado e não funciona mais.

  • protectedResourceMap foi movido para o MsalInterceptorConfiguration objeto e pode ser passado como Map<string, Array<string|ProtectedResourceScopes>>. MsalAngularConfiguration foi preterido e não funciona mais.
  • Colocar o domínio raiz no protectedResourceMap para proteger todas as rotas não é mais compatível. Use correspondência de curinga em vez disso.

Para obter mais informações sobre como configurar escopos, consulte nossas perguntas frequentes.