google drive sdk - trouble getting JWT for a server to server application in C -
i have trouble getting jwt server server application. following command
openssl pkcs12 -in mypkcs12-private.p12 -out privatekey.pem.
following doc /docs/oauth2serviceaccount, encoded header
{"alg":"rs256","typ":"jwt"}
and claim
{"iss":"******@developer.gserviceaccount.com","scope":"https://www.googleapis.com/auth/drive.file,"aud":"https://accounts.google.com/o/oauth2/token","exp":1401710837,"iat":1401707237}
in base64. created base64 encoded signature using (b64header.b64claim), private key , hmac function. when request token using curl, invalid_grant error. tried many things don't know issue is.
here code
static size_t writememorycallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; memorystruct *mem = (memorystruct *)userp; mem->memory = realloc(mem->memory, mem->size + realsize + 1); if(mem->memory == null) { /* out of memory! */ printf("not enough memory (realloc returned null)\n"); return 0; } memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; mem->memory[mem->size] = 0; return realsize; } char *base64encode(const char *normal, size_t length) { bio *bmem, *b64; buf_mem *bptr; char *buff = null; b64 = bio_new(bio_f_base64()); bmem = bio_new(bio_s_mem()); b64 = bio_push(b64, bmem); bio_write(b64, normal, (int) length); if (bio_flush(b64) != 1) { return null; } bio_get_mem_ptr(b64, &bptr); buff = (char *) malloc(bptr->length); memcpy(buff, bptr->data, bptr->length-1); buff[bptr->length - 1] = 0; bio_free_all(b64); b64 = null; return buff; } char * createclaimset(char * address) { char * output = null; char claim_format[] = "{\"iss\":\"%s\",\"scope\":\"https://www.googleapis.com/auth/drive.file\",\"aud\":\"https://accounts.google.com/o/oauth2/token\",\"exp\":%ld,\"iat\":%ld}"; size_t len_address = 0; size_t size = 0; time_t iat; time_t exp; time(&iat); exp = iat + 3600; if (address) len_address = strlen(address); size = strlen(claim_format); output = (char*) calloc(len_address + size - 8 + 20 + 1, sizeof(char)); sprintf(output,claim_format, address, exp, iat); printf(output); return output; } char *b64hmacsha256fct(char *line, char * keyp12, size_t size) { char *hmac64 = ""; const evp_md *evp_md = evp_sha256(); unsigned char md[evp_max_md_size]; unsigned int md_len; // hmac hmac(evp_md, keyp12, (int)size, (const unsigned char*) line, strlen(line), md, &md_len); hmac64=base64encode(md, md_len); return hmac64; } int authserviceaccount(curl *curl) { char * b64_claim_set = null; char * claim_set = null; char * header64 = null; char * jwt = null; char * tosign = null; char * sig64 = null; char * str = null; char * data = null; char * privatekey = null; char grant[] = "grant_type=urn%3aietf%3aparams%3aoauth%3agrant-type%3ajwt-bearer"; char uri[] = "https://accounts.google.com/o/oauth2/token"; char header[] = "{\"alg\":\"rs256\",\"typ\":\"jwt\"}"; char emailaddress[] = "xxxxxx@developer.gserviceaccount.com"; char pkcs12_file_path[] = "c:\\temp\\mykey.key"; file * pinputp12name = null; int = 0; int j = 0; memorystruct writememory; size_t filep12size = 0; size_t lclaim64 = 0; size_t lclaimset = 0; size_t lheader64 = 0; size_t lstr = 0; size_t resultat; header64 = base64encode(header, strlen(header)); if (header64) lheader64 = strlen(header64); claim_set = createclaimset(emailaddress); if (claim_set) lclaimset = strlen(claim_set); b64_claim_set = base64encode(claim_set, lclaimset); if (b64_claim_set) lclaim64 = strlen(b64_claim_set); str = (char*) calloc(lclaim64+1, sizeof(char)); if (!str) return 1; (i=0; i<lclaim64; i++) { if (isprint(b64_claim_set[i])) { str[j] = b64_claim_set[i]; j++; } } str[j] = '\0'; if (str) lstr = strlen(str); tosign = (char*) calloc(lheader64 + 1 + lstr + 1, sizeof(char)); if (!tosign) return 1; sprintf(tosign,"%s.%s",header64,str); pinputp12name = fopen (pkcs12_file_path,"rb"); if (pinputp12name==null) { perror ("error opening file"); return (-1); } else { resultat = _fseeki64(pinputp12name, 0, seek_end); filep12size= (size_t) ftell(pinputp12name); rewind(pinputp12name); privatekey = (char *) calloc(filep12size+1, sizeof(char)); resultat = fread (privatekey,sizeof(char),filep12size,pinputp12name); fclose (pinputp12name); } sig64 = b64hmacsha256fct(tosign,privatekey,filep12size); if (!sig64) return 1; jwt = (char *) calloc(strlen(tosign) + 1 + strlen(sig64) + 1, sizeof(char)); sprintf(jwt,"%s.%s", tosign, sig64); if (curl) { file* pfile = null; size_t size = 0; memset(&writememory,'\0',sizeof(memorystruct)); size = strlen(grant)+strlen("&assertion=")+strlen(jwt); data = (char *) calloc(size+1, sizeof(char)); if (!data) return 1; sprintf(data,"%s&assertion=%s", grant, jwt); curl_easy_reset(curl); curl_easy_setopt( curl, curlopt_url, uri ); curl_easy_setopt( curl, curlopt_port , 443 ); curl_easy_setopt( curl, curlopt_post, 1 ); curl_easy_setopt( curl, curlopt_postfields, data); curl_easy_setopt( curl, curlopt_postfieldsize, strlen(data)); curl_easy_setopt( curl, curlopt_header, 1 ); curl_easy_setopt( curl, curlopt_verbose, 1); curl_easy_setopt( curl, curlopt_writedata, &writememory); curl_easy_setopt( curl, curlopt_writefunction, writememorycallback); curl_easy_setopt( curl, curlopt_ssl_verifypeer, 0l); curl_easy_setopt( curl, curlopt_ssl_verifyhost, 0l); curl_easy_perform(curl); printf("%s",writememory.memory); } return 0; } int main(void) { curl *curl; curl_version_info_data *curlvers; curlvers = curl_version_info( curlversion_now ); curl_global_init(curl_global_all); curl = curl_easy_init(); authserviceaccount(curl); /* cleanup */ curl_easy_cleanup(curl); curl_global_cleanup(); exit(0); }
the documentation states must use base64url encoding, variant of base64 encoded uses url-safe characters.
Comments
Post a Comment