Generating proof of possession tokens

I am trying to use the addKey method to add a certificate to an App Registration via Graph API. This requires you to generate a proof of ownership of an existing certificate that’s present in the App Registration by creating a JWT token signed with that cert. The token should contain the following claims:

  • aud – Audience needs to be 00000002-0000-0000-c000-000000000000.
  • iss – Issuer needs to be the Azure AD ObjectId of the application that is making the call (not the applicationId or clientId).
  • nbf – Not before time.
  • exp – Expiration time should be “nbf” + 10 mins.

And there’s some sample code to generate this at this document. The code, however is in C#, but I want to generate the proof as part of my PowerShell code so that’s not entirely helpful.

Here’s the code from the document btw in case it changes/ goes down:

Turns out there’s a PowerShell module someone’s helpfully created that can create JWT tokens. Using it is straight-forward too:

The end-result is a token like the following:

Which has the following claims correctly set (I can view this using a site such as https://jwt.ms/):

Great!

However, I wanted to see if I could use the official C# version itself in PowerShell. I know you can use a lot of C# in PowerShell as the latter is based on .NET. I use PowerShell Core on macOS mainly, so hopefully all the .NET classes above were present in .NET Core too (which is what PowerShell Core is based on). Luckily they are!

The three classes I need are System.Security.Cryptography.X509Certificates, Microsoft.IdentityModel.Tokens, and Microsoft.IdentityModel.JsonWebTokens. And turns out I can just create new objects in PowerShell based on these classes and do the same as the C# code.

Here’s what I came up with through a fair bit of trial and error yesterday:

I had to Google a bit on creating the IDictionary object as everything pointed me towards using a hash table instead, but that didn’t do the trick.

Also when it came to certificates initially I was doing something along these lines:

But that gave the above error until I realized rather than create the object and then instantiate it with an import() I should just create the object with the certificate. Thanks to this blog post for pointing me to that.

The above PowerShell code successfully generates a JWT token and it looks similar to the one generated by New-JWT so I guess I am doing things alright.

If anything it also includes the thumbprint of the certificate used to sign the token (the kid parameter) so that’s better I guess.