Sobreposição de chave de assinatura na plataforma de identidade da Microsoft

Este artigo aborda o que você precisa saber sobre as chaves públicas usadas pela plataforma de identidade da Microsoft para autenticar tokens de segurança. É importante observar que essas chaves são substituídas em intervalos periódicos e, em caso de emergência, podem ser substituídas imediatamente. Todos os aplicativos que usam a plataforma de identidade da Microsoft devem ser capazes de tratar programaticamente o processo de substituição de chave. Você vai entender como as chaves funcionam, como avaliar o impacto da rotação sobre o seu aplicativo e como atualizar seu aplicativo ou estabelecer um processo de rotação periódica manual para lidar com a rotação de chaves, se necessário.

Visão geral das chaves de assinatura na plataforma de identidade da Microsoft

A plataforma de identidade da Microsoft usa criptografia de chave pública criada nos padrões da indústria para estabelecer a confiança entre ela e os aplicativos que a utilizam. Em termos práticos, isso funciona da seguinte maneira: a plataforma de identidade da Microsoft usa uma chave de assinatura que consiste em um par de chaves público e privado. Quando um usuário entra em um aplicativo que usa a plataforma de identidade da Microsoft para autenticação, a plataforma de identidade da Microsoft cria um token de segurança que contém informações sobre o usuário. Esse token é assinado pela plataforma de identidade da Microsoft usando sua chave privada antes de ser enviado de volta para o aplicativo. Para verificar se o token é válido e é originado a partir da plataforma de identidade da Microsoft, o aplicativo deverá validar a assinatura do token usando a chave pública exposta pela plataforma de identidade da Microsoft que está contida no documento de descoberta do OpenID Connect do locatário ou o documento de metadados federados do locatário SAML/WS-Fed.

Para fins de segurança, a chave de assinatura da plataforma de identidade da Microsoft é substituída periodicamente e, em caso de emergência, pode ser substituída imediatamente. Não há nenhum tempo definido ou garantido entre esses sobreposições de chave - qualquer aplicativo que se integre com a plataforma de identidade da Microsoft deve estar preparado para tratar um evento de sobreposição de chave, independentemente da frequência na qual possa ocorrer. Se não aceitar atualizações repentinas e tentar usar uma chave expirada para verificar a assinatura em um token, seu aplicativo rejeitará o token indevidamente. Verificar atualizações a cada 24 horas é uma prática recomendada, com restrições (uma vez a cada cinco minutos no máximo) atualizações imediatas do documento de chave se um token for encontrado e não for validado com as chaves no cache do seu aplicativo.

Sempre há mais de uma chave pública válida disponível no documento de descoberta do OpenID Connect e no documento de metadados de federação. O aplicativo deve estar preparado para usar toda e qualquer chave especificada no documento, já que uma das chaves pode ser substituída em breve, a outra pode ser a sua substituta e assim por diante. O número de chaves presentes pode mudar ao longo do tempo com base na arquitetura interna da plataforma de identidade da Microsoft à medida que damos suporte a novas plataformas, novas nuvens ou novos protocolos de autenticação. Nem a ordem das chaves na resposta JSON nem a ordem na qual elas foram expostas deve ser considerada significativa para seu aplicativo.

Os aplicativos que dão suporte a apenas uma única chave de assinatura, ou aqueles que exigem atualizações manuais para as chaves de assinatura, são inerentemente menos seguros e menos confiáveis. Eles devem ser atualizados para usar bibliotecas padrão a fim de garantir que estejam sempre usando chaves de assinatura atualizadas, entre outras práticas recomendadas.

Como avaliar se o aplicativo será afetado e o que fazer com ele

Como o seu aplicativo lida com a substituição de chave depende de variáveis como o tipo de aplicativo ou que protocolo de identidade e biblioteca foi usado. As seções a seguir avaliam se os tipos mais comuns de aplicativos são afetados pela substituição de chave e fornecem diretrizes sobre como atualizar o aplicativo para dar suporte à substituição automática ou à atualização manual da chave.

Esta diretriz não é aplicável:

  • Os aplicativos adicionados a partir da galeria de aplicativos do Microsoft Entra ID (incluindo os personalizados) têm diretrizes separadas no que se refere a chaves de assinatura. Mais informações.
  • Os aplicativos locais publicados por meio do proxy de aplicativo não precisam se preocupar com as chaves de assinatura.

Aplicativos cliente nativos que acessam recursos

Os aplicativos que acessam apenas recursos (por exemplo, Microsoft Graph, KeyVault, API do Outlook e outras APIs da Microsoft) obtêm apenas um token e o passam ao proprietário do recurso. Já que eles não estão protegendo recursos, não inspecionam o token e, portanto, não é necessário garantir que ele esteja adequadamente assinado.

Os aplicativos cliente nativos, tanto da área de trabalho como móveis, entram nessa categoria e, portanto, não são afetados pela substituição.

Aplicativos/APIs Web que acessam recursos

Os aplicativos que acessam apenas recursos (como, Microsoft Graph, KeyVault, API do Outlook e outras APIs da Microsoft) obtêm apenas um token e o passam ao proprietário do recurso. Já que eles não estão protegendo recursos, não inspecionam o token e, portanto, não é necessário garantir que ele esteja adequadamente assinado.

Os aplicativos Web e as APIs Web que estão usando o fluxo somente para aplicativo (credenciais de cliente/certificado de cliente) a fim de solicitar tokens, entram nessa categoria e, portanto, não são afetados pela sobreposição.

Aplicativos/APIs Web que protegem recursos e criam usando os Serviços de Aplicativo do Azure

A funcionalidade de Autenticação/Autorização (EasyAuth) dos Serviços de Aplicativo do Azure já tem a lógica necessária para tratar a substituição de chave automaticamente.

Aplicativos Web/APIs que protegem recursos usando o middleware OWIN do ASP.NET OpenID Connect, WS-Fed ou WindowsAzureActiveDirectoryBearerAuthentication

Se o seu aplicativo estiver usando o middleware ASP.NET OWIN OpenID Connect, WS-Fed ou WindowsAzureActiveDirectoryBearerAuthentication, ele já terá a logica necessária para tratar automaticamente a sobreposição de chaves.

Você pode confirmar se seu aplicativo está usando qualquer um deles ao procurar qualquer um dos snippets no Startup.cs ou Startup.Auth.cs do seu aplicativo.

app.UseOpenIdConnectAuthentication(
    new OpenIdConnectAuthenticationOptions
    {
        // ...
    });
app.UseWsFederationAuthentication(
    new WsFederationAuthenticationOptions
    {
        // ...
    });
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
    new WindowsAzureActiveDirectoryBearerAuthenticationOptions
    {
        // ...
    });

Aplicativos/APIs Web protegendo recursos usando .NET Core OpenID Connect ou o middleware JwtBearerAuthentication

Se o seu aplicativo estiver usando o middleware ASP.NET OWIN OpenID Connect ou JwtBearerAuthentication, ele já terá a logica necessária para tratar automaticamente a sobreposição de chaves.

Você pode confirmar que seu aplicativo está usando qualquer um desses ao procurar qualquer um dos snippets no Startup.cs ou Startup.Auth.cs do seu aplicativo

app.UseOpenIdConnectAuthentication(
     new OpenIdConnectAuthenticationOptions
     {
         // ...
     });
app.UseJwtBearerAuthentication(
    new JwtBearerAuthenticationOptions
    {
     // ...
     });

Aplicativos Web/APIs que protegem recursos usando o módulo Node.js passport-azure-ad

Se seu aplicativo estiver usando o módulo passport-ad do Node.js, ele já terá a lógica necessária para tratar a substituição de chave automaticamente.

Você pode confirmar que seu aplicativo tem passport-ad pesquisando o snippet a seguir no app.js do seu aplicativo

var OIDCStrategy = require('passport-azure-ad').OIDCStrategy;

