Substitution de clé de signature dans la plateforme d’identités Microsoft

Cet article explique ce que vous devez savoir sur les clés publiques utilisées par la plateforme d’identités Microsoft pour la signature des jetons de sécurité. Il est important de noter que ces clés sont substituées régulièrement, voire immédiatement en cas d’urgence. Toutes les applications qui utilisent la plateforme d’identités Microsoft doivent être en mesure de gérer par programme le processus de substitution de clé. Vous allez comprendre le fonctionnement des clés, comment évaluer l’impact de la substitution pour votre application, et comment mettre à jour votre application ou établir si nécessaire un processus périodique de substitution manuelle des clés pour gérer la substitution de clé.

Vue d’ensemble des clés de signature dans la plateforme d’identités Microsoft

La plateforme d’identités Microsoft utilise une technique de chiffrement de clés publiques conforme aux normes du secteur pour établir une relation de confiance avec les applications qui l’utilisent. En pratique, cela fonctionne de la façon suivante : La plateforme d’identités Microsoft utilise une clé de signature se composant d’une paire clé publique-clé privée. Quand un utilisateur se connecte à une application qui utilise la plateforme d’identités Microsoft pour l’authentification, la plateforme crée un jeton de sécurité qui contient des informations sur l’utilisateur. Ce jeton est signé par la plateforme d’identités Microsoft à l’aide de sa clé privée avant d’être renvoyé à l’application. Pour vérifier que le jeton est valide et provient bien de la plateforme d’identités Microsoft, l’application doit valider la signature du jeton à l’aide de la clé publique exposée par la plateforme d’identités Microsoft contenue dans le document de métadonnées de fédération SAML/WS-Fed ou le document de découverte OpenID Connect du locataire.

Pour des raisons de sécurité, les clés de signature de la plateforme d’identités Microsoft sont substituées régulièrement, voire immédiatement en cas d’urgence. Aucun intervalle de temps n’est défini ou garanti entre ces substitutions de clé. Toute application s’intégrant avec la plateforme d’identités Microsoft doit être préparée à gérer un événement de substitution de clé, quelle que soit la fréquence à laquelle il se produit. Si votre application ne gère pas les actualisations soudaines et tente d’utiliser une clé expirée pour vérifier la signature d’un jeton, votre application rejette incorrectement le jeton. La vérification de l’existence de mises à jour toutes les 24 heures constitue une meilleure pratique, assortie d’une limitation (au plus une fois toutes les cinq minutes) des actualisations immédiates du document de clés si un jeton ne se valide pas avec les clés dans le cache de votre application.

Plusieurs clés valides sont disponibles à tout moment dans le document de découverte OpenID Connect et dans le document de métadonnées de fédération. Votre application doit être préparée à utiliser n’importe quelle et toutes les clés spécifiées dans le document, car une clé peut être substituée rapidement, une autre la remplacer, et ainsi de suite. Le nombre de clés présentes peut changer au fil du temps, en fonction de l’architecture interne de la plateforme d’identités Microsoft, à mesure que nous prenons en charge de nouvelles plateformes, de nouveaux clouds ou de nouveaux protocoles d’authentification. Ni l’ordre des clés dans la réponse JSON, ni l’ordre dans lequel elles ont été exposées ne doivent être considérés comme significatifs pour votre application.

Les applications qui ne prennent en charge qu’une seule clé de signature, ou celles qui requièrent des mises à jour manuelles des clés de signature, sont fondamentalement moins sécurisées et fiables. Elles nécessitent une mise à jour pour utiliser des bibliothèques standard afin de s’assurer qu’elles utilisent toujours des clés de signature à jour, entre autres meilleures pratiques.

Comment évaluer si votre application sera affectée et que faire si cela se produit

La manière dont votre application gère la substitution de la clé dépend de variables comme le type d’application ou le protocole d’identité et la bibliothèque utilisés. Les sections ci-dessous évaluent si les types d’application les plus courants sont affectés par la substitution de clé et fournissent des conseils sur la mise à jour de l’application pour prendre en charge la substitution automatique ou mettre la clé à jour manuellement.

