Google App Script: Authentication failing on UrlFetchApp.Fetch() - javascript

My code:
var username = "";
var password = "";
var options = {};
options.headers = {
"Authorization": "Basic " + Utilities.base64Encode(username + ":" + password)
};
var html = UrlFetchApp.fetch("https://www.4for4.com/fantasy-football/full-impact/cheatsheet/Flex/38351/ff_nflstats/adp_blend", options).getContentText();
Logger.log(html);
I read through a few posts like this one but still having trouble getting the data I need. The result is HTML from the redirected login page. Is it possible this site uses a different Authorization type or do I need to pass something else in the header?

Related

How to fix "Exception: Limit Exceeded" error when trying to upload an image to Graph API using Google Apps Script?

I am using Facebook Graph API to create a Facebook ads campaign with Google Apps Script.
I need to upload an image to my Facebook ad account. I have already tried to use the image bytes as a Base64 UTF-8 string, but when I call the API I get:
Exception: Limit Exceeded: URLFetch URL Length.
Basically, the string is too long.
I am using the following code:
function uploadTest2() {
var image_id = 'blabla';
var image_blob = DriveApp.getFileById(image_id).getBlob();
var input = image_blob.getBytes();
var docImg = Utilities.base64Encode(input);
var account_id = '1111111111111';
var facebookUrl =
'https://graph.facebook.com/v7.0' +
'/act_' + account_id +
'/adimages?bytes=' + docImg +
'&access_token=' + TOKEN;
Logger.log(facebookUrl);
//var encodedFacebookUrl = encodeURI(facebookUrl);
var options = {
'method' : 'post'
};
var response = UrlFetchApp.fetch(facebookUrl, options);
var results = JSON.parse(response);
Logger.log(response);
}
The image does not exceed 5MB and I have already check the bytes string with an online decoder to verify it.
Do you have any idea on how to use the image URL directly in the post request?
The second version of the code:
function uploadTest2() {
var image_id = 'blabla';
var image_blob = DriveApp.getFileById(image_id).getBlob();
var input = image_blob.getBytes();
var docImg = Utilities.base64Encode(input);
var account_id = '1111111111111';
var facebookUrl =
'https://graph.facebook.com/v7.0' +
'/act_' + account_id +
// '/adimages?bytes=' + encodedImage +
// '&access_token=' + TOKEN;
'/adimages?access_token=' + TOKEN;
Logger.log(facebookUrl);
//var encodedFacebookUrl = encodeURI(facebookUrl);
var options = {
'method' : 'post',
'payload' : image_blob
};
var response = UrlFetchApp.fetch(facebookUrl, options);
var results = JSON.parse(response);
Logger.log(response);
}
Solution
In order to make a post request of an image with UrlFetchApp.fetch() you must provide the method, payload (i.e the body you want to POST) and sometimes the content type (if what we are passing is not a JavaScript object).
If you want to pass a base64Encode object obtained from a blob you should stringify this JSON object.
What the original poster was missing was to pass the payload and after my contribution and his work he finally solved the issue by editing the options variable such as:
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload': JSON.stringify({"bytes": docImg,"name" : 'Test'})};
}
Documentation reference : Class UrlFetchApp

Email encoding and basic auth in react

My API looks something like this https://customerlink.org/api/data?email="
I have no problem using it with postman, I just need to encode the query string(email), as ‘#’ is not a valid character.
I used a website to encode the email and it worked with no problem. I used Postman and add the Basic Auth credentials
however I am confused on how to add the email part and how to encode it from my react app.
var api_url = "https://customerlink.org/api/data?email="
var email = "testemail#gmail.com"
var username = 'username';
var password = 'password';
var basicAuth = 'Basic ' + btoa(username + ':' + password);
axios.post(api_url + email, {}, {
headers: { 'Authorization': + basicAuth }
}).then(function(response) {
console.log('Authenticated');
}).catch(function(error) {
console.log('Error on Authentication');
});
You can use encodeURI(uri) if you need to, but the # symbol can be used in a query string just fine.
let uri = "https://customerlink.org/api/data?email=my#email.com"
let encodedUri = encodeURI(uri);

how to fetch uber login page then redirect to statements page using google apps script