passport.use(new OIDCStrategy({
    //...
));

APIs/Aplicativos Web que protegem recursos e que foram criados com o Visual Studio 2015 ou posterior

Se seu aplicativo tiver sido criado usando um modelo de aplicativo Web no Visual Studio 2015 ou posterior e se você tiver selecionado Contas Corporativas ou de Estudante no menu Alterar Autenticação, ele já terá a lógica necessária para tratar da substituição de chave automaticamente. Essa lógica, incorporada ao middleware OWIN OpenID Connect, recupera as chaves de documento de descoberta do OpenID Connect, as armazena em cache e as atualiza periodicamente.

Se você tiver adicionado a autenticação à sua solução manualmente, talvez seu aplicativo não tenha a lógica de substituição de chave necessária. Você precisará escrevê-la por conta própria ou seguir as etapas em Aplicativos/APIs Web que usam quaisquer outras bibliotecas ou implementam manualmente os protocolos com suporte.

Aplicativos/APIs Web que protegem recursos e que foram criados com o Visual Studio 2013

Se seu aplicativo tiver sido criado usando um modelo de aplicativo Web no Visual Studio 2013 e você selecionou Contas Organizacionais no menu Alterar Autenticação, ele já tem a lógica necessária para tratar da substituição de chave automaticamente. Essa lógica armazena o identificador exclusivo da sua organização e as informações de chave de autenticação em duas tabelas de banco de dados associadas ao projeto. Você pode encontrar a cadeia de conexão para o banco de dados no arquivo Web.config do projeto.

Se você tiver adicionado a autenticação à sua solução manualmente, talvez seu aplicativo não tenha a lógica de substituição de chave necessária. Você precisará escrevê-la por conta própria ou seguir as etapas em Aplicativos/APIs Web que usam quaisquer outras bibliotecas ou que implementam manualmente qualquer um dos protocolos com suporte..

As etapas a seguir ajudam a verificar se a lógica está funcionando corretamente em seu aplicativo.

  1. No Visual Studio 2013, abra a solução e selecione a guia Gerenciador de Servidores na janela à direita.
  2. Expanda Conexões de dados, DefaultConnection, e em seguida Tabelas. Localize a tabela IssuingAuthorityKeys, clique com o botão direito do mouse e selecione Mostrar Dados da Tabela.
  3. Na tabela IssuingAuthorityKeys, haverá pelo menos uma fila, que corresponde ao valor da impressão para a chave. Exclua todas as linhas na tabela.
  4. Clique com o botão direito do mouse na tabela Locatários e, a seguir, selecione Mostrar Dados da Tabela.
  5. Na tabela Locatários, haverá pelo menos uma fila, que corresponde a um identificador único do locatário do diretório. Exclua todas as linhas na tabela. Se não excluir as linhas nas duas tabelas Locatários e IssuingAuthorityKeys, você obterá um erro no runtime.
  6. Compile e execute o aplicativo. Depois de entrar na sua conta, você poderá interromper o aplicativo.
  7. Volte no Explorador do Servidor e olhe os valores na tabela IssuingAuthorityKeys e Locatários. Você notará que eles foram repopulados automaticamente com as informações apropriadas do documento de metadados federados.

APIs Web que protegem recursos e que foram criados com o Visual Studio 2013

Se você tiver criado um aplicativo API no Visual Studio 2013 usando o modelo API da web, e após tiver selecionado Contas organizacionais do menu Alterar a autenticação, você já tem a lógica necessária no seu aplicativo.

Se você configurou a autenticação manualmente, siga as instruções abaixo para saber como configurar sua API Web para atualizar as informações de chave automaticamente.

O snippet de código a seguir demonstra como obter as chaves mais recentes do documento de metadados de federação e, a seguir, usar o Manipulador de Tokens JWT para validar o token. O snippet de código pressupõe que você usará seu próprio mecanismo de armazenamento em cache para persistir a chave e validar futuros tokens da plataforma de identidade da Microsoft, seja em um banco de dados, em um arquivo de configuração ou em outro lugar.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IdentityModel.Tokens;
using System.Configuration;
using System.Security.Cryptography.X509Certificates;
using System.Xml;
using System.IdentityModel.Metadata;
using System.ServiceModel.Security;
using System.Threading;

namespace JWTValidation
{
    public class JWTValidator
    {
        private string MetadataAddress = "[Your Federation Metadata document address goes here]";

        // Validates the JWT Token that's part of the Authorization header in an HTTP request.
        public void ValidateJwtToken(string token)
        {
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler()
            {
                // Do not disable for production code
                CertificateValidator = X509CertificateValidator.None
            };

            TokenValidationParameters validationParams = new TokenValidationParameters()
            {
                AllowedAudience = "[Your App ID URI goes here]",
                ValidIssuer = "[The issuer for the token goes here, such as https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/]",
                SigningTokens = GetSigningCertificates(MetadataAddress)

                // Cache the signing tokens by your desired mechanism
            };

            Thread.CurrentPrincipal = tokenHandler.ValidateToken(token, validationParams);
        }

        // Returns a list of certificates from the specified metadata document.
        public List<X509SecurityToken> GetSigningCertificates(string metadataAddress)
        {
            List<X509SecurityToken> tokens = new List<X509SecurityToken>();

            if (metadataAddress == null)
            {
                throw new ArgumentNullException(metadataAddress);
            }

            using (XmlReader metadataReader = XmlReader.Create(metadataAddress))
            {
                MetadataSerializer serializer = new MetadataSerializer()
                {
                    // Do not disable for production code
                    CertificateValidationMode = X509CertificateValidationMode.None
                };

                EntityDescriptor metadata = serializer.ReadMetadata(metadataReader) as EntityDescriptor;

                if (metadata != null)
                {
                    SecurityTokenServiceDescriptor stsd = metadata.RoleDescriptors.OfType<SecurityTokenServiceDescriptor>().First();

                    if (stsd != null)
                    {
                        IEnumerable<X509RawDataKeyIdentifierClause> x509DataClauses = stsd.Keys.Where(key => key.KeyInfo != null && (key.Use == KeyType.Signing || key.Use == KeyType.Unspecified)).
                                                             Select(key => key.KeyInfo.OfType<X509RawDataKeyIdentifierClause>().First());

                        tokens.AddRange(x509DataClauses.Select(token => new X509SecurityToken(new X509Certificate2(token.GetX509RawData()))));
                    }
                    else
                    {
                        throw new InvalidOperationException("There is no RoleDescriptor of type SecurityTokenServiceType in the metadata");
                    }
                }
                else
                {
                    throw new Exception("Invalid Federation Metadata document");
                }
            }
            return tokens;
        }
    }
}

Aplicativos Web que protegem recursos e que foram criados com o Visual Studio 2012

Se seu aplicativo foi criado no Visual Studio 2012, você provavelmente usou a Ferramenta de Identidade e Acesso para configurar seu aplicativo. Também é provável que você esteja usando o VINR (registro de nome de emissor validador). O VINR é responsável por manter informações sobre os provedores de identidade confiável (plataforma de identidade da Microsoft) e as chaves usadas para validar tokens emitidos por eles. O VINR também facilita a atualização automática das informações fundamentais armazenadas em um arquivo Web.config baixando o documento de metadados federados mais recente associado ao seu diretório, verificando se a configuração está desatualizada em relação ao documento mais recente e atualizando o aplicativo para usar a nova chave conforme necessário.

Se você criou seu aplicativo usando um dos exemplos de código ou documentação passo a passo fornecidos pela Microsoft, a lógica de substituição de chave já estará incluída no seu projeto. Você notará que o código a seguir já existe em seu projeto. Se seu aplicativo não tiver essa lógica, siga as etapas abaixo para adicioná-la e verificar se ela está funcionando corretamente.

  1. No Gerenciador de soluções, adicione uma referência para o assembly System.IdentityModel para o projeto correto.
  2. Abra o arquivo Global.asax.cs e adicione o seguinte usando diretivas:
    using System.Configuration;
    using System.IdentityModel.Tokens;
    
  3. Adicione o seguinte método ao arquivo Global.asax.cs :
    protected void RefreshValidationSettings()
    {
     string configPath = AppDomain.CurrentDomain.BaseDirectory + "\\" + "Web.config";
     string metadataAddress =
                   ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
     ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath);
    }
    
  4. Invoque o método RefreshValidationSettings() no método Application_Start() em Global.asax.cs conforme mostrado abaixo:
    protected void Application_Start()
    {
     AreaRegistration.RegisterAllAreas();
     ...
     RefreshValidationSettings();
    }
    