Ce guide n’est pas applicable aux :

  • Une aide distincte sur les clés de signature est disponible pour les applications ajoutées depuis la galerie d’applications Microsoft Entra (y compris les applications personnalisées). Informations complémentaires.
  • Applications locales publiées via le proxy d’application, qui ne sont pas concernées par les clés de signature.

Applications clientes natives ayant accès aux ressources

Les applications qui ont uniquement accès aux ressources (par exemple, Microsoft Graph, KeyVault, l’API Outlook et d’autres API Microsoft) obtiennent uniquement un jeton et le transmettent au propriétaire de la ressource. Étant donné qu’elles ne protègent pas les ressources, elles n’inspectent pas le jeton et n’ont donc pas besoin de s’assurer qu’il est correctement signé.

Les applications clientes natives, de bureau ou mobiles, appartiennent à cette catégorie et ne sont donc pas affectées par la substitution.

Applications web/API ayant accès aux ressources

Les applications qui ont uniquement accès aux ressources (par exemple, Microsoft Graph, KeyVault, l’API Outlook et d’autres API Microsoft) obtiennent uniquement un jeton et le transmettent au propriétaire de la ressource. Étant donné qu’elles ne protègent pas les ressources, elles n’inspectent pas le jeton et n’ont donc pas besoin de s’assurer qu’il est correctement signé.

Les applications et API web qui utilisent le flux d’application uniquement (informations d’identification du client/certificat client) pour demander des jetons, appartiennent à cette catégorie et ne sont donc pas affectées par la substitution.

Applications web/API protégeant les ressources et créées à l’aide d’Azure App Services

La fonctionnalité d’authentification/d’autorisation d’Azure App Services (EasyAuth) possède déjà la logique nécessaire pour gérer automatiquement la substitution de clé.

Applications web/API protégeant les ressources en utilisant l’intergiciel ASP.NET OWIN OpenID Connect, WS-Fed ou WindowsAzureActiveDirectoryBearerAuthentication

Si votre application utilise l'intergiciel ASP.NET OWIN OpenID Connect, WS-Fed ou WindowsAzureActiveDirectoryBearerAuthentication, elle dispose déjà de la logique nécessaire pour gérer automatiquement le renouvellement des clés.

Vous pouvez vérifier que votre application utilise l’un de ces middlewares en recherchant les extraits de code suivants dans les fichiers Startup.cs ou Startup.Auth.cs de l’application.

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

Applications web/API protégeant les ressources à l’aide du middleware .NET Core OpenID Connect ou JwtBearerAuthentication

Si votre application utilise l'intergiciel ASP.NET OWIN OpenID Connect ou JwtBearerAuthentication, elle dispose déjà de la logique nécessaire pour gérer automatiquement le renouvellement des clés.

Vous pouvez vérifier que votre application utilise l’un de ces middlewares en recherchant les extraits de code suivants dans le fichier Startup.cs ou Startup.Auth.cs de l’application.

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

Applications Web/API protégeant les ressources à l’aide du module passport-azure-ad Node.js

Si votre application utilise le module passport-ad Node.js, elle possède déjà la logique nécessaire pour gérer automatiquement la substitution de clé.

Vous pouvez vérifier que votre application utilise passport-ad en recherchant l’extrait de code suivant dans le fichier app.js de l’application.

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

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

Applications web/API protégeant les ressources et créées avec Visual Studio 2015 ou une version ultérieure

Si votre application a été générée à l’aide d’un modèle d’application web dans Visual Studio 2015 ou une version ultérieure, et si vous avez sélectionné Comptes professionnels ou scolaires dans le menu Modifier l’authentification, elle possède déjà la logique nécessaire pour gérer automatiquement la substitution de clé. Cette logique, incorporée dans l’intergiciel OWIN OpenID Connect, récupère et met en cache les clés du document de découverte OpenID Connect, et les actualise régulièrement.

