Share via


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

Este artigo discute o que você precisa saber sobre as chaves públicas que são usadas pela plataforma de identidade da Microsoft para assinar tokens de segurança. É importante notar que essas chaves rolam periodicamente e, em caso de emergência, podem ser roladas imediatamente. Todos os aplicativos que usam a plataforma de identidade da Microsoft devem ser capazes de manipular programaticamente o processo de substituição de chave. Você entenderá como as chaves funcionam, como avaliar o impacto da substituição para seu aplicativo e como atualizar seu aplicativo ou estabelecer um processo de substituição manual periódica para lidar com a substituiçã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 baseada em padrões do setor para estabelecer confiança entre ela e os aplicativos que a usam. 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úblicas e privadas. 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 ao aplicativo. Para verificar se o token é válido e originado da plataforma de identidade da Microsoft, o aplicativo deve validar a assinatura do token usando as chaves públicas expostas pela plataforma de identidade da Microsoft contidas no documento de descoberta OpenID Connect do locatário ou no documento de metadados de federação SAML/WS-Fed.

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

Há sempre mais de uma chave válida disponível no documento de descoberta do OpenID Connect e no documento de metadados de federação. Seu aplicativo deve estar preparado para usar todas e quaisquer chaves especificadas no documento, já que uma chave pode ser rolada em breve, outra pode ser sua substituição, 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 suportamos novas plataformas, novas nuvens ou novos protocolos de autenticação. Nem a ordem das chaves na resposta JSON nem a ordem em que foram expostas devem ser consideradas significativas para seu aplicativo.

Os aplicativos que suportam 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 para garantir que estejam sempre usando chaves de assinatura atualizadas, entre outras práticas recomendadas.

Como avaliar se o seu pedido será afetado e o que fazer a esse respeito

Como seu aplicativo lida com a substituição de chaves depende de variáveis como o tipo de aplicativo ou qual protocolo de identidade e biblioteca foram usados. As seções abaixo avaliam se os tipos mais comuns de aplicativos são afetados pela substituição de chave e fornecem orientação sobre como atualizar o aplicativo para dar suporte à substituição automática ou atualizar manualmente a chave.

As presentes orientações não se aplicam a:

  • Os aplicativos adicionados da Galeria de Aplicativos do Microsoft Entra (incluindo o Personalizado) têm orientações separadas sobre chaves de assinatura. Mais informações.
  • Os aplicativos locais publicados por meio de proxy de aplicativo não precisam se preocupar com chaves de assinatura.

Aplicativos cliente nativos acessando recursos

Os aplicativos que estão acessando apenas recursos (por exemplo, Microsoft Graph, KeyVault, API do Outlook e outras APIs da Microsoft) obtêm apenas um token e o transmitem ao proprietário do recurso. Como eles não estão protegendo nenhum recurso, eles não inspecionam o token e, portanto, não precisam garantir que ele esteja devidamente assinado.

Os aplicativos cliente nativos, seja desktop ou móvel, se enquadram nessa categoria e, portanto, não são afetados pela sobreposição.

Aplicações Web / APIs que acedem a recursos

Os aplicativos que estão acessando apenas recursos (como Microsoft Graph, KeyVault, API do Outlook e outras APIs da Microsoft) obtêm apenas um token e o passam para o proprietário do recurso. Como eles não estão protegendo nenhum recurso, eles não inspecionam o token e, portanto, não precisam garantir que ele esteja devidamente assinado.

Aplicativos Web e APIs da Web que estão usando o fluxo somente de aplicativo (credenciais de cliente/certificado de cliente) para solicitar tokens se enquadram nessa categoria e, portanto, não são afetados pela sobreposição.

Aplicativos Web/APIs que protegem recursos e são criados 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 lidar com a substituição de chaves automaticamente.

Aplicativos Web / APIs protegendo recursos usando ASP.NET middleware OWIN OpenID Connect, WS-Fed ou WindowsAzureActiveDirectoryBearerAuthentication

Se seu aplicativo estiver usando o middleware ASP.NET OWIN OpenID Connect, WS-Fed ou WindowsAzureActiveDirectoryBearerAuthentication, ele já tem a lógica necessária para lidar com a substituição de chaves automaticamente.