Depois que você tiver seguido as etapas, o Web.config do seu aplicativo será atualizado com as últimas informações do documento de metadados federados, incluindo as últimas chaves. Essa atualização ocorrerá sempre que o pool de aplicativos for reciclado no IIS. Por padrão, o IIS é definido para reciclar aplicativos a cada 29 horas.

Siga as etapas abaixo para verificar se a lógica de substituição de chave está funcionando.

  1. Após ter verificado que seu aplicativo está usando o código acima, abra o arquivo Web.config e navegue até o bloco <issuerNameRegistry> procurando especificamente as poucas linhas abaixo:
    <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
         <authority name="https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/">
           <keys>
             <add thumbprint="3A38FA984E8560F19AADC9F86FE9594BB6AD049B" />
           </keys>
    
  2. Na configuração <adicionar impressão digital = "">, altere o valor de impressão digital, substituindo um caractere por um diferente. Salvar o arquivo Web.config.
  3. Crie o aplicativo e o execute. Se você consegue completar o processo de logon, seu aplicativo está atualizando a chave com êxito baixando as informações necessárias do documento de metadados federados do diretório. Se você estiver tendo problemas ao entrar, verifique se as alterações em seu aplicativo estão corretas lendo o artigo Como adicionando logon ao seu aplicativo Web usando a plataforma de identidade da Microsoft ou baixando e inspecionando o seguinte exemplo de código: Aplicativo de nuvem multilocatário do Microsoft Entra ID.

Aplicativos/APIs Web que protegem recursos usando quaisquer outras bibliotecas ou implementando manualmente qualquer um dos protocolos com suporte