i'm trying to fetch https://partners.uber.com/statements/cdf3d725-da5d-3ea2-1985-b8b09a6249d9
but i didn't get the requested page
i tried many solutions have been published here but it didn't help
username and password are checked
function getData() {
var target = "https://partners.uber.com/statements/cdf3d725-da5d-3ea2-1985-b8b09a6249d9";
var username = "user#gmail.com";
var pass = "pass";
var headers = {
"Authorization" : "Bearer " + Utilities.base64Encode(username + ':' + pass)};
var params = {
"method":"GET",
"headers":headers,
"followRedirects": true
};
var pageTxt = UrlFetchApp.fetch(target,params).getContentText();
Logger.log(UrlFetchApp.fetch(target,params).getResponseCode() );
Logger.log(pageTxt);
var pageDoc = Xml.parse(pageTxt,true);
var trs = pageDoc.getElement()
.getElement("body")
.getElements("div")[0]
.getElements("div")[3]
.getElement("table")
.getElements("tbody")[1].getElements("tr");
var col = pageDoc.getElement()
.getElement("body")
.getElements("div");
}
try this code block,
function myFunction() {
var response = UrlFetchApp.fetch("https://partners.uber.com/statements/cdf3d725-da5d-3ea2-1985-b8b09a6249d9",{muteHttpExceptions:true});
Logger.log(response);
}

ADAL JS not attaching user token while invoking WebApi

