Google Drive REST API module for Powershell with Google Sheets API support.
- GMGoogleDrive Powershell Module
Google Drive is a free service for file storage files. In order to use this storage you need a Google user which will own the files, and a Google API client.
You need to create a Google project and enable the Google Drive API and Google Sheets API for it to use this module.
- Navigate to the Google Cloud Console, create a new project and give it a name of your choosing.
- You should be redirected to the Project Dashboard for your new project.
- Go to APIs & Services
- Click on Enable APIs and Services.
- Search for
Google Drive API
, click on it and then click Enable. - Search for
Google Sheets API
, click on it and then click Enable.
Before setting up OAuth 2.0 credentials, you need to set up the OAuth consent screen. This is a one-time setup for your project. The consent screen is what users will see when they are asked to authorize your application to access their Google Drive files.
- Navigate to APIs & Services
- Navigate to OAuth consent screen
- Click on
Get Started
- Under
App Information
fill in the following fields:App name
- be aware of the naming restrictionsUser support email
- normally your email address
- Under
Audience
:- Select
Internal
if you are using a Google Workspace account - Select
External
if you are using a personal account
- Select
- Under
Contact Information
fill in the following fields:Email address
- same asUser support email
- Click on
- Click on Audience and under
Test Users
add the email addresses of the users who will be testing/using your application.
Note
Be aware of the limitations of an External
application that is under Testing
mode. The refresh token will expire after 7 days. If you want to have a non-expiring refresh token, you need to publish your application or use an Internal
application.
- Navigate to APIs & Services
- Navigate to Credentials
- Click on
Create Credentials
and selectOAuth client ID
- Under
Application type
selectWeb application
- Under
Authorized redirect URIs
add the following URIhttps://developers.google.com/oauthplayground
- Click on
Create
- Click on
Download JSON
to download the credentials file. This file contains yourClient ID
andClient Secret
.
- Click on
Warning
Make sure that the redirect URI does not have a trailing /
at the end.
Here's how you can reference the credentials in your code:
$oAuthJson = Get-Content -Path 'C:\path\to\your\credentials.json' |
ConvertFrom-Json
Using a service account allows you to upload data to folders that are shared with the service account.
In Google Workspace enterprise environments, it is also possible to grant impersonation rights to the service account. With these rights, the service account can act as a user (without OAuth consent screen).
Please check the Google documentation:
Google offers two types of service user files .json
and .p12
. Both types are implemented in this module.
Get-GDriveAccessToken -Path D:\service_account.json `
-JsonServiceAccount -ImpersonationUser "user@domain.com"
$keyData = Get-Content -AsByteStream -Path D:\service_account.p12
Get-GDriveAccessToken -KeyData $KeyData `
-KeyId 'd41d8cd98f0b24e980998ecf8427e' `
-ServiceAccountMail test-account@980998ecf8427e.iam.gserviceaccount.com `
-ImpersonationUser "user@domain.com"
$authorizationCode = Request-GDriveAuthorizationCode -ClientID $oAuthJson.web.client_id `
-ClientSecret $oAuthJson.web.client_secret
$refreshToken = Request-GDriveRefreshToken -ClientID $oAuthJson.web.client_id `
-ClientSecret $oAuthJson.web.client_secret `
-AuthorizationCode $authorizationCode
- Browse to OAuth 2.0 Playground
- Click the gear in the right-hand corner and place a checkmark next to "Use your own OAuth credentials"
- Fill in the
OAuth Client ID
andOAuth Client Secret
fields with the values from your credentials file.
- Fill in the
- Under
Select & authorize APIs
search and select the following scopes: 1.UnderDrive API v3
select the following scopes:https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.file
- Under
Google Sheets API v4
select the following scopes:https://www.googleapis.com/auth/spreadsheets
- Click on
Authorize APIs
and follow the prompts to authorize the application. - Click on
Exchange authorization code for tokens
to get the yourRefresh token
.
Caution
The Refresh token
can only be retrieved once. If you lose it, you will need to repeat the authorization process to get a new one.
Tip
The Access Token
is a mandatory parameter for almost every GDrive
cmdlet. It is valid for 1 hour and needs to be refreshed every hour.
$accessToken = Get-GDriveAccessToken -ClientID $oAuthJson.web.client_id `
-ClientSecret $oAuthJson.web.client_secret `
-RefreshToken $refreshToken.refresh_token
# Upload new file
Add-GDriveItem -AccessToken $access.access_token -InFile D:\SomeDocument.doc -Name SomeDocument.doc
# Search existing file
Find-GDriveItem -AccessToken $access.access_token -Query 'name="test.txt"'
# Update existing file contents
Set-GDriveItemContent -AccessToken $access.access_token -ID $file.id -StringContent 'test file'
# Get ParentFolderID and Modified Time for file
Get-GDriveItemProperty -AccessToken $access.access_token -ID $file.id -Property parents, modifiedTime
# and so on :)
Cmdlets will exit at the first error. However, for instance if "Metadata Upload" succeeded but content upload failed, UploadID
is returned as ResumeID
to resume operations later.
You can further leverage Get-GDriveError
to get more information about the error by catching it in a try/catch block.
# Catch error
try {
Get-GDriveItemProperty -AccessToken 'error token' -id 'error id'
}
catch {
$err = $_
}
# Decode error message
Get-GDriveError $err
In order to automate operations, you can use the Get-GDriveAccessToken
cmdlet to retrieve an access token and then use that token.
The functions below are meant to be used as an example only. It is outside of the scope of this module to provide a secure way to store your credentials. You can use the Protect-String
and Unprotect-String
functions to convert a string to a secure string and back.
Important
ConvertTo-SecureString
and ConvertFrom-SecureString
use the Windows Data Protection API (DPAPI) to encrypt and decrypt the string.
This means that the encrypted string can only be decrypted on the same machine that it was encrypted on and by the user account that it was encrypted by.
function Protect-String {
<#
.SYNOPSIS
Convert String to textual form of SecureString
.PARAMETER String
String to convert
.OUTPUTS
String
.NOTES
Author: MVKozlov
#>
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]
$String
)
PROCESS {
$String | ConvertTo-SecureString -AsPlainText -Force |
ConvertFrom-SecureString
}
}
function Unprotect-String {
<#
.SYNOPSIS
Convert SecureString to string
.PARAMETER String
String to convert (textual form of SecureString)
.PARAMETER SecureString
SecureString to convert
.OUTPUTS
String
.NOTES
Author: MVKozlov
#>
[CmdletBinding(DefaultParameterSetName = 'String')]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0, ParameterSetName = 'String')]
[string]
$String,
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0, ParameterSetName = 'SecureString')]
[securestring]
$SecureString
)
PROCESS {
if ($String) {
$SecureString = $String | ConvertTo-SecureString
}
if ($SecureString) {
(New-Object System.Net.NetworkCredential '', ($SecureString)).Password
}
}
}
-
Open Powershell on the machine that will run the script using the specified user account.
# Method 1: Using runas command runas /user:DOMAIN\username powershell.exe # Method 2: Using the `-Credential` parameter of Start-Process Start-Process powershell.exe -Credential (Get-Credential)
-
Use the
Protect-String
function to convert your credentials to a secure string and save it to a file.$credentials = [PSCustomObject]@{ ClientID = 'clientid' ClientSecret = 'clientsecret' RefreshToken = 'refreshtoken' } | ConvertTo-Json | Protect-String | Set-Content -Path C:\Path\somefile -Value $credentials
-
In your automated script, use the
Unprotect-String
function to retrieve the credentials and use them to get the access token.$credentials = Get-Content -Path C:\path\somefile | Unprotect-String | ConvertFrom-Json try { Write-Host "Getting access token..." $token = Get-GDriveAccessToken -ClientID $credentials.ClientID ` -ClientSecret $credentials.ClientSecret ` -RefreshToken $credentials.RefreshToken Write-Host "Token expires $((Get-Date).AddSeconds($token.expires_in))" } catch { Write-Warning "Error retrieving access token $_" Get-GDriveError $_ } if ($token) { $Summary = Get-GDriveSummary -AccessToken $token.access_token ` -ErrorAction Stop # [rest of your code here] }