Edit user signature, but can't use Oauth - google-apps-script

I'm tryng to edit the users signature via GAS.
I have found lots of examples and tutorials, and one of the Waqar Ahmad's answers looks very good - Email Settings APIs Authentication.
However, it doesn't work for me.
I don't really understand OAuth autorization, but couldn't find a tutorial for it.
With what should I replace anonymous?
oAuthConfig.setConsumerKey("anonymous");
oAuthConfig.setConsumerSecret("anonymous");
I go to https://console.developers.google.com/ create a project and use clientID for key and client secret for secret, is it right?
Adding more information:
This is the Waqar's code I'm using:
/*-----------------------------------------------------------------------------
This function will update the HTML signature of a user.
Input will be jason data
To disable signature, pass an empty string as signature value
sample parameter
ob = {user='hps', signature='<b>Regards</b><br>Waqar'}
To disable signature
ob = {user='hps', signature=''}
-----------------------------------------------------------------*/
function updateSignature(ob) {
//ob = {};
//ob.user = "hps";
//ob.signature = "<b>Regards</b><br>Waqar";
ob = {};
ob.user = "test#xxxx.it";
ob.signature = "<b>Regards</b><br>Waqar";
var base = 'https://apps-apis.google.com/a/feeds/emailsettings/2.0/';
var xmlRaw = '<?xml version="1.0" encoding="utf-8"?>'+
'<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:apps="http://schemas.google.com/apps/2006">'+
'<apps:property name="signature" value="'+htmlEncode(ob.signature)+'" />'+
'</atom:entry>';
var fetchArgs = googleOAuth_('emailSetting',base);
fetchArgs.method = 'PUT';
fetchArgs.payload = xmlRaw;
fetchArgs.contentType = 'application/atom+xml';
var domain = UserManager.getDomain();
var url = base+domain+'/'+ob.user+'/signature';
var urlFetch = UrlFetchApp.fetch(url, fetchArgs);
var status = urlFetch.getResponseCode();
return status;
}
//--------------------------------------------------------------------------
//This function will retreive Signature settings as json.
/*Sample returned object
{user=hps, signature=<b>Regards</b><br>Waqar}
*/
//-----------------------------------------------------------------
function retrieveSignature(user) {
var user = 'hps';
var base = 'https://apps-apis.google.com/a/feeds/emailsettings/2.0/';
var fetchArgs = googleOAuth_('emailSetting',base);
fetchArgs.method = 'GET';
var domain = UserManager.getDomain();
var url = base+domain+'/'+user+'/signature?alt=json';
var urlFetch = UrlFetchApp.fetch(url, fetchArgs);
var jsonString = urlFetch.getContentText();
var jsonArray = Utilities.jsonParse(jsonString).entry.apps$property;
var ob = {};
ob.user = user;
for(var i in jsonArray){
ob[jsonArray[i].name] = jsonArray[i].value;
}
return ob;
}
//Google oAuthConfig..
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.getAccessTokenUrl()
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey("xxxxxxxxxxxx.apps.googleusercontent.com");
oAuthConfig.setConsumerSecret("xxxxxxxx-xxxxxx-xxxxx");
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
//This function will escape '<' and '>' characters from a HTML string
function htmlEncode(str){
str = str.replace(/</g,'<');
return str.replace(/>/g,'>')
}
to get the oAuthConfig.setConsumerKey and oAuthConfig.setConsumerSecret I have created a new project in the google developer console, modified to on the Admin SDK API status, created a "Client ID for native application" and used the CLIENT ID in setConsuperKey, and CLIENT SECRET in setConsumerSecret.
Executing the script updateSignature the test#xxxx.it's signature should be changed,
I can see the box "autorization required" clik ok, and appear the request access box,
i click on "grant access" but nothing happes, and no error are shown.
Executing the same function in debug mode, i have the same boxes and a red box with "Errore OAuth" at the end.
I'm doing something wrong... please help me to find the mistake!!
Thanks again.
Marco