I am using ADAL JS for authenticating the users against Azure AD. And as I am new to ADAL JS, I started reading with following articles, which I find very informative:
Introducing ADAL JS v1
ADAL JavaScript and AngularJS – Deep Dive
After reading the articles, I had the impression that ADAL JS intercepts the service calls and if the service url is registered as one of the endpoint in AuthenticationContext configuration, it attaches the JWT token as Authentication Bearer information.
However, I found the same is not happening in my case. And after some digging, it seemed to me that it is only possible, if adal-angular counter part is also used, which I am not using currently, simply because my web application is not based on Angular.
Please let me know if my understanding is correct or not. If I need to add the bearer information explicitly, the same can be done, but I am more concerned whether I am missing some out-of-the-box facility or not.
Additional Details: My present configuration looks like following:
private endpoints: any = {
"https://myhost/api": "here_goes_client_id"
}
...
private config: any;
private authContext: any = undefined;
....
this.config = {
tenant: "my_tenant.onmicrosoft.com",
clientId: "client_id_of_app_in_tenant_ad",
postLogoutRedirectUri: window.location.origin,
cacheLocation: "sessionStorage",
endpoints: this.endpoints
};
this.authContext = new (window["AuthenticationContext"])(this.config);
Also on server-side (WebApi), Authentication configuration (Startup.Auth) is as follows:
public void ConfigureOAuth(IAppBuilder app, HttpConfiguration httpConfig)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = "my_tenant.onmicrosoft.com",
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = "client_id_of_app_in_tenant_ad"
}
});
}
However, the Authorization is always null in request.Headers.
UPDATE: It seems that the same applies for auto-renewal of tokens as well; when used in conjunction with adal-angular, the renewal of token works seamlessly by calling AuthenticationContext.acquireToken(resource, callback) under the hood. Please correct me if I am wrong.
After reading the articles, I had the impression that ADAL JS intercepts the service calls and if the service url is registered as one of the endpoint in AuthenticationContext configuration, it attaches the JWT token as Authentication Bearer information.
This will work only if your application is angular based. As you mentioned, the logic for this lives in adal-angular.
If, however, you want to stick to pure JS, you will not get the automatic "get-access-token-and-attach-it-to-header" support. You can use acquireToken(resource, callback api to get a token for the endpoint. But you will have to do some work in the controller that is sending the request to the api.
This might give you some idea: https://github.com/Azure-Samples/active-directory-javascript-singlepageapp-dotnet-webapi/blob/master/TodoSPA/App/Scripts/Ctrls/todoListCtrl.js. This sample does not uses angular.
ADAL.JS is incompatible with v2.0 implicit flow. I could not get it working since I set my project up recently and don't think projects are backwards compatible.
This was very confusing and took me a long time to figure out that I was mixing up the versions, and can't use ADAL.JS with v2.0. Once I removed it, things went much smoother, just did a couple of XHR requests and a popup window, no magic actually required!
Here is code for v2:
function testNoADAL() {
var clientId = "..guid..";
var redirectUrl = "..your one.."
var authServer = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?";
var responseType = "token";
var stateParam = Math.random() * new Date().getTime();
var authUrl = authServer +
"response_type=" + encodeURI(responseType) +
"&client_id=" + encodeURI(clientId) +
"&scope=" + encodeURI("https://outlook.office.com/Mail.ReadWrite") +
"&redirect_uri=" + encodeURI(redirectUrl) +
"&state=" + stateParam;
var popupWindow = window.open(authUrl, "Login", 'width=' + 300 + ', height=' + 600 + ', top=' + 10 + ', left=' + 10 + ',location=no,toolbar=yes');
if (popupWindow.focus) {
popupWindow.focus();
}
}
Note: redirectUrl will appear in popup window, needs to have code in it to pass location hash, such as this:
<script>window.opener.processMicrosoftAuthResultUrl(location.hash);window.close();</script>
function processMicrosoftAuthResultUrl(hash) {
if (hash.indexOf("#") == 0) {
hash = hash.substr(1);
}
var obj = getUrlParameters(hash);
if (obj.error) {
if (obj.error == "invalid_resource") {
errorDialog("Your Office 365 needs to be configured to enable access to Outlook Mail.");
} else {
errorDialog("ADAL: " + obj.error_description);
}
} else {
if (obj.access_token) {
console.log("ADAL got access token!");
var token = obj.access_token;
var url = "https://outlook.office.com/api/v2.0/me/MailFolders/Inbox/messages";
$.ajax({
type: "GET",
url: url,
headers: {
'Authorization': 'Bearer ' + token,
},
}).done(function (data) {
console.log("got data!", data);
var message = "Your latest email is: " + data.value[0].Subject + " from " + data.value[0].From.EmailAddress.Name+ " on " + df_FmtDateTime(new Date(data.value[0].ReceivedDateTime));
alertDialog(message);
}).fail(function () {
console.error('Error getting todo list data')
});
}
}
}
function getUrlParameters(url) {
// get querystring and turn it into an object
if (!url) return {};
if (url.indexOf("?") > -1) {
url = url.split("?")[1];
}
if (url.indexOf("#") > -1) {
url = url.split("#")[0];
}
if (!url) return {};
url = url.split('&')
var b = {};
for (var i = 0; i < url.length; ++i) {
var p = url[i].split('=', 2);
if (p.length == 1) {
b[p[0]] = "";
} else {
b[decodeURIComponent(p[0])] = decodeURIComponent(p[1].replace(/\+/g, " "));
}
}
return b;
}

How do you pass a dynamically built string as a http header in HTTP.call with meteor?

I'm stuck having to use a legacy web service that takes a username and password and returns xml indicating if the credentials are valid. The legacy service requires me to pass an http header with the request that contains the user's password. So, to get it to work, I had to hard code the password (actualUserPassword) in the header as follows:
var urlToCall = "https://ourlegacyauthserver/auth?uid=" + username);
var result = HTTP.call("GET", urlToCall, {headers:{"token:appname:127.0.0.1:actualUserPassword":""}});
This works when I hard code the proper password for the user on the server, but what I really need to do is build that header dynamically using the password variable, like this:
var urlToCall = "https://ourlegacyauthserver/auth?uid=" + username);
var headerString = "token:appname:127.0.0.1:" + password;
var result = HTTP.call("GET", urlToCall, {headers: {headerString: ""}});
When I do this, the auth server does not see the header coming in. What is wrong? I'm just trying to replace the hard coded string: "token:appname:127.0.0.1:actualUserPassword" with a string variable I built using the actual password passed in.
It's a javascript Object key problem. Try this instead:
var urlToCall = "https://ourlegacyauthserver/auth?uid=" + username);
var headerString = "token:appname:127.0.0.1:" + password;
var headerObject = {};
headerObject[headerString] = "";
var result = HTTP.call("GET", urlToCall, {headers: headerObject});

Categories

Resources