Você pode confirmar que seu aplicativo está usando qualquer um desses arquivos procurando por qualquer um dos seguintes trechos nos arquivos Startup.cs ou Startup.Auth.cs do aplicativo.

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

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

Se o seu aplicativo estiver usando o middleware ASP.NET OWIN OpenID Connect ou JwtBearerAuthentication, ele já tem a lógica necessária para lidar com a substituição de chaves automaticamente.

Você pode confirmar que seu aplicativo está usando qualquer um desses itens procurando por qualquer um dos seguintes trechos no Startup.cs ou Startup.Auth.cs do seu aplicativo

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

Aplicações Web / APIs que protegem recursos utilizando Node.js passport-azure-ad módulo

Se o seu aplicativo estiver usando o módulo Node.js passport-ad, ele já tem a lógica necessária para lidar com a substituição de chaves automaticamente.

Você pode confirmar que seu anúncio de passaporte de aplicativo pesquisando o seguinte trecho no app.js do seu aplicativo

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

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

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

Se seu aplicativo foi criado usando um modelo de aplicativo Web no Visual Studio 2015 ou posterior e você selecionou Contas Corporativas ou Escolares no menu Alterar Autenticação , ele já tem a lógica necessária para lidar com a substituição de chaves automaticamente. Essa lógica, incorporada no middleware OWIN OpenID Connect, recupera e armazena em cache as chaves do documento de descoberta do OpenID Connect e as atualiza periodicamente.

Se você adicionou a autenticação à sua solução manualmente, seu aplicativo pode não ter a lógica de substituição de chave necessária. Você pode escrevê-lo você mesmo, ou seguir as etapas em aplicativos Web / APIs usando quaisquer outras bibliotecas ou implementando manualmente qualquer um dos protocolos suportados.

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

Se seu aplicativo foi 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 lidar com a substituição de chave automaticamente. Essa lógica armazena o identificador exclusivo da sua organização e as informações da chave de assinatura 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ê adicionou a autenticação à sua solução manualmente, seu aplicativo pode não ter a lógica de substituição de chave necessária. Você precisará escrevê-lo você mesmo, ou siga as etapas em aplicativos Web / APIs usando quaisquer outras bibliotecas ou implementando manualmente qualquer um dos protocolos suportados..

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

  1. No Visual Studio 2013, abra a solução e selecione na 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 nela e selecione Mostrar Dados da Tabela.
  3. Na tabela IssuingAuthorityKeys, haverá pelo menos uma linha, que corresponde ao valor de impressão digital da chave. Exclua todas as linhas da tabela.
  4. Clique com o botão direito do rato na tabela Inquilinos e, em seguida, selecione Mostrar Dados da Tabela.
  5. Na tabela Locatários, haverá pelo menos uma linha, que corresponde a um identificador de locatário de diretório exclusivo. Exclua todas as linhas da tabela. Se você não excluir as linhas na tabela Locatários e na tabela IssuingAuthorityKeys, receberá um erro no tempo de execução.
  6. Compile e execute a aplicação. Depois de iniciar sessão na sua conta, pode parar a aplicação.
  7. Retorne ao Gerenciador de Servidores e examine os valores na tabela IssuingAuthorityKeys e Tenants . Você notará que eles foram preenchidos automaticamente com as informações apropriadas do documento de metadados de federação.

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

Se você criou um aplicativo de API Web no Visual Studio 2013 usando o modelo de API Web e, em seguida, selecionou Contas Organizacionais no menu Alterar Autenticação , você já tem a lógica necessária em seu aplicativo.

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