Finally i found the clue!!
Thank's to mike's quastions and answers
who let me discover This example
I Finally understand!!
in consumerkey you have to set your domain (p.e. "mydomain.it",
in consumerSecret you have to set the "Secret data of the customer to OAuth:" from admin google console->secority->advanced settings->Manage data OAuth key and secret for this domain.
I was confusing by the secret key in the google developer console, may be this answer can help

Related

Sign Ethereum transactions offline using Node-RED

I am trying to create a flow in Node-RED to sign for Etherem transactions (in this primary case, just messages) off-line and am struggling.
I have a Python code working fine (meaning doing well this off-line signing) and posting via an API but the Node-RED is not happy doing what I want (it returns a different signature than the one I get on the Web3.py and thus the EVM reverts the transaction).
Can anyone help? I tried several approaches, including the ones commented out, but none will match the signature generated at the Python code...
PS - the Python code implements it with signed_hash = self.web3.eth.account.signHash(hash, self._fetch_signer_key())
Thanks!
var Web3 = global.get('web3');
var web3 = new Web3();
var account = "0x9EfEe29e8fDf2cXXXXXXXde5502ABDf3f13ADac9a";
var privateKey = "0xbde16f62dadb43dad898e182e4e798baXXXXae46458d4939361d2494e11ce9e4";
var password = "12XXX8";
var message = "SMX1 10 1527596375";
var _hash = web3.utils.sha3(message);
//var signedObject = web3.eth.accounts.sign(_hash, privateKey);
var signedObject = web3.eth.accounts.sign(message, account);
//var signedObject = web3.eth.personal.sign(message, account, password);
//const signature = web3.eth.sign(message,account);
var msg = {};
msg.payload = {
//"message": message,
"message": signedObject.message,
"hash": _hash,
//"hash": signedObject.messageHash,
"signature": web3.utils.toHex(signedObject.signature),
//"signature": web3.eth.personal.sign(message, account, password),
"identity": identity,
};
/*
//msg.payload = signedObject.message;
msg.payload.message = signedObject.message;
msg.payload.hash = signedObject.messageHash;
msg.payload.signature = signedObject.signature;
msg.payload.identity = identity;
*/
//return signedObject.messageHash;
//return msg;
return signedObject;

Creating a group with Admin SDK Directory API in Google Apps Script doesn't work "On form submit"

I've read through all of the relevant pages in the Admin ADK Directory API documentation and several questions on stackoverflow, and I'm still stuck.
I am the super admin of my Google Apps domain, and I want users in my domain to be able to create their own Google Groups. I made a Google Form where the user specifies the name and email of the group. Then the Google Form Responses sheet has an "On form submit" trigger that invokes my code to create the group.
This code works when I run createGroupTest() from the Script Editor. It creates the group in my Google apps domain immediately.
This code does not work when the "On form submit" trigger runs the onFormSubmit(e) function. I get the email from the catch(e) saying Exception: Failed to authenticate for service: Groups.
Does anyone know what is causing the oauth authentication to work from within the Script Editor but not when invoked by the onFormSubmit function?
function onFormSubmitTest() {
var t = new Date();
t = t.getTime();
onFormSubmit([t, "AAA Test Group " + t], ["aaa.testgroup." + t + "#mydomain.com"], ["me#mydomain.com"]);
}
var consumerKey = "mydomain.com";
var consumerSecret = "xxxxxxxxxxxxxxxxxxxxxxxx";
var domainName = "mydomain.com";
function onFormSubmit(e) {
var timestamp = e.values[0];
var groupName = e.values[1];
var groupEmail = e.values[2];
var owner = e.values[3];
owner = owner.split("#")[0];
var description = 'test';
var requestBody = {email: groupEmail, name: groupName, description: description};
var scope = "https://www.googleapis.com/auth/admin.directory.group";
var fetchArgs = googleOAuth_("Groups", scope);
fetchArgs.method = "POST";
fetchArgs.contentType = "application/json";
fetchArgs.payload = JSON.stringify(requestBody);
fetchArgs.muteHttpExceptions = true;
var url = 'https://www.googleapis.com/admin/directory/v1/groups?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
UrlFetchApp.fetch(url, fetchArgs);
}
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name)
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey(consumerKey);
oAuthConfig.setConsumerSecret(consumerSecret);
return {oAuthServiceName:name, oAuthUseToken:'always'};
}
I figured it out: I had failed to include the domain extension in the groupEmail string (because my Google Form only asks the user to fill in the group email name without the domain extension).

muteHttpExceptions = true throws authentication failure

Using the Google Apps Email Settings API a delegate is deleted with the script below. If an error occurs, for example trying to delete delegates that do not exist, the following message is returned:
Exception: Request failed for returned code 400. Truncated server
response: <xml version="1.0" encoding="UTF-8"?>
<AppsForYourDomainErrors> <error errorCode="1303"
invalidInput="XXXX#XXXX.com" reason="E... (use muteHttpExceptions
option to examine full response)
However when using muteHttpExceptions = true the authentication fails:
Exception: Failed to authenticate for service: google
This forces me to use a try / catch structure instead of examining the HTTPResponse object. I would like to know why this is happening and how to solve it.
The test function:
function test() {
var consumerKey = 'XXXX';
var consumerSecret = 'XXXX';
var domain = 'XXXX.com';
var userName = 'XXXX'
var delegateName = 'XXXX#XXXX.com'
var serviceName = 'google';
var scope = 'https://apps-apis.google.com/a/feeds/emailsettings/2.0/';
var oAuthConfig = UrlFetchApp.addOAuthService(serviceName);
oAuthConfig.setRequestTokenUrl('https://www.google.com/accounts/OAuthGetRequestToken?scope=' + scope);
oAuthConfig.setAuthorizationUrl('https://www.google.com/accounts/OAuthAuthorizeToken');
oAuthConfig.setAccessTokenUrl('https://www.google.com/accounts/OAuthGetAccessToken');
oAuthConfig.setConsumerKey(consumerKey);
oAuthConfig.setConsumerSecret(consumerSecret);
var fetchParameters = {};
fetchParameters.oAuthServiceName = serviceName;
fetchParameters.oAuthUseToken = 'always';
fetchParameters.method = 'DELETE';
fetchParameters.muteHttpExceptions = false;
try {
var url = 'https://apps-apis.google.com/a/feeds/emailsettings/2.0/'+ domain + '/' + userName + '/delegation/' + delegateName;
var result = UrlFetchApp.fetch(url, fetchParameters);
} catch (e) {
Logger.log(e);
}
}
This question has been posted to the Google Apps Script issue tracker as ticket 3478 and acknowledged as a bug. The ticket remains open but the following workaround has been proposed:
Revoking access in your Google Account's Security settings to both www.google.com AND the source of Apps Script (spreadsheet etc).
Change the oAuthServiceName parameter to something else.
Re-running the script

