0

I have a linux OS based custom embedded system. There are cameras connected to my system and i want to use google drive as cloud storage for records that were taken from my cameras.

For that purpose i used almost all google drive api functions successfully by following google drive api rest documentation in

https://developers.google.com/drive/v3/web/about-sdk

Restful api functions require an access_token for authentication purpose in accordance with OAuth2 protocol in HTTP requests. Getting this token requires some one time manual operations.

1- When signed in to google with my account, i had to create a client_id and a client_secure using google developer console.

2- Then i use these credentials to get access_code. In a response to a http request google sends me a url and a grant code.

3- Then i visit the url using a browser, typing grant code and allowing for authentication manually. Then i get access_token and refresh_token with another HTTP request.

4- After that point i can use any api function successfully with given access_token. (and i refresh it if it expires using refresh_token)

My problem is one time manual operations that are made to get tokens. I am making these operation in my computer so making them in my embedded system looks very difficult. But i want to make all the steps (signing in, client_id and client_secure, visiting url, typing grant code and allowing for authentication) in my embedded system.

So, I wonder if it is possible doing all this one time manual process to get access_code without using developer console and a browser? Can i make them programatically?


This is what i tried following oauth2 google official documentation.

After creating client_id and client_Secret i simply used curl for http operations. I wrote following bash code for testing purpose. So It is not self confident and requires some files which can be empty at first and named "access_token", "folder_id", "refresh_token", "myFile" files in the same directory.

#!/bin/bash

# Google Drive API

get_file_id() {
    RESPONSE=`curl --silent -H 'GData-Version: 3.0' -H "Authorization: Bearer $ACCESS_TOKEN" \
        https://www.googleapis.com/drive/v2/files?q=title+contains+\'$1\'\&fields=items%2Fid`
    FILE_ID=`echo $RESPONSE | python -mjson.tool | grep -oP 'id"\s*:\s*"\K(.*)"' | sed 's/"//'`
}

set -e

CLIENT_SECRET="my client_secret"
CLIENT_ID="my_client_id"
BOUNDARY="foo_bar_baz"
SCOPE="https://docs.google.com/feeds"
MIME_TYPE="application/octet-stream"
ACCESS_TOKEN=`cat access_token`
REFRESH_TOKEN=`cat refresh_token`
FOLDER_ID=`cat folder_id`

if [ "$1" == "create_token" ]; then # Usage: <"create_token">
    RESPONSE=`curl --silent "https://accounts.google.com/o/oauth2/device/code" -d "client_id=$CLIENT_ID&scope=$SCOPE"`
    DEVICE_CODE=`echo "$RESPONSE" | python -mjson.tool | grep -oP 'device_code"\s*:\s*"\K(.*)"' | sed 's/"//'`
    USER_CODE=`echo "$RESPONSE" | python -mjson.tool | grep -oP 'user_code"\s*:\s*"\K(.*)"' | sed 's/"//'`
    URL=`echo "$RESPONSE" | python -mjson.tool | grep -oP 'verification_url"\s*:\s*"\K(.*)"' | sed 's/"//'`
    echo -n "Go to $URL and enter $USER_CODE to grant access to this application. Hit enter when done..."
    read

    RESPONSE=`curl --silent "https://accounts.google.com/o/oauth2/token" -d "client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&code=$DEVICE_CODE&grant_type=http://oauth.net/grant_type/device/1.0"`
    ACCESS_TOKEN=`echo "$RESPONSE" | python -mjson.tool | grep -oP 'access_token"\s*:\s*"\K(.*)"' | sed 's/"//'`
    REFRESH_TOKEN=`echo "$RESPONSE" | python -mjson.tool | grep -oP 'refresh_token"\s*:\s*"\K(.*)"' | sed 's/"//'`
    echo "Access Token: $ACCESS_TOKEN"
    echo "Refresh Token: $REFRESH_TOKEN"
    echo "$ACCESS_TOKEN" > access_token
    echo "$REFRESH_TOKEN" > refresh_token

elif [ "$1" == "refresh_token" ]; then # Usage: <"refresh_token">
    RESPONSE=`curl --silent "https://accounts.google.com/o/oauth2/token" --data "client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&refresh_token=$REFRESH_TOKEN&grant_type=refresh_token"`
    ACCESS_TOKEN=`echo $RESPONSE | python -mjson.tool | grep -oP 'access_token"\s*:\s*"\K(.*)"' | sed 's/"//'`  
    echo "Access Token: $ACCESS_TOKEN"  
    echo "$ACCESS_TOKEN" > access_token