O trecho de código a seguir demonstra como obter as chaves mais recentes do documento de metadados de federação e, em seguida, usa o manipulador de token JWT para validar o token. O trecho de código pressupõe que você usará seu próprio mecanismo de cache para persistir a chave para validar tokens futuros da plataforma de identidade da Microsoft, seja em um banco de dados, 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 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 Validating Issuer Name Registry (VINR). O VINR é responsável por manter informações sobre provedores de identidade confiáveis (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 de chave armazenadas em um arquivo Web.config baixando o documento de metadados de federação mais recente associado ao seu diretório, verificando se a configuração está desatualizada com o documento mais recente e atualizando o aplicativo para usar a nova chave conforme necessário.

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

  1. No Gerenciador de Soluções, adicione uma referência ao assembly System.IdentityModel para o projeto apropriado.
  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:
    protected void Application_Start()
    {
     AreaRegistration.RegisterAllAreas();
     ...
     RefreshValidationSettings();
    }
    

Depois de seguir essas etapas, o Web.config do seu aplicativo será atualizado com as informações mais recentes do documento de metadados de federação, incluindo as chaves mais recentes. 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. Depois de verificar se seu aplicativo está usando o código acima, abra o arquivo Web.config e navegue até o< bloco issuerNameRegistry>, procurando especificamente as seguintes linhas:
    <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
         <authority name="https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/">
           <keys>
             <add thumbprint="AA11BB22CC33DD44EE55FF66AA77BB88CC99DD00" />
           </keys>
    
  2. <Na configuração add thumbprint="",> altere o valor da impressão digital substituindo qualquer caractere por um diferente. Salve o arquivo Web.config .
  3. Crie o aplicativo e execute-o. Se você puder concluir o processo de entrada, seu aplicativo estará atualizando a chave com êxito baixando as informações necessárias do documento de metadados de federação do diretório. Se você estiver tendo problemas para entrar, verifique se as alterações em seu aplicativo estão corretas lendo o artigo Adicionando logon ao seu aplicativo Web usando a plataforma de identidade da Microsoft ou baixando e inspecionando o seguinte exemplo de código: Multi-Tenant Cloud Application for Microsoft Entra ID.

Aplicativos Web / APIs protegendo recursos usando quaisquer outras bibliotecas ou implementando manualmente qualquer um dos protocolos suportados

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

Se a chave estiver sendo armazenada em algum lugar ou codificada em seu aplicativo, você poderá recuperá-la manualmente e atualizá-la de acordo, executando uma substituição manual de acordo com as instruções no final deste documento de orientação. É altamente recomendável que você aprimore seu aplicativo para oferecer suporte à substituição automática usando qualquer uma das abordagens descritas neste artigo para evitar interrupções e sobrecarga futuras se a plataforma de identidade da Microsoft aumentar sua cadência de substituição ou tiver uma substituição fora de banda de emergência.

Como testar seu aplicativo para determinar se ele será afetado

Você pode validar se seu aplicativo dá suporte à substituição automática de chaves usando os seguintes scripts do PowerShell.

Para verificar e atualizar chaves de assinatura com o PowerShell, você precisará do módulo PowerShell MSIdentityTools .

  1. Instale o módulo PowerShell MSIdentityTools:

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

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

    Get-MsIdSigningKeyThumbprint
    
  4. Escolha qualquer uma das impressões digitais da chave e configure a ID do Microsoft Entra para usar essa chave com 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 entrando para obter um novo token. A alteração da atualização de chave é instantânea, mas certifique-se de que utiliza uma nova sessão do navegador (utilizando, por exemplo, o modo "InPrivate" do Internet Explorer, o modo "Anônimo" do Chrome ou o modo "Privado" do Firefox) para garantir que recebe um novo token.

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

  7. Se o aplicativo Web fizer login corretamente, ele suportará a substituição automática. Caso contrário, modifique seu aplicativo para oferecer suporte à substituição manual. Consulte Estabelecendo um processo de substituição manual para obter mais informações.

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

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -Default
    

Como executar uma substituição manual se o seu aplicativo não suportar a substituição automática

Se seu aplicativo não oferecer suporte à substituição automática, você precisará estabelecer um processo que monitore periodicamente as chaves de assinatura da plataforma de identidade da Microsoft e execute uma substituição manual de acordo.

Para verificar e atualizar chaves de assinatura com o PowerShell, você precisará do MSIdentityTools módulo PowerShell.

  1. Instale o MSIdentityTools módulo PowerShell:

    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 que seu aplicativo está atualmente codificado ou configurado para usar.

  4. Se a chave mais recente for diferente da chave que seu 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 a ID do Microsoft Entra para usar essa chave mais recente com 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 entrando para obter um novo token. A alteração da atualização de chave é instantânea, mas certifique-se de que utiliza uma nova sessão do navegador (utilizando, por exemplo, o modo "InPrivate" do Internet Explorer, o modo "Anônimo" do Chrome ou o modo "Privado" do Firefox) para garantir que recebe um novo token.

  8. Se tiver algum problema, reverta para a chave anterior que estava a utilizar e contacte o suporte do Azure:

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

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -Default