Introduction
With over 2 billion registered users, Google G Suite is one of the world's most popular cloud solutions across various industries. This article will lead you through creating your own custom target connector for G Suite, using HelloID's PowerShell target connector.
Getting Connected
In this example we are going to connect to the Google API using OAuth2.0 and the PowerShell Invoke-RestMethod cmdlet. Before we can start scripting in PowerShell using the example script below, we first need to get a ClientId, ClientSecret, AuthCode and finally the Access and Refresh tokens.
Getting the Google API access
- Go to Google Developers Console and create a new project by clicking on the top bar and choosing New Project.
- Give your project a name and click Create. When you are done, click the top bar again and select your newly created project.
You will see the empty dashboard where you can select which API the project interacts with. In this example, we are managing user accounts. As such, select the Admin SDK and click the Enable button. Afterwards, you will be redirected back to the dashboard.
As stated on the dashboard, go to the credentials menu item and click on Create Credentials and choose OAuth client ID.
- For Application Type, choose Web Application.
- Fill in a name you like for the OAuth 2.0 client ID.
- For Authorized redirect URIs, specify http://localhost/oauth2callback
- Click Create the OAuth 2.0 consent screen and we will get the credentials from the credentials page.
- The Client ID and Client secret of the new OAuth client we use in the example scripts below.
Getting the authorization code
With the authorization code, we can get the refresh token. We only need the refresh token, so the easiest way to get this one is to opening the endpoint in the browser, authenticate, and copy the code from the address bar.
To get the authorization code please use the URL below and replace the <replaceclientid> and <replaceredirecturi> with the values from the OAuth client we created before.
https://accounts.google.com/o/oauth2/auth?client_id=<replaceclientid>&scope=https://www.googleapis.com/auth/admin.directory.user&response_type=code&redirect_uri=<replaceredirecturi>&access_type=offline&approval_prompt=force
After you have been authenticated, the request will be redirected to http://localhost/oauth2callback?code=4/QhUXhB********************z9jGKkhvac2&. Copy the code without the & at the end and store it somewhere; you will need it later on.
Getting the refreshToken
To exchange the authorization code for the refresh token, we will use PowerShell to make a call to https://www.googleapis.com/oauth2/v4/token.
Fill in Authorization code, ClientId, Client Secret and Redirect URI from the Google Developer Console and run the PowerShell script below. It will store the refresh token in a text file so you can use it later on.
Note: The claimed authorization code can be exchanged for a refreshToken only once, otherwise you have to request a new authorization code as described above.
Run the following PowerShell script. After the script has completed successfully, there will be a file named refreshToken.txt containing the token value.
$requestUri = "https://www.googleapis.com/oauth2/v4/token"
$clientId = "<put your client id here>"
$clientSecret = "<put your client secret here>"
$redirectUri = "http://localhost/oauth2callback"
$code = "<put your authorization code here>"
$body = @{
code=$code;
client_id=$clientId;
client_secret=$clientSecret;
redirect_uri=$redirectUri;
grant_type="authorization_code"; # Fixed value
};
$tokens = Invoke-RestMethod -Uri $requestUri -Method POST -Body $body;
# Store refreshToken
Set-Content $PSScriptRoot"\refreshToken.txt" $tokens.refresh_token
Authorizing the OAuth client for API access
- Log in to your Google Apps environment management console (https://admin.google.com) with an administrative account.
- From the search bar on the top of the page, search for "Manage API client access".
- Select the item Manage API client access.
- Scroll down to Advanced settings (if it is not visible, click Show more) and in the Authentication setting click on Manage API client access.
- In the Client Name field, enter the Client ID value generated for the service account in the developer console.
- Enter the APIs to be authorized in the API scopes input field. For example, you can use "https://www.googleapis.com/auth/admin.directory.user" to authorize user account management. Once you are finished, click on Authorize. More information about API scopes can be found here.
Customize the connector's lifecycle stages
Once you have established an API connection to Google, you are ready to begin customizing the lifecycle stages of the connector in HelloID. The following scripts can be assigned to each of the lifecycle stages. Update the scripts accordingly with your own values for Client ID, Client Secret, Refresh Token, and default domain values.
These scripts serve as basic examples of how you can work with the G Suite API to manage user accounts. You are free to extend these examples as you see fit.
Account Create Example
$clientId = "<put your client id here>"
$clientSecret = "<put your client secret here>"
$redirectUri = "http://localhost/oauth2callback"
$refreshToken = "<put your refreshtoken here>"
#Initialize default properties
$success = $False;
$p = $person | ConvertFrom-Json
$auditMessage = "Account for person " + $p.DisplayName + " not created successfully";
$defaultPassword = "Welkom01!";
$defaultDomain = "yourdomain.com";
#Change mapping here
#For all of the supported attributes please check https://developers.google.com/admin-sdk/directory/v1/guides/manage-users
$account = [PSCustomObject]@{
primaryEmail = $p.Contact.Business.Email.split("@")[0] + "@" + $defaultDomain
name = @{
givenName = $p.Name.NickName
familyName = $p.Name.FamilyName
fullName = ($p.Name.NickName + " " + $p.Name.FamilyName)
}
externalIds = @{
value = $p.ExternalId
type = "custom"
customType = "employee"
}
password = $defaultPassword
suspended = $True
}
try{
if(-Not($dryRun -eq $True)){
### exchange the refresh token for an access token
$requestUri = "https://www.googleapis.com/oauth2/v4/token"
$refreshTokenParams = @{
client_id=$clientId;
client_secret=$clientSecret;
redirect_uri=$redirectUri;
refresh_token=$refreshToken;
grant_type="refresh_token"; # Fixed value
};
$response = Invoke-RestMethod -Method Post -Uri $requestUri -Body $refreshTokenParams -Verbose:$false
$accessToken = $response.access_token
#Add the authorization header to the request
$authorization = @{
Authorization = "Bearer $accesstoken";
'Content-Type' = "application/json";
Accept = "application/json";
}
$body = $account | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri "https://www.googleapis.com/admin/directory/v1/users/$aRef" -Method POST -Headers $authorization -Body $body -Verbose:$false
$aRef = $response.id
}
$success = $True;
$auditMessage = " successfully";
}catch{
if(-Not($_.Exception.Response -eq $null)){
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$errResponse = $reader.ReadToEnd();
$auditMessage = " : ${errResponse}";
}else {
$auditMessage = " : General error";
}
}
#build up result
$result = [PSCustomObject]@{
Success= $success;
AccountReference= $aRef;
AuditDetails=$auditMessage;
Account= $account;
};
Write-Output $result | ConvertTo-Json -Depth 10;
Account Enable Example
$clientId = "<put your client id here>"
$clientSecret = "<put your client secret here>"
$redirectUri = "http://localhost/oauth2callback"
$refreshToken = "<put your refreshtoken here>"
#Initialize default properties
$success = $False;
$p = $person | ConvertFrom-Json
$aRef = $accountReference | ConvertFrom-Json;
$auditMessage = " not enabled successfully";
#Change mapping here
$account = [PSCustomObject]@{
suspended = $False
}
try{
if(-Not($dryRun -eq $True)){
### exchange the refresh token for an access token
$requestUri = "https://www.googleapis.com/oauth2/v4/token"
$refreshTokenParams = @{
client_id=$clientId;
client_secret=$clientSecret;
redirect_uri=$redirectUri;
refresh_token=$refreshToken;
grant_type="refresh_token"; # Fixed value
};
$response = Invoke-RestMethod -Method Post -Uri $requestUri -Body $refreshTokenParams -Verbose:$false
$accessToken = $response.access_token
#Add the authorization header to the request
$authorization = @{
Authorization = "Bearer $accesstoken";
'Content-Type' = "application/json";
Accept = "application/json";
}
$body = $account | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri "https://www.googleapis.com/admin/directory/v1/users/$aRef" -Method PUT -Headers $authorization -Body $body -Verbose:$false
}
$success = $True;
$auditMessage = " successfully";
}catch{
if(-Not($_.Exception.Response -eq $null)){
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$errResponse = $reader.ReadToEnd();
$auditMessage = " : ${errResponse}";
}else {
$auditMessage = " : General error";
}
}
#build up result
$result = [PSCustomObject]@{
Success= $success;
AccountReference= $aRef;
AuditDetails=$auditMessage;
Account= $account;
};
Write-Output $result | ConvertTo-Json -Depth 10;
Account Update Example
$clientId = "<put your client id here>"
$clientSecret = "<put your client secret here>"
$redirectUri = "http://localhost/oauth2callback"
$refreshToken = "<put your refreshtoken here>"
#Initialize default properties
$success = $False;
$p = $person | ConvertFrom-Json
$aRef = $accountReference | ConvertFrom-Json;
$auditMessage = "Account for person " + $p.DisplayName + " not updated successfully";
$defaultDomain = "yourdomain.com";
#Change mapping here
#For all of the supported attributes please check https://developers.google.com/admin-sdk/directory/v1/guides/manage-users
$account = [PSCustomObject]@{
primaryEmail = $p.Contact.Business.Email.split("@")[0] + "@" + $defaultDomain
name = @{
givenName = $p.Name.NickName
familyName = $p.Name.FamilyName
fullName = ($p.Name.NickName + " " + $p.Name.FamilyName)
}
externalIds = @{
value = $p.ExternalId
type = "custom"
customType = "employee"
}
}
try{
if(-Not($dryRun -eq $True)){
### exchange the refresh token for an access token
$requestUri = "https://www.googleapis.com/oauth2/v4/token"
$refreshTokenParams = @{
client_id=$clientId;
client_secret=$clientSecret;
redirect_uri=$redirectUri;
refresh_token=$refreshToken;
grant_type="refresh_token"; # Fixed value
};
$response = Invoke-RestMethod -Method Post -Uri $requestUri -Body $refreshTokenParams -Verbose:$false
$accessToken = $response.access_token
#Add the authorization header to the request
$authorization = @{
Authorization = "Bearer $accesstoken";
'Content-Type' = "application/json";
Accept = "application/json";
}
$body = $account | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri "https://www.googleapis.com/admin/directory/v1/users/$aRef" -Method PUT -Headers $authorization -Body $body -Verbose:$false
}
$success = $True;
$auditMessage = " successfully";
}catch{
if(-Not($_.Exception.Response -eq $null)){
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$errResponse = $reader.ReadToEnd();
$auditMessage = " : ${errResponse}";
}else {
$auditMessage = " : General error";
}
}
#build up result
$result = [PSCustomObject]@{
Success= $success;
AccountReference= $aRef;
AuditDetails=$auditMessage;
Account= $account;
};
Write-Output $result | ConvertTo-Json -Depth 10;
Account Disable Example
$clientId = "<put your client id here>"
$clientSecret = "<put your client secret here>"
$redirectUri = "http://localhost/oauth2callback"
$refreshToken = "<put your refreshtoken here>"
#Initialize default properties
$success = $False;
$p = $person | ConvertFrom-Json
$aRef = $accountReference | ConvertFrom-Json;
$auditMessage = " not disabled successfully";
#Change mapping here
$account = [PSCustomObject]@{
suspended = $True
}
try{
if(-Not($dryRun -eq $True)){
### exchange the refresh token for an access token
$requestUri = "https://www.googleapis.com/oauth2/v4/token"
$refreshTokenParams = @{
client_id=$clientId;
client_secret=$clientSecret;
redirect_uri=$redirectUri;
refresh_token=$refreshToken;
grant_type="refresh_token"; # Fixed value
};
$response = Invoke-RestMethod -Method Post -Uri $requestUri -Body $refreshTokenParams -Verbose:$false
$accessToken = $response.access_token
#Add the authorization header to the request
$authorization = @{
Authorization = "Bearer $accesstoken";
'Content-Type' = "application/json";
Accept = "application/json";
}
$body = $account | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri "https://www.googleapis.com/admin/directory/v1/users/$aRef" -Method PUT -Headers $authorization -Body $body -Verbose:$false
}
$success = $True;
$auditMessage = " successfully";
}catch{
if(-Not($_.Exception.Response -eq $null)){
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$errResponse = $reader.ReadToEnd();
$auditMessage = " : ${errResponse}";
}else {
$auditMessage = " : General error";
}
}
#build up result
$result = [PSCustomObject]@{
Success= $success;
AccountReference= $aRef;
AuditDetails=$auditMessage;
Account= $account;
};
Write-Output $result | ConvertTo-Json -Depth 10;
Account Delete Example
$clientId = "<put your client id here>"
$clientSecret = "<put your client secret here>"
$redirectUri = "http://localhost/oauth2callback"
$refreshToken = "<put your refreshtoken here>"
#Initialize default properties
$success = $False;
$p = $person | ConvertFrom-Json
$aRef = $accountReference | ConvertFrom-Json;
$auditMessage = " not removed successfully";
try{
if(-Not($dryRun -eq $True)){
### exchange the refresh token for an access token
$requestUri = "https://www.googleapis.com/oauth2/v4/token"
$refreshTokenParams = @{
client_id=$clientId;
client_secret=$clientSecret;
redirect_uri=$redirectUri;
refresh_token=$refreshToken;
grant_type="refresh_token"; # Fixed value
};
$response = Invoke-RestMethod -Method Post -Uri $requestUri -Body $refreshTokenParams -Verbose:$false
$accessToken = $response.access_token
#Add the authorization header to the request
$authorization = @{
Authorization = "Bearer $accesstoken";
'Content-Type' = "application/json";
Accept = "application/json";
}
$body = $account | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri "https://www.googleapis.com/admin/directory/v1/users/$aRef" -Method DELETE -Headers $authorization -Body $body -Verbose:$false
}
$success = $True;
$auditMessage = " successfully";
}catch{
if(-Not($_.Exception.Response -eq $null)){
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$errResponse = $reader.ReadToEnd();
$auditMessage = " : ${errResponse}";
}else {
$auditMessage = " : General error";
}
}
#build up result
$result = [PSCustomObject]@{
Success= $success;
AccountReference= $aRef;
AuditDetails=$auditMessage;
Account= $account;
};
Write-Output $result | ConvertTo-Json -Depth 10;