I can connect to MS Graph to get a Bearer token using Powershell but not with a Web Acvtivity in ADFv2 using the same credentials.
I'm getting the TenantId, ApplicationId and ClientSecret from an existing App in Azure.
This is what I'm doing in Powershell - Works
# Authenticate to Microsoft Graph
Write-Host "Authenticating to Microsoft Graph via REST method"
$url = "https://login.microsoftonline.com/$tenantId/oauth2/token"
$resource = "https://graph.microsoft.com/"
$restbody = #{
grant_type = 'client_credentials'
client_id = $applicationID
client_secret = $clientSecret
resource = $resource
}
# Get the return Auth Token
$token = Invoke-RestMethod -Method POST -Uri $url -Body $restbody
Write-Host "Authenticated - token retrieved of type " $($token.token_type)
Result
This is the Web Activity - Fails
Input
{
"url": "https://login.microsoftonline.com/<tenantId>/oauth2/token",
"method": "POST",
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"body": "grant_type=client_credentials&client_id=\"<applId>\"&client_secret=\"<client_secret>\"&resource=\"https://graph.microsoft.com/\"",
"authentication": {
"type": "MSI",
"resource": "https://graph.microsoft.com/"
}
}
Error
Application with identifier '{appIdentifier}' was not found in the
directory '{tenantName}'. This can happen if the application has not
been installed by the administrator of the tenant or consented to by
any user in the tenant. You may have sent your authentication request
to the wrong tenant.
The error doesn't make sense as it works in powershell.
The difference here is that I'm executing the powershell with my own account and with a System Assigned MI in ADF. What permission am I missing? How do I troubleshoot this?
I tried to reproduce same thing in my environment got below results:
PowerShell with Bearer token :
To resolve the error .Please follow below steps:
Step1: Created AD application added permission as below:
Step2: Create a web activity to get the Access Token from ADF
URL: https://login.microsoftonline.com/<Tenant ID>/oauth2/token
Method : POST
Body: grant_type=client_credentials&client_id=<client_id>&client_secret=<client_secret>&resource=https://graph.microsoft.com/
Header: Content-Type:application/x-www-form-urlencoded
Step3: Create Set variable :
Add dynamic content -> #activity('Web1').output.access_token
Response
Related
I have an Azure App Registration setup as below:
Not shown: two redirect URIs for https://login.microsoftonline.com/common/oauth2/nativeclient (which I believe is needed for auth code flows if using PowerShell?) and https://MYDEVSERVER
We have a web API that can correctly access Graph against this App Registration by using a hybrid on-behalf-of flow and IConfidentialClientApplication, along with a bootstrap token provided by an Office add-in.
The creation of this App Registration is actually done by a PowerShell script, and I want to add a feature that will try to login as the script user to make a test Graph API call (against the /me endpoint) to make sure it is setup correctly. The script can ensure that the App Registration is granted admin consent for the Graph API permissions so the script user does not have to provide consent.
From what I understand, the authorization code flow can be used to test these delegated permissions. However, I've tried two approaches with different results as below using the MSAL module to get the token and then use that token in the authorization header for a Graph call to simply return details about the logged in user via the /me endpoint:
If I don't pass a client secret to the Get-MsalToken cmdlet, I do get a login prompt but Get-MsalToken always returns the error 'AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'
If I do provide a client_secret, I do NOT get the login prompt and can successfully get a token, but the Graph call fails saying that the /me request is only valid with delegated authentication flow. Which makes sense because we need a user context.
So I'm stuck - I can't use the user context with the interactive login without it expecting a client secret that if I do use is using a different flow that's not supporting delegated permissions. What am I doing wrong? Or do I need to use a completely different authentication flow?
Does the fact that the App Registration is designed to handle SSO with Office web add-ins have anything to do with it? Meaning, I have a scope (e.g. api://MYWEBSERVER/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/access_as_user, as used by the add-in manifests for purposes of issuing a bootstrap token from the Office JS library to our Web API) and a list of authorized client applications (Office apps) in the 'Expose an API' section. I'm wondering if only those applications are authorized, and not the PowerShell script...
I've also seen some suggestions about using the device code flow and I'm wondering if I'm missing a step to get a refresh token (as demonstrated here but I can't get that example to work either using a client secret (I can't figure out the proper Get-MsalToken parameter combination).
$graphEndPointUrl = "https://graph.microsoft.com/v1.0/me"
$connectionDetails = #{
'TenantId' = $tenantId #Set variable to your own value
'ClientId' = $clientId #Set variable to your own value
'Scopes' = 'https://graph.microsoft.com/.default'
}
#Using the above information, it throws this error on Invoke-RestMethod:
#ERROR: "{"error":"invalid_client","error_description":"AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
#"error_codes":[7000218]
#"error_uri":"https://login.microsoftonline.com/error?code=7000218"}"
$connectionDetails = #{
'TenantId' = $tenantId #Set variable to your own value
'ClientId' = $clientId #Set variable to your own value
'ClientSecret' = $clientSecret | ConvertTo-SecureString -AsPlainText -Force #Set $clientSecret variable to your own value
'Scopes' = 'https://graph.microsoft.com/.default'
}
#Using the above information, it throws this error on Invoke-RestMethod:
#ERROR: "{"error":{"code":"BadRequest","message":"/me request is only valid with delegated authentication flow."
Import-Module MSAL.PS
try {
$myAccessToken = Get-MsalToken #connectionDetails
Write-Host $myAccessToken.AccessToken
$authHeader = #{
'Authorization' = $myAccessToken.CreateAuthorizationHeader()
}
$response = Invoke-RestMethod -Uri $graphEndPointUrl -Headers $authHeader
#Error thrown below
if ($null -eq $response) {
Write-Error "An unexpected error occurred making a test Graph API call to the $($graphEndPointUrl) endpoint" -ForegroundColor Red
}
else {
Write-Host "The test Graph API call to the $($graphEndPointUrl) endpoint was successful!"
}
}
catch {
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$responseBody = $reader.ReadToEnd();
$errorObj = ConvertFrom-Json -InputObject $responseBody
Write-Host "An unexpected error occurred making a test Graph API call to the $($graphEndPointUrl) endpoint: $($errorObj.error.message)"
}
Update
Everything you need I believe is written in this Microsoft article - https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
I noticed a key difference in the tutorial you referenced and your setup, thats the ID Token that is used with the hybrid setup, you can read more about it in the MS guide, check response_mode .
So principal goes as follow > You get an authorization code > use that code to generate your access and refresh tokens > then you can use different API calls with the Access token in the header.
As for your code, here are the things that are missing or are not correctly implemented.
You are missing the RedirectUri param. Make sure the URL is exact I have just put https://localhost as an example.
$connectionDetails = #{
'TenantId' = $tenantId #Set variable to your own value
'ClientId' = $clientId #Set variable to your own value
'ClientSecret' = $clientSecret | ConvertTo-SecureString -AsPlainText -Force #Set $clientSecret variable to your own value
'Scopes' = 'https://graph.microsoft.com/.default'
'RedirectUri' = 'https://localhost'
}
Your header is not implementing the Authorization properly. Check out the example from the tutorial
$myAuthMethods = (Invoke-RestMethod -Headers #{Authorization = "Bearer $($myAccessToken.AccessToken)" } `
-Uri "https://graph.microsoft.com/beta/me/authentication/methods" `
-Method Get).value
$myAuthMethods
The header have the following structure, where the word Bearer is before the token.
$header = #{
"Authorization" = "Bearer $($myAccessToken.AccessToken)"
}
Make sure you have the access token $myAccessToken.AccessToken in the header.
At that point, you should at least get a different error if request does not proceed.
The issue is that an additional "Mobile and desktop applications" platform needs to be added to the App Registration on the Authentication page (with "https://login.microsoftonline.com/common/oauth2/nativeclient" as a Redirect URI), as it only has a web platform currently. Then Get-MsalToken works without a client Id:
$myAccessToken = Get-MsalToken -ClientId $clientID -TenantId $tenantId -Interactive -Scopes 'https://graph.microsoft.com/.default' -RedirectUri 'https://login.microsoftonline.com/common/oauth2/nativeclient'
However, an additional request is needed to get a refresh token and use that for the Graph call:
$myAccessToken = Get-MsalToken -ClientId $clientID -TenantId $tenantId -Silent
When using Azure Devops functions such as creating a new Repo or starting a pipeline is there any way to authenticate the user without an Access token through Powershell? The only other solution that I found is Azure CLI though I would prefer to Invoke the web API calls.
Actually, indeed you can auth the Azure DevOps REST API without using a PAT(personal access token), but you could not auth it without any access token. Even if you use the user account to auth, essentially it will generate an access token to auth.
For your requirement, if you want to use powershell to auth the REST API, you could use the script below.
Make sure you have installed the Az powershell module, and login with a user account which has the permission in your devops org via Connect-AzAccount.
Here is a sample to start the pipeline with Runs - Run Pipeline. This sample uses the Azure AD access token to auth, please note don't change the 499b84ac-1321-427f-aa17-267ca6975798 in the script, it is the well-known resource id of the DevOps REST API, it works for me.
$token = (Get-AzAccessToken -ResourceUrl "499b84ac-1321-427f-aa17-267ca6975798").Token
$URL = 'https://dev.azure.com/orgname/testpro1/_apis/pipelines/52/runs?api-version=6.0-preview.1'
$header = #{
'Authorization' = 'Bearer ' + $token
'Content-Type' = 'application/json'
}
$body = #"
{
"resources": {
"repositories": {
"self": {
"refName": "refs/heads/main"
}
}
}
}
"#
Invoke-RestMethod -Method Post -Uri $URL -Headers $header -Body $body | ConvertTo-Json
Working scenario
I have an Azure web application (https://www.contoso.com) to which I want to authenticate against and perform web call on.
I want to authenticate myself using Connect-AzAccount and make calls to it using my own identity.
I use the following code with success to obtain a valid token and call the application.
#Authenticate as myself or a sevice principal
Connect-AzAccount -Tenant 'a736bac3-c259-450f-90a4-f7d5bd7c4c78'
# App registration ID for Contoso
$ResourceUri = '24114488-8c26-4e87-8f71-90de62f5a8aa'
$Context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $ResourceUri).AccessToken
$Headers = #{Headers = #{Authorization = "Bearer $token" } }
Invoke-RestMethod -Method Get -uri 'https://Contoso.com/module/Something' #Headers
That being said, the application itself does not implement forced user & groups assignment.
Instead, everybody can connect to it (by design).
The problematic
The solution presented above requires me to add Powershell Azure (1950a258-227b-4e31-a9cf-717495945fc2) in the list of Authorized client application to enable this scenario. By doing this operation, anybody in my directory can now technically make calls to the website, which is not desired.
Desired Scenario
Because user assignment is not enforced, I removed the Powershell Azure client from the main app and instead created a second App Registration for which I authorized the PS AZ client and added an API permission so it had access to the main App. The idea is that I can require user assignement for the second app registration and therefore limit the user that can make these kind of calls.
Initial (working) flow:
Connect-AzAccount authenticate the user
Code sample above is ran to obtain the token and call the app.
Desired flow
Connect-AzAccount authenticate the user
User connect through the client app registraion (new app) that has api permission to the main app.
User make calls to the main app.
Now, if I try to use my initial code sample with the Application Id of the second registration acting as a client ID, I get the following error
Invoke-RestMethod : {"code":401,"message":"IDX10214: Audience validation failed. Audiences: '[PII is hidden]'. Did not
match: validationParameters.ValidAudience: '[PII is hidden]' or validationParameters.ValidAudiences: '[PII is hidden]'."}
At line:1 char:12
+ $result2 = Invoke-RestMethod -Method Get -uri 'https://Contoso.com/so...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExcept
ion
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
I believe that this is because I am obtaining a token for the second app registration and trying to call the main app URL, which is not authorized through the token.
A "working" alternative to this problem would be to connect using Client_credentials as grant_type such as this:
function get-Bearer([string]$TenantID, [string]$ClientID, [string]$ClientSecret) {
$TokenEndpoint = "https://login.windows.net/{0}/oauth2/token" -f $TenantID
$Body = #{
'resource' = '24114488-8c26-4e87-8f71-90de62f5a8aa'
'client_id' = $ClientID
'grant_type' = 'client_credentials'
'client_secret' = $ClientSecret
}
$params = #{
ContentType = 'application/x-www-form-urlencoded'
Headers = #{'accept' = 'application/json' }
Body = $Body
Method = 'Post'
URI = $TokenEndpoint
}
$token = Invoke-RestMethod #params
Return "Bearer " + ($token.access_token).ToString()
}
If I do that, even though I can make calls to the main app. again but it is connected with the actual client app. and not using the user identity obtained through Connect-AzAccount (for which tokens can be generated through the initial sample)
I was also able to make it work with a password grant_type but this is not making use of my bearer token and is also invalidated by MFA enabled users.
All insights are welcome.
References
Microsoft Identity platform documentation - v2-oauth2-on-behalf-of-flow
(digging around the application flow to try and get something working)
Application app ids, not object ids, should be used as resources identifiers. Keep getting tokens using the first application (24114488-8c26-4e87-8f71-90de62f5a8aa) as resource/audience (using its application id uri) and the second application as client. Connect-Az will be out of the equation.
#Install the ADAL.PS package if it's not installed.
if(!(Get-Package adal.ps)) { Install-Package -Name adal.ps }
$authority = "https://login.windows.net/common/oauth2/authorize"
#this is the security and compliance center endpoint
$resourceUrl = "{first application id uri}"
#replace <redirect-uri>, with the Redirect URI from your Azure AD application registration.
$clientId = "{second application app id}"
$redirectUri = "<redirect-uri>"
$response = Get-ADALToken -Resource $resourceUrl -ClientId $clientId -RedirectUri $redirectUri -Authority $authority -PromptBehavior:Always
$response.AccessToken | clip
I finally succeeded in my attempt.
In case my initial question was confusing, I "simply" wanted to connect as myself on Web API B using an intermediary Web API A
The reason was that I could not implement control access on Web API B (it is a requirement that it is available for all users of the tenant) and I also could not add Powershell client ID to Web API B directly as this would have allowed everyone to obtain a token and make call to Web API B using Powershell.
Therefore, I needed the intermediary Web API A to allow Powershell client ID and provide a controlled / limited user access to Web API B
There is a flow in the Microsoft identity platform and Oauth 2.0 called On-Behal-Of flow which allow exactly that scenario.
Prerequisites
App Registration for Web API B
API Permission: Delegated permission to User.Read (Graph API)
Expose an API: add a User_Impersonation scope and the Application ID of Web API A in the authorized client ID
App Registration for Web API A
In Api Permissions, add the User_Impersonation scope of Web API B
From there, the following code will get you connected
Connect-AzAccount -TenantId '584e32bc-214f-4046-89e5-79b7bac9ae75'
$Params = #{
ClientId = '6788d279-fb83-4962-b371-445479875e0e'
ClientSecret = '16cc0f3d88cb4dd189fe6bf8e845982d'
resourceId = 'aeefa559-cb1c-41eb-ac5d-0bcb0bc01eaf'
Scope = 'https://graph.microsoft.com/user.read+offline_access'
}
function Get-AzCustomTokenOnBehalOf {
[CmdletBinding()]
param (
$ClientId,
$ClientSecret,
#Application ID of the target resource
$ResourceId,
$Scope
)
# Get Token For WebApp A $TenantId
$Context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$IntermediaryToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, $ClientId).AccessToken
$TokenUri = "https://login.microsoftonline.com/$($Context.Tenant.Id)/oauth2/token"
$FinalToken = Invoke-RestMethod -Uri $TokenUri -Method Post -Body #{
grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
resource = $ResourceId
client_id = $ClientId
client_secret = $ClientSecret
assertion = $IntermediaryToken
scope = $Scope
requested_token_use = 'on_behalf_of'
}
return $FinalToken
}
$Token = Get-AzCustomTokenOnBehalOf #Params
$Headers = #{Headers = #{Authorization = "bearer $($Token.access_token)" } }
$MYsite = Invoke-RestMethod -Method Get -uri 'https://SomeWebsite.com/' #Headers
Additional considerations
This scenario do require a client secret (This is the one I demonstratedO or a client certificate in order to work.
It is also subject to some limitations defined in the reference documentation and might not be suitable to all scenarios.
References:
Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow
want to use the Graph API to create a folder in a user's mailbox that exists in Exchange Online.
As a result of the investigation, if I use "https://graph.microsoft.com/v1.0/users/testuser01#domain.com/mailFolders", I feel that it is possible, but an error is displayed and I cannot create it.
Currently, "Exchange> Mail.ReadWrite, MailboxSettings.ReadWrite" is assigned to the execution user (admin).
However, it says "Access is denied. Check credentials and try again." Is the permission wrong?
Or is the specified URL incorrect?
Sorry to trouble you, but thank you for your response.
【Append】
$body = #{
grant_type="client_credentials"
resource=$resource
client_id=$ClientID
client_secret=$ClientSecret
}
`#Get Token
$oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$TenantName/oauth2/token -Body $body
API Permissions
You are using the client credential flow to get the token to call Microsoft Graph - Create MailFolder, so you need to add the Application permission Mail.ReadWrite of Micrsoft Graph to your AD App.
1.Add the Application permission Mail.ReadWrite like below.
2.Click the Grant admin consent for xxx button, and make sure the $resource in your request is https://graph.microsoft.com.
Update:
Here is a powershell sample to call Create MailFolder API to create MailFolder.
$uri = "https://graph.microsoft.com/v1.0/users/joyw#xxxxx.onmicrosoft.com/mailFolders"
$headers = #{
'Content-Type' = 'application/json'
'Authorization' = 'Bearer <access-token-here>'
}
$body = ConvertTo-Json #{
"displayName" = "testfolder1"
}
Invoke-RestMethod -Method Post -Uri $uri -Headers $headers -Body $body
Check the result in the Graph Explorer with List mailFolders:
I have a Powershell script that calls a Google App Script function.
When I run the Powershell script I can see the following error on the Error Reporting on my GCP project:
Exception: You do not have permission to call SpreadsheetApp.getActiveSpreadsheet. Required permissions: (https://www.googleapis.com/auth/spreadsheets.currentonly || https://www.googleapis.com/auth/spreadsheets)
at toSpreadsheet (Código:3)
at fromPS (Código:14)
I have understood that I have to authorize the scope, so I've been trying to do that by editing the manifest file.
The Authorization Scopes Documentation says,
"During the authorization flow, Apps Script presents human-readable descriptions of the required scopes to the user. For example, if your script needs read-only access to your spreadsheets, the manifest may have the scope https://www.googleapis.com/auth/spreadsheets.readonly. During the authorization flow, a script with this scope asks the user to allow this application to "View your Google Spreadsheets"."
In my case I edited the manifest file appscript.json to add the scope https://www.googleapis.com/auth/spreadsheets, then I saved it, published the Google App Script project as API Executable, and finally I run the Powershell code again, but I still get the same error as above. During all this flow, I was not asked to allow anything. I cannot understand what is missing authorizing the script have the required permission.
I also added the spreadsheets scope to OAuth consent screen, but it seems to do not make any difference. I am suspecting I should use a Service Account to accomplish that since I see no way to go through a OAuth Client Verification since my script on Google is called from Powershell script. I dont want to believe on that because getting to know how config OAuth2 took me a lot of time :(
A few considerations:
The function that the run method calls by Powershell just works fine when I run it directly from Google Script Editor.
The script project is deployd as an API executable
Google Apps Script API is enabled in the GCP project
It is associated to a Standard GCP project
The OAuth credential is Web Application type
The script for writing and reading values from Powershell to Google Sheets works fine
Google script:
function toSpreadsheet(text2write)
{
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("HIL_APP");
var LastRow = sheet.getLastRow();
for (var i = 1; i < LastRow; i++)
{
sheet.getRange(i+1, 8, 1).setValue(text2write)
}
return "myreturn"
}
function fromPS(params)
{
Logger.log(params)
var rtn = toSpreadsheet(params)
return rtn
}
manifest file:
{
"oauthScopes": [
"https://www.googleapis.com/auth/spreadsheets"
],
"timeZone": "America/Argentina/Buenos_Aires",
"dependencies": {
},
"webapp": {
"access": "ANYONE",
"executeAs": "USER_DEPLOYING"
},
"exceptionLogging": "STACKDRIVER",
"executionApi": {
"access": "MYSELF"
},
"runtimeVersion": "V8"
}
Powershell code:
function doit{
$json = ".\client_id.json"
$jdata = get-content $json | convertfrom-json
<#
$jdata | ForEach-Object {
$_.PSObject.Properties.Value
}
#>
$ClientID = $jdata.web.client_id.ToString()
$ClientSecret = $jdata.web.client_secret.ToString()
$refreshToken = "1//04VvG_FTyDGhiCgYIARAAGAQSNwF-L9IrZ-o1kaZQQccvzL5m4TUTNz6b9Q4KCb16t4cH11gGCshWZWvgaCoMlg73FgpLAGOYTEk"
$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
$headers = #{"Authorization" = "Bearer $accessToken"
"Content-type" = "application/json"}
$spreadsheetId = "1htbeGlqZ4hojQBWl9fxE4nW_KZI9uVwi0ApzNOIbwnY"
$currentDate = (Get-Date).ToString('MM/dd/yyyy')
$currentTime = (Get-Date).ToString('HH:mm:sstt')
$json = #”
{
"range": "HIL_APP!A1:G1",
"majorDimension": "ROWS",
"values":
[[
"HIL_NAME",
"$env:ComputerName",
"$currentDate",
"$currentTime",
"$env:UserName",
"input from user",
"attempt"
],]
}
“#
$write = Invoke-WebRequest -Uri "https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/HIL_APP!A1:G1:append?valueInputOption=USER_ENTERED" -Method Post -ContentType "application/json" -Body $json -Headers #{"Authorization"="Bearer $accessToken"}
$read = Invoke-WebRequest -Uri "https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/HIL_APP!A1:G1" -Headers #{"Authorization"="Bearer $accessToken"}
$read
Write-Output "read: " ($read.Content | ConvertFrom-Json)
$scriptId = "1eF7ZaHH-pw2-AjnRVhOgnDxBUpfr0wALk1dVFg7B220bg_KuwVudbALh"
$json = #"
{
"function": "fromPS",
"parameters": ["myparam"],
"devMode": true
}
"#
$resp = Invoke-WebRequest -Uri "https://script.googleapis.com/v1/scripts/${scriptId}:run" -Method Post -ContentType "application/json" -Body $json -Headers #{"Authorization"="Bearer $accessToken"}
$resp
Write-Output "script response: " ($resp.Content | ConvertFrom-Json)
}
$error.Clear()
clear
doit
In order to run the function of Google Apps Script (GAS) using Apps Script API, it is required to do a bit complicated settings. In this case, I would like to propose for testing to run the GAS function as follows. This flow might be too careful.
Flow:
Link the Cloud Platform Project to Google Apps Script Project. Ref
Install for running the GAS function with the scripts.run method in Apps Script API. Ref
Put the script you want to run to the script editor of Google Apps Script.
Here, please run the function by the script editor and confirm whether the script works. By this, the issue of the script can be avoided.
Put the following script for testing to run. This is used for 1st test of Apps Script API.
function test() {
return "ok";
}
Put a following sample script for retrieving the access token. This is used for testing it. Please run this at the script editor, and copy the returned access token.
function getToken() {
Logger.log(ScriptApp.getOAuthToken());
}
Test to run the GAS function of test() using the retrieved access token. In this case, the script of powershell is used by replacing $accessToken = $GAuthResponse.access_token.
When an error occurs, please confirm the settings of Apps Script API. In this case, it can be said that the GAS script is correct.
When no error occurs, please test to run the function you want to run. In this case, the required scopes have already been included in the access token. By this, the issue of scopes can be avoided.
When above test is done and your script for using Apps Script API works, please retrieve the refresh token using the scopes. The scopes can be seen at the script editor. By this, the valid access token can be retrieved by the refresh token. And your script can be used at the local PC.
References:
Linking Cloud Platform Project to Google Apps Script Project
Executing Functions using the Apps Script API