Generate proof of possession tokens for rolling keys
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. The proof is represented by a self-signed JWT token. This JWT token must be signed using the private key of one of the application's existing valid certificates. 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), can't use this service action. You can use the Update application operation to perform an update instead.
The token should contain the following claims:
aud
- Audience needs to be00000003-0000-0000-c000-000000000000
which is the appId of the Microsoft Graph service principal.iss
- Issuer needs to be the object ID of the application that's making the call (not the appId).nbf
- Not before time.exp
- Expiration time should be "nbf" + 10 mins.
You can use the following code examples 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 = $"00000003-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);
}
}
}
You can also generate the proof using signature in Azure KeyVault. It is important to note that padding character '=' must not be included in the JWT header and payload or an Authentication_MissingOrMalformed error will be returned.
Next steps
Now that you have your proof of possession token, you can use it to:
- Add a key or remove a key from your application.
- Add a key or remove a key from your service principal.
Feedback
Submit and view feedback for