elif [ "$1" == "create_folder" ]; then # Usage: <"create_folder">
    FOLDER_NAME=`date "+%F-%T"`
    ( echo -en "{ \"title\": \"$FOLDER_NAME\", \"mimeType\": \"application/vnd.google-apps.folder\" }\n" ) \
        | curl -H 'GData-Version: 3.0' -v "https://www.googleapis.com/drive/v2/files" \
        --header "Authorization: Bearer $ACCESS_TOKEN" \
        --header "Content-Type: application/json" \
        --data-binary "@-"
    #save FILE_ID to filde
    get_file_id $FOLDER_NAME
    echo "$FILE_ID" > folder_id

elif [ "$1" == "upload_file" ]; then # Usage: <"upload_file"> <file name>
    ( echo -en "--$BOUNDARY\nContent-Type: application/json; charset=UTF-8\n\n{ \"title\": \"$2\", \"parents\": [ { \"id\": \"$FOLDER_ID\" } ] }\n\n--$BOUNDARY\nContent-Type: $MIME_TYPE\n\n" \
    && cat $2 && echo -en "\n\n--$BOUNDARY--\n" ) \
        | curl -H 'GData-Version: 3.0' -v "https://www.googleapis.com/upload/drive/v2/files/?uploadType=multipart" \
        --header "Authorization: Bearer $ACCESS_TOKEN" \
        --header "Content-Type: multipart/related; boundary=\"$BOUNDARY\"" \
        --data-binary "@-"

elif [ "$1" == "list_files" ]; then # Usage: <"list_files"> <number of files>
    curl -H 'GData-Version: 3.0' -H "Authorization: Bearer $ACCESS_TOKEN" \
        https://www.googleapis.com/drive/v2/files?maxResults=$2

elif [ "$1" == "download_file" ]; then # Usage: <"download_file"> <file name>
    get_file_id $2
    curl -H 'GData-Version: 3.0' -H "Authorization: Bearer $ACCESS_TOKEN" \
        https://www.googleapis.com/drive/v2/files/$FILE_ID?alt=media

elif [ "$1" == "get_file" ]; then # Usage: <"get_file"> <file name> 
    get_file_id $2
    curl -H 'GData-Version: 3.0' -H "Authorization: Bearer $ACCESS_TOKEN" \
        https://www.googleapis.com/drive/v2/files/$FILE_ID

elif [ "$1" == "delete_file" ]; then # Usage: <"delete_file"> <file name>
    get_file_id $2
    curl -X Delete -H 'GData-Version: 3.0' -H "Authorization: Bearer $ACCESS_TOKEN" \
        https://www.googleapis.com/drive/v2/files/$FILE_ID

elif [ "$1" == "trash_file" ]; then # Usage: <"trash_file"> <file name>
    get_file_id $2
    curl -d -H 'GData-Version: 3.0' -H "Authorization: Bearer $ACCESS_TOKEN" \
        https://www.googleapis.com/drive/v2/files/$FILE_ID/trash

elif [ "$1" == "untrash_file" ]; then # Usage: <"untrash_file"> <file name>
    get_file_id $2
    curl -d -H 'GData-Version: 3.0' -H "Authorization: Bearer $ACCESS_TOKEN" \
        https://www.googleapis.com/drive/v2/files/$FILE_ID/untrash
fi

exit 0

Regards

mehmet riza oz
  • 541
  • 6
  • 18

1 Answers1

0

One way to do this would be to use Domain-Wide Delegation of Authority, a service account. This method works with a JWT for the authentication. The process is explained here: Using OAuth 2.0 for Server to Server Applications

The app would use the service account to authenticate as the id that you want t use to store the drive files.

Jasper Duizendstra
  • 2,587
  • 1
  • 21
  • 32
  • True, but authenticating as a user, store the refresh token is an option, but a service account is easier IMHO. I did assume a G suite environment, that might not be the case. Then it is a matter getting the credentials on the pc and transferring them to the embedded system? – Jasper Duizendstra Nov 02 '16 at 15:37
  • the embedded system can get them directly, see first link in comments above. – Zig Mandel Nov 02 '16 at 16:09
  • Do you propose using ClientLogin in the SO question link above? Except for ClientLogin which is deprecated the question there is much more about using refresh_token. – mehmet riza oz Nov 07 '16 at 07:55