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 Informationfill in the following fields:App name- be aware of the naming restrictionsUser support email- normally your email address
- Under
Audience:- Select
Internalif you are using a Google Workspace account - Select
Externalif you are using a personal account
- Select
- Under
Contact Informationfill in the following fields:Email address- same asUser support email
- Click on
- Click on Audience and under
Test Usersadd 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 Credentialsand selectOAuth client ID - Under
Application typeselectWeb application - Under
Authorized redirect URIsadd the following URIhttps://developers.google.com/oauthplayground - Click on
Create - Click on
Download JSONto download the credentials file. This file contains yourClient IDandClient 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-JsonUsing 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 "[email protected]"$keyData = Get-Content -AsByteStream -Path D:\service_account.p12
Get-GDriveAccessToken -KeyData $KeyData `
-KeyId 'd41d8cd98f0b24e980998ecf8427e' `
-ServiceAccountMail test-account@980998ecf8427e.iam.gserviceaccount.com `
-ImpersonationUser "[email protected]"$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 IDandOAuth Client Secretfields with the values from your credentials file.
- Fill in the
- Under
Select & authorize APIssearch and select the following scopes: 1.UnderDrive API v3select the following scopes:https://www.googleapis.com/auth/drivehttps://www.googleapis.com/auth/drive.file
- Under
Google Sheets API v4select the following scopes:https://www.googleapis.com/auth/spreadsheets
- Click on
Authorize APIsand follow the prompts to authorize the application. - Click on
Exchange authorization code for tokensto 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 $errIn 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-Stringfunction 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-Stringfunction 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] }