Si vous avez ajouté manuellement l’authentification à votre solution, votre application ne possède peut-être pas la logique de substitution de clé nécessaire. Vous pouvez l’écrire vous-même ou suivre les étapes décrites dans Applications web / API protégeant les ressources en utilisant d’autres bibliothèques ou implémentant manuellement un des protocoles pris en charge.

Applications web protégeant les ressources et créées avec Visual Studio 2013

Si votre application a été générée à l’aide d’un modèle d’application web dans Visual Studio 2013 et que vous avez sélectionné Comptes professionnels dans le menu Modifier l’authentification, elle possède déjà la logique nécessaire pour gérer automatiquement la substitution de clé. Cette logique stocke l’identifiant unique de votre organisation et les informations de clé de signature dans deux tables de base de données associées au projet. Vous trouverez la chaîne de connexion de la base de données dans le fichier Web.config du projet.

Si vous avez ajouté manuellement l’authentification à votre solution, votre application ne possède peut-être pas la logique de substitution de clé nécessaire. Vous devrez l’écrire vous-même ou suivre les étapes décrites dans Applications web/API protégeant les ressources avec d’autres bibliothèques ou implémentant manuellement l’un des protocoles pris en charge..

Les étapes suivantes vous aident à vérifier le bon fonctionnement de la logique de votre application.

  1. Dans Visual Studio 2013, ouvrez la solution, puis sélectionnez l’onglet Explorateur de serveurs dans la fenêtre de droite.
  2. Développez Connexions de données, DefaultConnection, puis Tables. Recherchez la table IssuingAuthorityKeys, cliquez dessus avec le bouton droit, puis sélectionnez Afficher les données de la table.
  3. La table IssuingAuthorityKeys comporte au moins une ligne correspondant à la valeur de l’empreinte de la clé. Supprimez toutes les lignes de la table.
  4. Cliquez avec le bouton droit sur la table Locataires, puis sélectionnez Afficher les données de la table.
  5. La table Clients comporte au moins une ligne correspondant à un identifiant unique du client de répertoire. Supprimez toutes les lignes de la table. Si vous ne supprimez pas les lignes à la fois dans la table Locataires et dans la table IssuingAuthorityKeys, vous recevrez une erreur au moment de l’exécution.
  6. Générez et exécutez l’application. Une fois connecté à votre compte, vous pouvez arrêter l’application.
  7. Revenez à l’Explorateur de serveurs et examinez les valeurs contenues dans les tables IssuingAuthorityKeys et Clients. Vous remarquerez qu’elles ont été automatiquement complétées avec les informations appropriées extraites du document de métadonnées de fédération.

API web protégeant les ressources et créées avec Visual Studio 2013

Si vous avez créé une application API web dans Visual Studio 2013 à l’aide du modèle API web et que vous avez sélectionné Comptes professionnels dans le menu Modifier l’authentification, votre application contient déjà la logique nécessaire.

Si vous avez configuré l’authentification manuellement, suivez les instructions ci-dessous pour savoir comment configurer votre API web afin de mettre automatiquement à jour ses informations de clé.

L’extrait de code suivant montre comment obtenir les clés les plus récentes auprès du document de métadonnées de fédération, puis comment utiliser le Gestionnaire de jetons JWT pour valider le jeton. Cet extrait de code suppose que vous allez utiliser votre propre mécanisme de mise en cache pour conserver la clé afin de valider les jetons futurs de la plateforme d’identité Microsoft, que ce soit dans une base de données, un fichier de configuration ou ailleurs.

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

Applications web protégeant les ressources et créées avec Visual Studio 2012

Si votre application a été créée dans Visual Studio 2012, vous avez probablement utilisé l’outil Identité et accès pour configurer votre application. Il est également probable que vous utilisiez le registre de validation de nom d’émetteur (VINR). Le VINR est chargé de conserver les informations relatives aux fournisseurs d’identité approuvés (plateforme d’identités Microsoft) et les clés utilisées pour valider les jetons qu’ils émettent. Le VINR permet également de mettre à jour automatiquement les informations de clé stockées dans un fichier Web.config en téléchargeant le dernier document de métadonnées de fédération associé à votre annuaire, en vérifiant si la configuration est à jour avec le dernier document et en mettant à jour l’application pour utiliser la nouvelle clé si nécessaire.