Se você estiver usando alguma outra biblioteca ou se tiver implementado manualmente qualquer um dos protocolos com suporte, precisará examinar a biblioteca ou a implementação para garantir que a chave esteja sendo recuperada do documento de descoberta OpenID Connect ou do documento de metadados de federação. Uma maneira de verificar isso é fazer uma pesquisa no seu código ou no código da biblioteca de quaisquer chamadas para o documento de descoberta OpenID ou para o documento de metadados de federação.

Se a chave estiver armazenada em algum lugar ou embutida em código no aplicativo, você poderá recuperá-la e atualizá-la manualmente executando uma substituição manual de acordo com as instruções ao final deste documento de diretrizes. É altamente incentivado que você aprimore seu aplicativo para dar suporte à substituição automática usando qualquer um dos tópicos de abordagens neste artigo para evitar transtornos futuros e sobrecarga caso a plataforma de identidade da Microsoft aumente a cadência de sua substituição ou tenha uma substituição fora de banda de emergência.

Como testar o aplicativo para determinar se ele será afetado

Você pode validar se o aplicativo dá suporte à substituição automática de chave usando os scripts do PowerShell a seguir.

Para verificar e atualizar as chaves de assinatura com o PowerShell, será necessário obter o módulo do PowerShell MSIdentityTools.

  1. Instale o módulo do PowerShell MSIdentityTools:

    Install-Module -Name MSIdentityTools
    
  2. Entre usando o comando Connect-MgGraph com uma conta do administrador para consentir os escopos necessários:

     Connect-MgGraph -Scope "Application.ReadWrite.All"
    
  3. Obtenha a lista de impressões digitais de chave de assinatura disponíveis:

    Get-MsIdSigningKeyThumbprint
    
  4. Escolha uma das impressões digitais de chave e configure o Microsoft Entra ID para usar essa chave com o seu aplicativo (obtenha a ID do aplicativo no centro de administração do Microsoft Entra):

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -KeyThumbprint <Thumbprint>
    
  5. Teste o aplicativo Web ao entrar para obter um novo token. A alteração de atualização de chave é instantânea, mas use uma nova sessão do navegador (como o "InPrivate" do Internet Explorer, o modo "Incógnito" do Chrome ou o modo "Privado" do Firefox) para verificar se você emitiu um novo token.

  6. Para cada uma das impressões digitais de chave de assinatura retornadas, execute o cmdlet Update-MsIdApplicationSigningKeyThumbprint e teste o processo de entrada do aplicativo Web.

  7. Se o aplicativo Web entrar corretamente, ele será compatível com a substituição automática. Se não, modifique o aplicativo para dar suporte à substituição manual. Confira Estabelecer um processo manual de substituição para obter mais informações.

  8. Execute o seguinte script para reverter ao comportamento normal:

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -Default
    

Como executar uma substituição manual se seu aplicativo não oferecer suporte à substituição automática

Se o aplicativo não der suporte à substituição automática, será necessário estabelecer um processo que monitore periodicamente as chaves de assinatura da plataforma de identidade da Microsoft e execute uma substituição manual adequada.

Para verificar e atualizar as chaves de assinatura com o PowerShell, será necessário obter o módulo do PowerShell MSIdentityTools.

  1. Instale o módulo do PowerShell MSIdentityTools:

    Install-Module -Name MSIdentityTools
    
  2. Obtenha a chave de assinatura mais recente (obtenha a ID do locatário no centro de administração do Microsoft Entra):

    Get-MsIdSigningKeyThumbprint -Tenant <tenandId> -Latest
    
  3. Compare essa chave com a chave configurada para ser usada pelo aplicativo ou embutida no código dele.

  4. Se a chave mais recente for diferente da chave que o aplicativo está usando, baixe a chave de assinatura mais recente:

    Get-MsIdSigningKeyThumbprint -Latest -DownloadPath <DownloadFolderPath>
    
  5. Atualize o código ou a configuração do aplicativo para usar a nova chave.

  6. Configure o Microsoft Entra ID para usar essa chave mais recente com o seu aplicativo (obtenha a ID do aplicativo no centro de administração do Microsoft Entra):

    Get-MsIdSigningKeyThumbprint -Latest | Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId>
    
  7. Teste o aplicativo Web ao entrar para obter um novo token. A alteração de atualização de chave é instantânea, mas use uma nova sessão do navegador (como o "InPrivate" do Internet Explorer, o modo "Incógnito" do Chrome ou o modo "Privado" do Firefox) para verificar se você emitiu um novo token.

  8. Se você tiver problemas, reverta para a chave anterior que estava usando e entre em contato com o suporte do Azure:

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -KeyThumbprint <PreviousKeyThumbprint>
    
  9. Depois de atualizar o aplicativo para dar suporte à substituição manual, reverta-o para o comportamento normal:

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -Default