I have been working for weeks trying to interpret and follow the instructions on Using OAuth 2.0 for Server to Server Applications for connecting our work SQL based calendar to our Google calendar. I first tried directly interacting using HTTP but was not successful in creating the correct signature, even tho I used Ben Nadel's 2015 JSONWebTokens.cfc as a resource. Then I came across Java Integration Guide CFML Documentation and realized that it might be possible to use Google's provided JAVA client library, which would be ideal for security reasons. Has anyone successfully connected server to server with Google APIs using either method? If so, I could really use help.
Here is where I am stuck in the JAVA route:
- I have downloaded the Google APIs Client Library onto my server test folder, lets call it /usingJAVA/calendar/
- I have an application file in /usingJAVA with the following lines indicating JAVA class file paths:
<CFSET this.javaSettings = {loadPaths = ["/usingJAVA/calendar/","/usingJAVA/calendar/libs/","/usingJAVA/calendar/libs-sources/"], reloadOnChange=true,watchInterval=100 }>
3. I have taken the JAVA code provided on the instructions for "Other", since I am not running on Google Compute Engine, and 'translated' it to CF
<CFSCRIPT>
SQLAdminScopes = createObject("java", "com.google.api.services.sqladmin.SQLAdminScopes");
writeOutput(SQLAdminScopes);
</CFSCRIPT>
4. When I run this code (and many variations of it!) I get an error:
Message: Object instantiation exception.
Detail: Class not found: com.google.api.services.sqladmin.SQLAdminScopes
The calendar library contains only jars, so I can not check the location of the classes and am just depending on the path shown in the JAVA import code provided.
Here is where I am stuck in the HTML route:
- Here is my function to create the JWT
<CFFUNCTION name="createToken" access="public" output="true" hint="Create a JSON Web Token">
<CFSET local.expireTime = dateadd('h',1,now())>
<!---create JWT header--->
<CFSET local.header = '{"alg":"RS256","typ":"JWT"}'>
<CFSET local.Base64header = toBase64(local.header)>
<!---create JWT claim set--->
<CFSET local.claimSet = structNew()>
<CFSET local.claimSet["iss"] = "myprojectserviceaccount.com">
<CFSET local.claimSet["scope"] = "https://www.googleapis.com/auth/calendar">
<CFSET local.claimSet["aud"] = "https://www.googleapis.com/oauth2/v4/token">
<CFSET local.claimSet["exp"] = GetEpochTime(local.expireTime)><!---an inline function--->
<CFSET local.claimSet["iat"] = GetEpochTime(now())>
<CFSET local.JSONclaimSet = SerializeJSON(local.claimSet)>
<CFSET local.Base64claimSet = ToBase64(local.JSONclaimSet)>
<!---create JWT signature--->
<CFSET local.signatureInput = '{#Base64header#}.{#local.Base64ClaimSet#}'>
<CFSET var signer = createObject( "java", "java.security.Signature" )
.getInstance( javaCast( "string", "SHA256withRSA" ) )>
<CFSET signer.initSign( variables.privatekey )>
<CFSET signer.update( charsetDecode(local.signatureInput, "utf-8" ) )>
<CFSET local.signatureSigned = signer.sign()>
<CFSET local.Base64Signature = ToBase64(local.signatureSigned)>
<CFSET local.tokenstring = '{#local.Base64header#}.{#local.Base64claimSet#}.{#local.Base64signature#}'>
<CFRETURN local.tokenstring>
</CFFUNCTION>
2. When I call this function I get an error on the call for the initSign class of Security:
Message: The initSign method was not found.