Si vous avez créé votre application à l’aide des exemples de code ou de la documentation détaillée fournis par Microsoft, la logique de substitution de clé est déjà incluse dans votre projet. Vous remarquerez que le code ci-dessous existe déjà dans votre projet. Si votre application ne contient pas déjà cette logique, suivez les étapes ci-dessous pour l’ajouter et vérifier qu’elle fonctionne correctement.

  1. Dans l’Explorateur de solutions, ajoutez une référence à l’assembly System.IdentityModel correspondant au projet approprié.
  2. Ouvrez le fichier Global.asax.cs et ajoutez le code suivant en utilisant les directives :
    using System.Configuration;
    using System.IdentityModel.Tokens;
    
  3. Ajoutez la méthode suivante au fichier Global.asax.cs :
    protected void RefreshValidationSettings()
    {
     string configPath = AppDomain.CurrentDomain.BaseDirectory + "\\" + "Web.config";
     string metadataAddress =
                   ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
     ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath);
    }
    
  4. Appelez la méthode RefreshValidationSettings() dans la méthode Application_Start() dans Global.asax.cs comme illustré ici :
    protected void Application_Start()
    {
     AreaRegistration.RegisterAllAreas();
     ...
     RefreshValidationSettings();
    }
    

Une fois ces étapes effectuées, le fichier Web.config de votre application sera mis à jour avec les dernières informations du document de métadonnées de fédération, y compris les clés les plus récentes. Cette mise à jour sera effectuée chaque fois que votre pool d’applications sera recyclé dans IIS. Par défaut, IIS est configuré pour recycler les applications toutes les 29 heures.

Suivez les étapes ci-dessous pour vérifier que la logique de substitution de clé fonctionne correctement.

  1. Vérifiez que votre application utilise bien le code ci-dessus, puis ouvrez le fichier Web.config et accédez au bloc <issuerNameRegistry>. Examinez plus attentivement les quelques lignes suivantes :
    <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. Dans le paramètre <add thumbprint="">, modifiez la valeur de l’empreinte en remplaçant l’un des caractères par un caractère différent. Enregistrez le fichier Web.config .
  3. Générez puis exécutez l’application. Si vous pouvez terminer le processus de connexion, votre application mettra correctement à jour la clé en téléchargeant les informations requises à partir du document de métadonnées de fédération de votre répertoire. Si vous rencontrez des problèmes de connexion, assurez-vous que les modifications apportées à votre application sont correctes en lisant l'article Ajout de la connexion à votre application Web à l'aide de la plateforme d'identités Microsoft, ou en téléchargeant et en inspectant l'exemple de code suivant : Application cloud multi-tenant pour Microsoft Entra IDENTIFIANT.

Applications web/API protégeant les ressources avec d’autres bibliothèques ou implémentant manuellement l’un des protocoles pris en charge

Si vous utilisez une autre bibliothèque ou si vous avez implémenté manuellement l’un des protocoles pris en charge, vous devez examiner la bibliothèque ou votre implémentation afin de vous assurer que la clé est récupérée à partir du document de découverte OpenID Connect ou du document de métadonnées de fédération. Pour le vérifier, vous pouvez rechercher dans votre code ou dans le code de la bibliothèque les appels vers le document de découverte OpenID ou le document de métadonnées de fédération.

Si la clé est stockée quelque part ou codée en dur dans votre application, vous pouvez récupérer la clé et la mettre à jour manuellement en suivant les instructions indiquées à la fin de ce document. Nous vous recommandons fortement d’améliorer votre application pour prendre en charge la substitution automatique en utilisant l’une des approches présentées dans cet article pour éviter les perturbations et les surcharges à l’avenir si la plateforme d’identités Microsoft augmente sa cadence de substitution ou doit effectuer une substitution hors bande en urgence.

Comment tester votre application pour savoir si elle sera affectée

Vous pouvez vérifier si votre application prend en charge le renouvellement automatique des clés en utilisant les scripts PowerShell suivants.

