coldfusionjwtgoogle-oauthcfml

Creating JWT in Coldfusion for google Service account


I'm confused on the signature aspect for a JWT. I believe I have the header and claim set correct as I got past any errors was seeing when originally writing this. My question is mostly around the signature. IS HMac with HMACSHA256 correct? I think I may be confused on where to get the private key for encryption. If anyone has some guidance that would be great.

<cfset JWT_header = structNew()>
<cfset JWT_header['alg'] = 'RS256'>
<cfset JWT_header['typ'] = 'JWT'>
<cfset JWT_header = serializeJSON(JWT_header)>

<cfset JWT_claim_set = structNew()>
<cfset JWT_claim_set['iss'] = 'secret_iss'>
<cfset JWT_claim_set['scope'] = 'my_scope'>
<cfset JWT_claim_set['aud'] = 'https://www.googleapis.com/oauth2/v4/token'>
<cfset JWT_claim_set['exp'] = 'Time_Stamp')>
<cfset JWT_claim_set['iat'] = 'Time_Stamp')>
<cfset JWT_claim_set = serializeJSON(JWT_claim_set)>

<cfset data = ToBase64(JWT_header) & '.' & ToBase64(JWT_claim_set)>

<cfset hashedData = HMac(data, 'my_secret_private_key','HMACSHA256')>

<cfset signature = toBase64(hashedData)>

<cfset JWT = data & '.' & signature>

<cfhttp url="https://www.googleapis.com/oauth2/v4/token" method="post" result="result">
    <cfhttpparam name="grant_type"          type="formField" value="urn:ietf:params:oauth:grant-type:jwt-bearer" />
    <cfhttpparam name="assertion"       type="formField" value="#JWT#" />
</cfhttp>

<cfoutput>#result.filecontent#</cfoutput>

This returns:

'{ "error": "invalid_grant", "error_description": "Invalid JWT Signature." }'


Solution

  • I got this to work with Ben Nadel's code(https://www.bennadel.com/blog/2941-experimenting-with-rsa-encrypted-signature-generation-and-verification-in-coldfusion.htm), but I had to modify it to work. I commented out anything to do with a public key as I was not using one to interface with google. If I was to enhance it I could create logic to look for the use of public or private key. Next I skipped anything with Pem file formatting since google isn't using that. Now it works.