生成用于滚动密钥的所有权证明令牌Generating proof of possession tokens for rolling keys

可以使用在 applicationservicePrincipal 资源上定义的 addKeyremoveKey 方法,以编程方式滚动过期密钥。You can use the addKey and removeKey methods defined on the application and servicePrincipal resources to roll expiring keys programmatically.

作为对这些方法的请求验证的一部分,在调用这些方法之前,将对现有密钥的所有权证明进行验证。As part of the request validation for these methods, a proof of possession of an existing key is verified before the methods can be invoked. 该证明由自签名的 JWT 令牌表示。The proof is represented by a self-signed JWT token. 此 JWT 令牌必须使用应用程序现有有效证书之一的私钥进行签名。This JWT token must be signed using the private key of one of the application's existing valid certificates. 令牌有效期不应超过 10 分钟。The token lifespan should not exceed 10 minutes.

注意: 没有任何现有有效证书(尚未添加证书,或者所有证书均已过期)的应用程序将无法使用此服务操作。Note: Applications that don’t have any existing valid certificates (no certificates have been added yet, or all certificates have expired), won’t be able to use this service action. 可改用更新应用程序操作来执行更新。You can use the Update application operation to perform an update instead.

令牌应包含以下声明:The token should contain the following claims:

  • aud - 受众需要是 00000002-0000-0000-c000-000000000000aud - Audience needs to be 00000002-0000-0000-c000-000000000000.
  • iss - 颁发者需要是正在进行调用的应用程序的 Azure AD ObjectId(而非 applicationId 或 clientId)。iss - Issuer needs to be the Azure AD ObjectId of the application that is making the call (not the applicationId or clientId).
  • nbf -“不早于”时间。nbf - Not before time.
  • exp - 过期时间应该是“不早于”+ 10 分钟。exp - Expiration time should be "nbf" + 10 mins.

可使用以下代码示例来生成此所有权证明令牌。You can use the following code example to generate this proof of possession token.

using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.JsonWebTokens;

namespace MicrosoftIdentityPlatformProofTokenGenerator
{
    class Program
    {
        static void Main(string[] args)
        {
            // Configure the following
            string pfxFilePath = "<Path to your certificate file";
            string password = "<Certificate password>";
            string objectId = "<id of the application or servicePrincipal object>";

            // Get signing certificate
            X509Certificate2 signingCert = new X509Certificate2(pfxFilePath, password);

            // audience
            string aud = $"00000002-0000-0000-c000-000000000000";

            // aud and iss are the only required claims.
            var claims = new Dictionary<string, object>()
            {
                { "aud", aud },
                { "iss", objectId }
            };

            // token validity should not be more than 10 minutes
            var now = DateTime.UtcNow;
            var securityTokenDescriptor = new SecurityTokenDescriptor
            {
                Claims = claims,
                NotBefore = now,
                Expires = now.AddMinutes(10),
                SigningCredentials = new X509SigningCredentials(signingCert)
            };

            var handler = new JsonWebTokenHandler();
            var x = handler.CreateToken(securityTokenDescriptor);
            Console.WriteLine(x);
        }
    }
}