Retrieve photo from Google Apps Profile API

I am trying to retrieve Google Apps Profile API photo using Google Apps Profile API but It keeps on prompting to authorize the request even after authorizing it.
Here is the code which I have tried so far.
function getPhoto(userName){
userName = 'user#myDomain.com'; //will be replaced by actual username
var scope = 'https://www.google.com/m8/feeds/profiles';
var fetchArgs = googleOAuth_('Profile', scope);
fetchArgs.method = 'GET';
var domain = UserManager.getDomain();
var url = 'https://www.google.com/m8/feeds/photos/profile/'+domain+'/'+userName+'?v=3';
var rawData = UrlFetchApp.fetch(url, fetchArgs).getContentText();
Logger.log(rawData);
}
//google oAuth
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey("anonymous");
oAuthConfig.setConsumerSecret("anonymous");
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
Refernces :
https://developers.google.com/google-apps/profiles/#photo_management
https://developers.google.com/google-apps/profiles/auth
Note : I have super administrator access to the domain I am trying
You could try with
var scope = 'https://www.google.com/m8/feeds/';
to authorize.
You can take a look at this Library. It lets you get the profile picture as a blob without any issue:
https://sites.google.com/site/scriptsexamples/new-connectors-to-google-services/profiles-services

To get user's profile information in google script

I want to get my domain's user's profile information..I am using profile API for this..
Profile API gives only a few fields like (Family Name, Given Name,Email etc)..But i also want to get these fields also:
occupation,department,Phone [Work], Phone [Mobile], Relation [Manager]...
i am not able to get these fields..So please give me suggestion to get these fields.
I got my all fields by Profile API.... Actually if any field is empty then Profile API doesn't give that field as an output.....
So using Profile API, we can get a user's full information....
Code :
var username="user "
var base = 'https://www.google.com/m8/feeds/';
var fetchArgs = googleOAuth_('contacts', base);
fetchArgs.method='GET'
var url=base+'profiles/domain/'+domainName+'/full/'+username+'?v=3&alt=json'
var name=""
var occupation=""
var department=""
var email=""
var contactNumber_1=""
var contactNumber_2=""
var relation=""
var account=""
var office=""
var personal_account=""
var current_account=""
var language=""
var blog=""
var image=""
try{
var urlFetch = UrlFetchApp.fetch(url, fetchArgs)
var json=Utilities.jsonParse(urlFetch.getContentText())
var profileInfo = json.entry
try{
name=profileInfo.gd$name.gd$fullName.$t
}catch(err){}
try{
occupation=profileInfo.gContact$occupation.$t
}catch(err){}
try{
department=profileInfo.gd$organization[0].gd$orgDepartment.$t
}catch(err){}
try{
var emaillist=profileInfo.gd$email
for(var i=0;i<emaillist.length;i++){
if(emaillist[i].rel.split("#")[1]=='work')
email=profileInfo.gd$email[i].address
}
}catch(err){}
try{
var phonelist=profileInfo.gd$phoneNumber
for(var i=0;i<phonelist.length;i++){
if(phonelist[i].rel.split("#")[1]=='work')
contactNumber_1=phonelist[i].$t
else if(phonelist[i].rel.split("#")[1]=='mobile')
contactNumber_2=phonelist[i].$t
}
}catch(err){}
try{
relation=profileInfo.gContact$relation[0].$t+" ["+profileInfo.gContact$relation[0].rel+"]"
}catch(err){}
}catch(err){}
}
/*
Oauth Authentication
*/
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey(consumerKey);
oAuthConfig.setConsumerSecret(consumerSecret);
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
If any field is empty then that tag will not be found thats why all the fields are written in try - catch block...
There isn't a built in API for that in Apps Script directly, but if you are using a Google Apps for Business or Education, you can use the Google Apps through UrlFetch and oAuth. That should expose any profile information that is stored in Google Apps.