I'm trying to call StackExchange's API, using Google Apps Script and Google Sheets. I can't figure out where in the OAuth process things are going wrong. My current code is not granting access:
function getStackExchangeService_() {
var CLIENT_ID = PropertiesService.getScriptProperties().getProperty('SE_CLIENT_ID');
var CLIENT_SECRET = PropertiesService.getScriptProperties().getProperty('SE_CLIENT_SECRET');
return OAuth2.createService('StackExchange')
.setAuthorizationBaseUrl('https://stackoverflow.com/oauth')
.setTokenUrl('https://stackoverflow.com/oauth/access_token')
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
.setRedirectUri('https://stackexchange.com/oauth/login_success')
.setScope('global');
}
When I call this and log the response I always get "false":
var service = getStackExchangeService_();
Logger.log(service.hasAccess());
Thanks for the help!
The most obvious issue is that global is not a valid Stack Exchange scope.
Probably use .setScope('read_inbox'); to start.
Also, be sure that:
You have registered your app and configured it for explicit (server-side) OAuth2. (Omit the port information in your case.)
Apparently you should use https://script.google.com/macros/d/{SCRIPT ID}/usercallback for the Application Website, per these instructions??.
Which means you would use script.google.com for the OAuth Domain.
Related
I'm using the https://github.com/googleworkspace/apps-script-oauth2 library in a Google Sheet script to call an external API. It works well for the owner of the sheet. For all other users it fails in creating the service/property store? It fails the "Service.hasAccess()" condition.
I suspect I am missing some sort of permissions somewhere. I have given users Edit permissions on the Sheet and have gone through other various gyrations trying to figure this out. I decided to apply this script via a Standard Project.
Scope are applied explicitly in the manifest and all works swimmingly for the sheet owner.
''''''''Google Apps Script, Spreadsheet Script in GCP Standard Project
function authorizeUser() {
var myService = getMyService();
if (myService.hasAccess()) {
>FAILS THIS CONDITION for all except spreadsheet owner
}
}
function getMyService() {
return OAuth2.createService('sky')
.setAuthorizationBaseUrl('https://oauth2../authorization')
.setTokenUrl('https://oauth2.../token')
.setClientId('fee......')
.setClientSecret('Ighh.....')
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
//.setScope('https://www.googleapis.com/auth/drive')
// Below are Google-specific OAuth2 parameters.
.setParam('login_hint', Session.getEffectiveUser().getEmail())
}
>I believe the failure is occurring in OAuth2.gs here
function createService(serviceName) {
return new Service_(serviceName);
}
OAuth2.gs: https://github.com/googleworkspace/apps-script-oauth2/tree/master/dist
Any thoughts?
D M
Apparently the suggested code to validate the service state in the apps-script-oauth2 library is not indicative of whether or not the Oauth process can be completed.
Direct the user to the authorization URL
Apps Script UI's are not allowed to redirect the user's window to a new URL, so you'll >need to present the authorization URL as a link for the user to click. The URL is >generated by the service, using the function getAuthorizationUrl().
function showSidebar() {
var driveService = getDriveService();
if (!driveService.hasAccess()) {
I was able to complete my Oauth process regardless of the state returned by has.Access() . I'm not sure if this is a time sensitive operation or something else is at play. At any rate I was able to proceed and develop a final solution as a GAS web app.
We're using Gsuite Enterprise/Piazzaweb at work. I'm using basic scripts to get information from my own mailbox, no problems there. But I want to pull information from a couple of shared mailboxes in which I'm delegated. For example billing#mycompany.com. But I can't find any information regarding this and if it's even possible to reach a delegated mailbox with App script.
I've been sending e-mails from the delegated mailbox with app script without any problem.
Hopefully somebody can tell me more about this.
Thanks in advance.
In order to use Service Accounts in Apps Script, you have to do the following:
Build the OAuth service for your Service Account with the following library: OAuth2 for Apps Script.
Call the corresponding API by making the corresponding HTTP request via UrlFetchApp.fetch(url, params).
1. Build the OAuth service:
Once you have added the specified library to your script, you have to do this in order to build the OAuth service with delegated credentials, :
const PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n';
const CLIENT_EMAIL = 'xxxxxxxxxxxxxxxxxxxxx.iam.gserviceaccount.com'; // Service account email
const USER_EMAIL = 'email_address_to_impersonate'; // Account to impersonate
const SCOPE = 'https://www.googleapis.com/auth/gmail.readonly' // Change according to your preferences
function getGmailService() {
return OAuth2.createService('Gmail: ' + USER_EMAIL)
.setTokenUrl('https://oauth2.googleapis.com/token')
.setPrivateKey(PRIVATE_KEY)
.setIssuer(CLIENT_EMAIL)
.setSubject(USER_EMAIL)
.setPropertyStore(PropertiesService.getScriptProperties())
.setScope(SCOPE);
}
Where PRIVATE_KEY refers to the key found in the Service Account JSON credentials, CLIENT_EMAIL is the Service Account email, and USER_EMAIL refers to the email address whose INBOX you want to access.
It's important to note that SCOPE should be one of the scopes you specified when delegating authority.
2. Access the API:
Once the OAuth service is built, you use it to retrieve an access token with which you can access the desired resource. Of course, GmailApp service and the Advanced Gmail Service won't be of use here, since you have to access the API using the service you just built. Because of this, the way to access the API will be making the corresponding HTTP request via UrlFetch.
I'm not sure what you want to do exactly, and the exact request would depend on that, but for example, if you wanted to list the messages from the impersonated user, you could do this:
function readInbox() {
var service = getGmailService();
console.log(service.getAccessToken());
if (service.hasAccess()) {
var url = 'https://www.googleapis.com/gmail/v1/users/me/messages';
var response = UrlFetchApp.fetch(url, {
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
console.log(JSON.stringify(result, null, 2));
}
}
Note:
I'm assuming here that you have already created a Service Account and granted domain-wide authority, and that your issue was just using it in Apps Script.
In Gmail API Reference, check the HTTP request, Parameters and Request body sections corresponding to the API method you want to use, if you need information on how to make the HTTP request (URL to access, HTTP method, request parameters, etc.).
Reference:
OAuth2 for Apps Script
Apps Script OAuth2 > GoogleServiceAccount.gs
You cant use delegation from apps script as apps script doesn't support using service accounts. You would need to make an oauth2 flow and have that user authorize it. Answer provided by #Zig Mandel
On top of what #ZigMandel said: unless this is a google domains or google for work account to my knowledge you cant use service accounts with gmail. you need to use Oauth2. Answer provided by #DalmTo
I don't know if this would solve the problem, but a feature request has been placed on Google Cloud Community and on Google Issue Tracker to enable access to Gmail Apps Script add-ons from delegated mailboxes.
The more upvotes, the more chances Google seriously looks at this issue ;).
i want to get an authorized token for my App Script Application for YouTube Analytics.. Currently i am using cGoa Library to get an Authorized token which requires authentication once as provided in this link .. But for security purpose, we don't want to use external script like the so called cGoa Library. Please i need to know any other ways to acquires Oauth2 access token for YouTube Analytics in Google App Script. Our major objective id to have the token once and for all future uses because we want to automatically run the script on a daily basis. So we need something that will works all time without require more authentication. Currently this is the code i use to get token with cGoa Llibrary.
function oneOffScript() {
var options = {
packageName: 'youtube-analytics', // user defined
clientId: '942097727718-t663ep631aqhd75610g4etpcn3foj827.apps.googleusercontent.com',
clientSecret:'Ng_9HJ34hKSPesvRA6hb85KR',
// following method to add Google scopes. Here we are mixing YouTube Data and Analytics (prefixed yt-)
// in the same service allowing calls to both APIs with the same token (we can do this because both are Google APIs)
// More on mixing services http://ramblings.mcpher.com/Home/excelquirks/goa/mutipleconsent
scopes : cGoa.GoaApp.scopesGoogleExpand (['youtube',
'youtube.force-ssl',
"youtubepartner",
"youtubepartner-channel-audit",
"yt-analytics-monetary.readonly",
"yt-analytics.readonly"]),
service:'google' // always this for Google APIs. Ref: http://ramblings.mcpher.com/Home/excelquirks/goa/services
};
// store one off in user properties
cGoa.GoaApp.setPackage(PropertiesService.getUserProperties(), options);
}
function doGet(e) {
var goa = cGoa.GoaApp.createGoa ('youtube-analytics',
PropertiesService.getUserProperties()).execute (e);
if (goa.needsConsent()) {
return goa.getConsent();
}
Please your response is highly appreciated. Thanks
Currently my code only modifies my signature, because when I put the email of the other person in my domain, the error: Not Found (line 9, file "Code") appears.
My current code:
function myFunction() {
var newSignature = Gmail.newSendAs();
newSignature.signature = "signature";
var listEmails = [
"leticia#domain.com"]
var updateSignature = Gmail.Users.Settings.SendAs.update(newSignature, "me", listEmails)
}
I am developing using APPS SCRIPT.
Any suggestions for me to be able to change the signature of someone else in my domain?
To change other people Gmail settings in your domain you'll need to be a domain Admin, then create a service account with domain-wide authority, then whitelist it in the Admin Console. Then use said service account and authentication token generated to authenticate your requests to the Gmail API.
This built-in Apps Script Gmail integration was not made for that use-case. The intended usage is to setup your own settings, or individual users that explicitly authorize your application to run on their behalf. This sendAs is there because one might have multiple Gmail signatures, depending on their selected send-as/from alias.
Note that simply authorizing an script with your GSuite admin account won't allow to the script to perform domain-wide operations. That'd be too dangerous, therefore the somewhat convoluted service-account setup is required.
Link to the relevant documentation
I've been working to solve this issue for months and it is just getting worse.
I have a simple program in Google Apps script that grabs email addresses from a sheet and puts them in the appropriate Google Contacts group. It was working fine up until a month or so ago when it stopped working.
Please help me:
1) Understand If I really need to work with API's to do what I'm doing.
2) Check my work below for something I might be missing.
Original Problem:
When I run this code i get the error: "You do not have permission to perform that action."
function testAddEmail(){
ContactsApp.createContact(null, null, "tomfoolery#validemailaddress.com");
};
To resolve this issues I've:
-Made sure Contacts API is enabled in my Cloud Console.
-Disabled and reinabled it multiple times.
-Created a new file with the program and enabled new Contacts API.
-Created Credentials for the new program (It worked for one day after this).
-Contacted Google Cloud Support and G Suite Support to make sure settings are correct (they don't support script or contacts.)
Problem 2:
I've tried to add the Oauth 2 code but now it gives me the error "You do not have permission to call getActiveSpreadsheet."
Are their problems in my Oauth 2 code below? (I removed my personal info.)
function getContactsService() {
// Create a new service with the given name. The name will be used when
// persisting the authorized token, so ensure it is unique within the
// scope of the property store.
return OAuth2.createService('contacts')
// Set the endpoint URLs, which are the same for all Google services.
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
// Set the client ID and secret, from the Google Developers Console.
.setClientId('blablabla.apps.googleusercontent.com')
.setClientSecret('blablabla')
// Set the name of the callback function in the script referenced
// above that should be invoked to complete the OAuth flow.
.setCallbackFunction('authCallback')
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getUserProperties())
// Set the scopes to request (space-separated for Google services).
.setScope('https://www.google.com/m8/feeds')
.setScope('https://www.googleapis.com/auth/spreadsheets')
// Below are Google-specific OAuth2 parameters.
// Sets the login hint, which will prevent the account chooser screen
// from being shown to users logged in with multiple accounts.
.setParam('login_hint', Session.getActiveUser().getEmail())
// Requests offline access.
.setParam('access_type', 'offline')
// Forces the approval prompt every time. This is useful for testing,
// but not desirable in a production application.
.setParam('approval_prompt', 'force');
}
Are you logged into multiple Google accounts? That often causes issues with authorization. Try logging out of everything and logging back in to just one account.
Is this running on a trigger or are you manually running the formulas?
Are the owner of the spreadsheet and logged in as the owner? Are you running this test in the spreadsheet's container-bound script?
If you're the owner of the spreadsheet and you're just adding the email addresses from your own spreadsheet to your own Gmail account then there's no reason you need to use the API or OAuth protocol.
As another commenter mentioned, what are the scopes you're requesting? To just set up a simple script from your spreadsheet to add contacts you probably just need the two you listed. You can set them manually by selecting view-->show manifest file. For example:
{
"timeZone": "America/New_York",
"dependencies": {
},
"oauthScopes": [
"https://www.googleapis.com/auth/script.container.ui",
"https://www.googleapis.com/auth/spreadsheets"
]
}