Skip to content

Instantly share code, notes, and snippets.

@vanessaaleung
Created April 17, 2019 06:51
Show Gist options
  • Save vanessaaleung/c4e5143837e1791d8e1abfb031472b14 to your computer and use it in GitHub Desktop.
Save vanessaaleung/c4e5143837e1791d8e1abfb031472b14 to your computer and use it in GitHub Desktop.
Implement OAuth 2.0 authorization to access Google Drive API in C programming
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if(ptr == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
int main(void)
{
CURL *curl_handle, *curl_handle2, *curl_handle3, *curl_handle4;
CURLcode res, res2, res3, res4;
struct MemoryStruct chunk, chunk2, chunk3, chunk4;
chunk.memory = malloc(1); /* will be grown as needed by the realloc above */
chunk.size = 0; /* no data at this point */
char user_code[21];
char device_code[200];
char access_token[200];
curl_global_init(CURL_GLOBAL_ALL);
/* init the curl session */
curl_handle = curl_easy_init();
/* specify URL to get */
curl_easy_setopt(curl_handle, CURLOPT_URL, "https://accounts.google.com/o/oauth2/device/code");
/* Now specify the POST data */
/* Step 1: Request device and user codes */
curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, "client_id=603382496792-5ac366vug85fs77v13lh1550cjem0fs5.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/drive.file");
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
/* some servers don't like requests that are made without a user-agent
field, so we provide one */
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
/* get it! */
res = curl_easy_perform(curl_handle);
/* Step 2: Handle the authorization server response */
/* check for errors */
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else {
char *expire_result = strstr(chunk.memory, "\"expires_in");
int expire_position = (int)(expire_result - chunk.memory);
char *user_result = strstr(chunk.memory, "\"user_code");
int user_position = (int)(user_result - chunk.memory);
int uc_length = expire_position - user_position - 19;
memcpy(user_code, &chunk.memory[user_position] + 14, uc_length);
user_code[uc_length] = '\0';
char *device_result = strstr(chunk.memory, "device_code");
int device_position = (int)(device_result - chunk.memory);
int dc_length = user_position - device_position - 20;
memcpy(device_code, &chunk.memory[device_position] + 15, dc_length);
device_code[dc_length] = '\0';
}
curl_easy_cleanup(curl_handle);
free(chunk.memory);
/* Step 3: Display the user code */
printf("Enter below code on 'https://www.google.com/device' :\n");
printf("%s\n", user_code);
printf("Press enter when finish\n");
while( getchar() != '\n' );
/* init the curl session */
curl_handle2 = curl_easy_init();
/* specify URL to get */
curl_easy_setopt(curl_handle2, CURLOPT_URL, "https://www.googleapis.com/oauth2/v4/token");
char url[300];
strcat(url, "client_id=603382496792-5ac366vug85fs77v13lh1550cjem0fs5.apps.googleusercontent.com&client_secret=6kVOv06vdWFKYwMixUFioF5d&code=");
strcat(url, device_code);
strcat(url, "&grant_type=http://oauth.net/grant_type/device/1.0");
curl_easy_setopt(curl_handle2, CURLOPT_POSTFIELDS, url);
curl_easy_setopt(curl_handle2, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handle2, CURLOPT_WRITEDATA, (void *)&chunk2);
curl_easy_setopt(curl_handle2, CURLOPT_USERAGENT, "libcurl-agent/1.0");
res2 = curl_easy_perform(curl_handle2);
if(res2 != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res2));
}
else {
//printf("%s\n", chunk2.memory);
char *ei2_result = strstr(chunk2.memory, "\"expires_in");
int ei2_position = (int)(ei2_result - chunk2.memory);
char *at_result = strstr(chunk2.memory, "\"access_token");
int at_position = (int)(at_result - chunk2.memory);
int at_length = ei2_position - at_position - 22;
memcpy(access_token, &chunk2.memory[at_position] + 17, at_length);
access_token[at_length] = '\0';
/* init the curl session */
curl_handle3 = curl_easy_init();
char token[200];
strcat(token, "https://www.googleapis.com/drive/v2/files?access_token=");
strcat(token, access_token);
curl_easy_setopt(curl_handle3, CURLOPT_URL, token);
curl_easy_setopt(curl_handle3, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handle3, CURLOPT_WRITEDATA, (void *)&chunk3);
curl_easy_setopt(curl_handle3, CURLOPT_USERAGENT, "libcurl-agent/1.0");
res3 = curl_easy_perform(curl_handle3);
if(res3 != CURLE_OK){
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res3));
}
else{
printf("%s\n", "Authorization sucessed");
}
curl_easy_cleanup(curl_handle3);
free(chunk3.memory);
}
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle2);
free(chunk2.memory);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment