1

Note: Encryption is very new to me.

I'm trying to create a JWT for use in OAuth2 Protocol with client credentials flow and certificate as per these specifications. (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow).

When sending the request with JWT as client_assertion I receive the error:

{"error":"invalid_client","error_description":"AADSTS700027: Invalid JWT token. Unsupported key for the signing algorithm.\r\nTrace ID: XXXXX\r\nCorrelation ID: XXXXX\r\nTimestamp: 2021-12-22 15:40:56Z","error_codes":[700027],"timestamp":"2021-12-22 15:40:56Z","trace_id":"XXXXX","correlation_id":"XXXXX","error_uri":"https://login.microsoftonline.com/error?code=700027"}

I'm extracting the private key from ther certificate and using it as the key when signing via HS256. Is this correct? What key should I be using to sign the JWT when I have a certificate?

Note: I've tried using it with and without the '-----BEGIN PRIVATE KEY-----' and '-----END PRIVATE KEY-----' with no success.

Here is how I'm calling the hash signing function:

propsRawSignature = base64UrlEncode(propvRawHeader) & "." & base64UrlEncode(propvRawPayload)
vHashedData = base64SHA256Encode(propsRawSignature, propsCertKey)
resultingJWT = base64UrlEncode(propvRawHeader) + "." + base64UrlEncode(propvRawPayload) + "." + vHashedData

I'm using a hash function @HK1 was nice enough to share in this answer:

Private Function base64SHA256Encode(strValue, strSecret)
    'original https://stackoverflow.com/a/10068932/7303640
    'also seen here https://stackoverflow.com/a/36386633/7303640
    Dim asc As Object, enc As Object
    Dim TextToHash() As Byte
    Dim SharedSecretKey() As Byte
    Set asc = CreateObject("System.Text.UTF8Encoding")
    Set enc = CreateObject("System.Security.Cryptography.HMACSHA256")

    TextToHash = asc.Getbytes_4(strValue)
    SharedSecretKey = asc.Getbytes_4(strSecret)
    enc.key = SharedSecretKey
    'enc.key = strSecret
    
    Dim bytes() As Byte
    bytes = enc.ComputeHash_2((TextToHash))
    base64SHA256Encode = EncodeBase64(bytes)
    Set asc = Nothing
Set enc = Nothing
End Function

Thank you for any guidance you can provide.

Amy
  • 165
  • 1
  • 10
  • 1
    In this specific use case only [RS256 is supported](https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials) as the signing algorithm. Examples in VBA: [one](https://github.com/ststeiger/Jwt_Net20/blob/master/vbJWT/JWT.vb) [two](https://github.com/krijnsent/crypto_vba/blob/master/ModHash.bas) – identigral Jan 07 '22 at 22:20
  • Thank you @identigral . Link one appears to be in VB, link two looks promising but I'm confused on how I would use RS256 signing with this. The methods available are: `Methods: default SHA1, other options SHA512, SHA384 and SHA256` – Amy Jan 11 '22 at 15:09
  • 1
    the 1st example: `string token = JWT.JsonWebToken.Encode(payload, privateKey, JWT.JwtHashAlgorithm.RS256)`. Load their [sample project](https://github.com/ststeiger/Jwt_Net20/tree/master/vbConsoleTestApplication) and play with it. – identigral Jan 11 '22 at 16:47

1 Answers1

1

The general approach should be to use asymmetric encryption that works like this:

CREATE YOUR OWN KEY PAIR

Most commonly RSA256 is used, and that is a good starting point, though EC256 is considered stronger. Note that currently you are using HS256, which means Azure would need to receive the private key to verify the assertion.

CREATE AN ASSERTION FROM THE PRIVATE KEY

Only you can create this because only you have the private key. There is some C# code here that you could translate to VB.

UPLOAD THE PUBLIC KEY TO AZURE AD

This is saved to Certificates and Secrets area, after which Azure AD can verify signatures. This previous answer has some useful screenshots, and also some notes on creating keypairs for development.

IMPORTING KEYS FROM CERT FILES

First you need to ensure that the cert you have been given is RSA and compatible with Azure AD - see identigral's comment. You can generate your own one for testing if needed.

I would aim to write a console app that produces the assertion as a first step. Then translate to VBA later.

The key will need to be imported into a .NET object, preferably using one of the operations described in this article, eg ImportFromPem. You can then use digital signing as described here, which is similar to what you posted above.

Gary Archer
  • 22,534
  • 2
  • 12
  • 24
  • Thank you @Gary Archer . I should have been more clear in my OP that I've been provided a certificate from the service provider to use for auth. Specifically, I'm looking to know what exactly is used to sign the data. I'm reading it's the private key but do I remove the -----BEGIN PRIVATE KEY-----, do I need to remove line breaks, etc. – Amy Jan 09 '22 at 15:13