PowerShell – OAuth & Downloading,Uploading to Google Drive via Drive API

Google offers a REST API that can be accessed via PowerShell to Upload, Download, and change files relatively easily.

Where does this come handy? This could be used to dynamically process Active Directory, Office 365, employee onboarding workflows, or any other system changes off a Google Sheet. This also allows the sysadmin to routinely upload logs, backup files, or any other data to Google Drive as apart of their job process.

This guide shows from start to finish how to generate an OAuth token, Download a file, and upload a file to Google Drive via the Drive REST HTTP API.

Create Project and OAuth Tokens

  1. Go to https://console.developers.google.com/iam-admin/projects?
  2. Create a new project
  3. Enable the Drive API by selecting the Drive API and selecting enable API , after creating your project.
  4. Click Credentials
  5. Create OAuth Client ID Credentials
  6. Select Web Application as product type
  7. Configure the Authorized Redirect URI to https://developers.google.com/oauthplayground must not have a ending “/” in the URI
  8. Save your client ID and Secret
  9. Browse to https://developers.google.com/oauthplayground
    This saves us time from generating an OAuth request in PowerShell. This is where we will authorize our Project to our Google Account using our provided Client ID and Client Secret. 
  10. Click the gear in the right-hand corner and select “Use your own OAuth credentials
  11. Authorize the https://www.googleapis.com/auth/drive API
  12. Click “Exchange Refresh Token for Access Token”
    explanation – Access Tokens have a limited lifetime (approximately 60 minutes) whereas Refresh Tokens last indefinitely (some exclusions here). The Access Token is what you will hardcode into your script, configuring the script to hit the Google Identity Platform to request a Refresh Token on execution. 
  13. Save your Refresh Token

Get Auth Token & Download

Now that we have our Refresh Token, Client ID, Client Secret we can request an Access Token with PowerShell.  Random but lookalike values gave for variables.

function Get-GAuthToken {
    $refreshToken = "1/qfbb40x7erxitM2itb__EyrnNdyXvMxSZgrgbr26K3p8c" 
    $ClientID = "651899223565-locvr3qi7l4im0jr1c9nDvkjhgjhlu5b7j6.apps.googleusercontent.com"
    $ClientSecret = "<CLIENT_SECRET_HERE>"
    $grantType = "refresh_token" 
    $requestUri = "https://accounts.google.com/o/oauth2/token" 
    $GAuthBody = "refresh_token=$refreshToken&client_id=$ClientID&client_secret=$ClientSecret&grant_type=$grantType" 
    $GAuthResponse = Invoke-RestMethod -Method Post -Uri $requestUri -ContentType "application/x-www-form-urlencoded" -Body $GAuthBody 
}

note that Invoke-RestMethod was used instead of Invoke-WebRequest. Invoke-RestMethod returns the output to a JSON object that we can easily work with going forward.

Our access token is now $accessToken = $GAuthResponse.access_token .

Now that we have the Access Token, downloading from Drive is pretty straight forward.

$headers = @{"Authorization" = "Bearer $accessToken"          

              "Content-type" = "application/json"}

$DocumentID = "<DOCUEMENT_ID_HERE>" #Your desired document ID, found by clicking "Get Share Link" from the  Drive UI

$File = Invoke-RestMethod -Uri "https://www.googleapis.com/drive/v3/files/$DocumentID/export?mimeType=text/csv" -Method Get -Headers $headers

Notice here that I am requesting to download a Google Sheet as CSV. This is done by calling /{DocumentID}/export?mimeType=txt/csv against the API endpoint. Other formats are supported depending on your file type, or /export can removed if the file is not a G Suite file type. More info on this here.

Uploading to Drive

Traditionally, uploads to Drive are sent via 2 requests. One to send file metadata to get the DocumentID, the second to PUT the contents of the file to the DocumentID. However, the https://www.googleapis.com/upload/drive/v2/files endpoint supports Multi part uploads, allowing us to send metadata and file contents in one request.

    $refreshToken = "1/qUbW0x7eexitM2itb__EyrnNdyXvMxSZCHHr26K3p8c" 
    $ClientID = "651899223565-locvr3qi7l4im0jr1c9narohslu5b7j6.apps.googleusercontent.com"
    $ClientSecret = "<CLIENT_SECRET_HERE>"
    $grantType = "refresh_token" 
    $requestUri = "https://accounts.google.com/o/oauth2/token" 
    $GAuthBody = "refresh_token=$refreshToken&client_id=$ClientID&client_secret=$ClientSecret&grant_type=$grantType" 
    $GAuthResponse = Invoke-RestMethod -Method Post -Uri $requestUri -ContentType "application/x-www-form-urlencoded" -Body $GAuthBody
    $accessToken = $GAuthResponse.access_token 

$GUploadURI  = "https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart"
$GBodySize = ($GUploadBody | Measure-Object  -property length -sum).Sum #Calculates the size in bytes of the HTTP POST body, necessary for Content-Length in the request header 


$title = "My Document Title"
$description = "Stuff about file"
$parentfolder = "<FOLDER_ID_HERE>" #folder ID where to save
$inputmime = "application/vnd.google-apps.document" # https://developers.google.com/drive/v2/web/mime-types more on mime types here
$togoogle = "my text here"
#Request headers
$Guploadheaders = @{"Authorization" = "Bearer $accessToken" 
                    "Content-type" = 'multipart/related; boundary="BOUNDARY"'
                    "Content-Length" = "$GBodySize"}
##The body must be formatted EXACTLY as below. Any extra linebreaks within the boundaries will cause Google to return a 400 error
$GUploadBody= @"
--BOUNDARY
Content-Type: application/json; charset=UTF-8

{
  "title": "$title",
  "parents": [{
    "id":"$parentfolder" 
    }],
  "mimeType": "$inputmime",
  "description": "$description"
  

}
--BOUNDARY
Content-Type: text/plain

$togoogle
--BOUNDARY--

"@
## End HTTP Body

$uploadrequest = Invoke-WebRequest -method Post -uri $GUploadURI -body $GUploadBody -Headers $Guploadheaders
$uploadrequest

3
Leave a Comment

newest oldest most voted
Pramod Yadav

Cool post. I am building something on similar lines and your code is a big help!

Sravan

Great post Montel. I have a script will run everyday and write all published outputs to the folder [C:\publishedoutputs]. Will it be possible to upload published outputs to the google drive by using PS script?