Pour vérifier et mettre à jour les clés de signature avec PowerShell, vous avez besoin du module PowerShell MSIdentityTools .

  1. Installez le module PowerShell MSIdentityTools :

    Install-Module -Name MSIdentityTools
    
  2. Connectez-vous à l’aide de la commande Connect-MgGraph avec un compte d’administrateur pour donner le consentement aux étendues requises :

     Connect-MgGraph -Scope "Application.ReadWrite.All"
    
  3. Obtenir la liste des empreintes numériques de clé de signature disponibles :

    Get-MsIdSigningKeyThumbprint
    
  4. Choisissez l’une des empreintes clés et configurez l’ID Microsoft Entra pour utiliser cette clé avec votre application (obtenez l’ID de l’application auprès du centre d’administration Microsoft Entra) :

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -KeyThumbprint <Thumbprint>
    
  5. Testez l’application web en vous connectant pour obtenir un nouveau jeton. La modification de la mise à jour de clé est instantanée, mais veillez à utiliser une nouvelle session de navigateur (à l’aide, par exemple, du mode « InPrivate » d’Internet Explorer, « Incognito » de Chrome ou « Privé » de Firefox) pour vous assurer que vous avez reçu un nouveau jeton.

  6. Pour chacune des empreintes de clé de signature retournées, exécutez la cmdlet Update-MsIdApplicationSigningKeyThumbprint et testez le processus de connexion de votre application web.

  7. Si l’application web vous connecte correctement, elle prend en charge la substitution automatique. Si ce n’est pas le cas, modifiez votre application pour qu’elle prenne en charge la substitution manuelle. Pour plus d’informations, consultez Établissement d’un processus de substitution manuel.

  8. Exécutez le script suivant pour rétablir le comportement normal :

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -Default
    

Comment effectuer une substitution manuelle si votre application ne prend pas en charge la substitution automatique

Si votre application ne prend pas en charge la substitution automatique, vous devez établir un processus permettant de superviser régulièrement les clés de signature de la plateforme d’identités Microsoft et d’effectuer une substitution manuelle en conséquence.

Pour vérifier et mettre à jour les clés de signature avec PowerShell, vous avez besoin du module PowerShell MSIdentityTools .

  1. Installer le module PowerShell MSIdentityTools :

    Install-Module -Name MSIdentityTools
    
  2. Obtenez la clé de signature la plus récente (obtenez l’ID de locataire à partir du centre d’administration Microsoft Entra) :

    Get-MsIdSigningKeyThumbprint -Tenant <tenandId> -Latest
    
  3. Comparez cette clé à la clé que votre application a actuellement codée en dur ou est configurée pour utiliser.

  4. Si la clé la plus récente est différente de la clé utilisée par votre application, téléchargez la dernière clé de signature :

    Get-MsIdSigningKeyThumbprint -Latest -DownloadPath <DownloadFolderPath>
    
  5. Mettez à jour le code ou la configuration de votre application pour utiliser la nouvelle clé.

  6. Configurez l'ID Microsoft Entra pour utiliser cette dernière clé avec votre application (obtenez l'ID de l'application auprès du centre d'administration Microsoft Entra) :

    Get-MsIdSigningKeyThumbprint -Latest | Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId>
    
  7. Testez l’application web en vous connectant pour obtenir un nouveau jeton. La modification de la mise à jour de clé est instantanée, mais veillez à utiliser une nouvelle session de navigateur (à l’aide, par exemple, du mode « InPrivate » d’Internet Explorer, « Incognito » de Chrome ou « Privé » de Firefox) pour vous assurer que vous avez reçu un nouveau jeton.

  8. Si vous rencontrez des problèmes, revenez à la clé précédente que vous utilisiez et contactez le support Azure :

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -KeyThumbprint <PreviousKeyThumbprint>
    
  9. Une fois que vous avez mis à jour votre application pour prendre en charge la substitution manuelle, rétablissez le comportement normal :

    Update-MsIdApplicationSigningKeyThumbprint -ApplicationId <ApplicationId> -Default