Twilio, Google Sheets, No credentials provided - javascript

Our company is looking for ability to use a service like Twilio to send out SMS messages to several hundred people (RSVP reminders). Currently, we are using Google Sheets to track the list of people.
I found an entry in Twilio's blog (https://www.twilio.com/blog/2016/02/send-sms-from-a-google-spreadsheet.html) written by Greg Baugues that outlines how to send SMS messages using JS and Google Sheets. I copied Greg's JS code into the Google Sheets Script Editor, change out the Account SID and AuthToken with the values provided in my trial account, and then tried to send a single test SMS. Every time I run the function, I get the following response:
Request failed for https://api.twilio.com/2010-04-01/Accounts/AC042b89e7dffb4cb877f82b0c2efc76a7/Messages.json
returned code 401. Truncated server response:
{"code": 20003, "detail": "Your AccountSid or AuthToken was incorrect.", "message": "Authentication Error - No credentials provided", "more_info": ... (use muteHttpExceptions option to examine full response)
To make sure I didn't have some kind of error in my SID and Token, I tried send a test SMS through the web interface, and Python script available on Twilio's website. Both of these were successful.
Does anyone have any other recommendations? In the original blog post, I noticed that several other readers have left comments with the same issue. The authentication part of the original function is:
var options = {
"method" : "post",
"payload" : payload
};
options.headers = {
"Authorization" : "Basic" + Utilities.base64Encode("AccountSID:AuthToken") ##Credentials hidden, obviously
};
I wonder if something has change in Twilio's security settings since this posts was originally shared.

Got it. Very simple Javascript typo. In the options headers, there needs to be a space after Basic. "Authorization" : "Basic "
Everything works now. I'll leave this up in case anyone else decides to replicate the same code from the blog post.

Related

Gmail API - sending email with oAuth2.0 in javascript

I'm trying to create a web page that sends an email only using javascript and Gmail API. I have set up my developer's console to use the API and also created an API key and a credential.
I have adapted this example code, and so far I think I got to the point of loading the GMail API. (or.. 400 means something is wrong?) The console log shows:
POST https://content.googleapis.com/gmail/v1/users/me/messages/send?alt=json 400 (OK)
zu # cb=gapi.loaded_0:85
n # cb=gapi.loaded_0:85
Cu # cb=gapi.loaded_0:85
(anonymous function) # cb=gapi.loaded_0:86
g # cb=gapi.loaded_0:55
c # cb=gapi.loaded_0:46
And when I try authenticating with oAuth2.0 through a url:
var code;
$.get("https://accounts.google.com/o/oauth2/auth?scope=email&
redirect_uri=http://hiro.collegewebserver.com/COSW200/hw13/gmailtest.html&
response_type=token&client_id=386373199858-o1rt7qj3gt99gbfg6pqpr0g6i92urq9t.apps.googleusercontent.com&
approval_prompt=force",
function (returnedValue) { code = returnedValue; });
I get this message:
XMLHttpRequest cannot load https://accounts.google.com/o/oauth2/auth?scope=email&
redirect_uri=http://h…3gt99gbfg6pqpr0g6i92urq9t.apps.googleusercontent.com&
approval_prompt=force.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://hiro.collegewebserver.com' is therefore not allowed access.
I've read other posts that say this may be due to cross origin requests being blocked? Someone wrote that there are ways to work around this like using JSONP?
If someone can enlighten me as to what I'm missing here, I would really appreciate! :)
You cannot make an ajax call to Google to get your access code. The idea of OAuth2 is that you first redirect the user to accounts.google.com/o/oauth2/your_settings. In your case:
https://accounts.google.com/o/oauth2/auth?scope=email&redirect_uri=http://hiro.collegewebserver.com/COSW200/hw13/gmailtest.html&response_type=token&client_id=386373199858-o1rt7qj3gt99gbfg6pqpr0g6i92urq9t.apps.googleusercontent.com&approval_prompt=force
In this Google environment the user can login with his/her account. One of the settings you provide is the redirect_uri.
Since you whitelisted http://hiro.collegewebserver.com/COSW200/hw13/ as one of the Authorized redirect URIs in your Google Developers Console and this url is related to your client_id, no other application than your website can use your client_id to receive an authorization code.
After login the user will be redirected to this redirect_uri, with the code as one of the parameters.
This will look something like this:
http://hiro.collegewebserver.com/COSW200/hw13/#access_token=yb27…jK0AVtilhnrJDcuTISgIB5LiNtKLMut1kVvPW69w&token_type=Bearer&expires_in=3600
After that you would have to extract the access token from the url. With this access token you can authorise the user and make use of the scopes you entered. This can be done with an ajax call.
$http({
method: 'GET',
url: 'https://www.googleapis.com/upload/gmail/v1/users/userId/messages?access_token=' + access_token
}).then(function(response){
//your code
})
You could also put the access_token in the header of the call:
Authorization: Bearer access_token
Another option is to use the API Client Library for JavaScript (Beta): https://developers.google.com/api-client-library/javascript
Although it is in Beta and the basic workflow is the same, it might give you clearer examples.

How to get a Twilio SMS body text in Node.js

I'm working on a side-project of mine which integrates with Twilio. It's a Node.js app running on the Hapi.js framework.
I have the app set up with Twilio so that when I text my Twilio number, Twilio gets the request from my app's route and texts me back with a static message in the response.
What I'm having trouble with is getting the SMS body from the user's text. Let's say that I text the Twilio number with a word like banana I want to be able to retrieve that from the request so that I can have a dynamic message based on it.
I've tried request.Body, request.message, among several other things, and I can't seem to retrieve the user's text to the Twilio number. I've looked through Twilio's documentation and can't seem to figure it out. I saw this PHP keyword tutorial on Twilio which looked promising, but even accessing request.Body as in that tutorial doesn't seem to work at all.
Does anyone know how to get the text body from a Twilio SMS that a user sends? Any and all help is appreciated
With Hapi, if you want to read all the request body into memory before running your handler you need to set the payload config:
server.route({
config: {
payload: {
output: 'data'
}
},
method: 'POST',
path: '/textMessage',
handler: function (request, reply) {
console.log('Body was', request.payload.toString());
reply('...');
}
});
From the Hapi API docs:
'data' - the incoming payload is read fully into memory. If parse is
true, the payload is parsed (JSON, form-decoded, multipart) based on
the 'Content-Type' header. If parse is false, the raw Buffer is
returned. This is the default value except when a proxy handler is
used.
More options here: http://hapijs.com/api#route-options
After trying different methods to retrieve the request payload from Twilio, I found that the Twilio request body can be accessed via request.url.query, and therefore, the Body of the text, can be retrieved via request.url.query.Body. Thanks for the help #MattHarrison!

How would I form a correct POST request to LinkedIn to exchange the temp auth code for the access token and is SSL3 the cause?

I'm still a bit confused about how to form the correct POST request to LinkedIn to exchange the already received temporary authorization code for the user's access token as described in the LinkedIn docs at https://developer.linkedin.com/documents/authentication in step 3b.
There it says a POST request should be made, but instead of the POST request format, the docs give this URL with query parameters:
https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=YOUR_REDIRECT_URI
&client_id=YOUR_API_KEY
&client_secret=YOUR_SECRET_KEY
I'm using server-side JavaScript and would like to form the proper POST request. Does this look correct?
r = 'POST /uas/oauth2/accessToken HTTP/1.1' + crlf;
r += 'Host: www.linkedin.com' + crlf + crlf;
r += parameters;
Where crlf is '\r\n' and parameters would be in the body and would be:
grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI&client_id=YOUR_API_KEY&client_secret=YOUR_SECRET_KEY
with the upper-case values being replaced by the actual values for our app and the user.
Then the request itself would be sent to https://www.linkedin.com/uas/oauth2/accessToken using a function I have for making HTTP requests.
Does that seem correct? Is that sufficient for forming a proper POST request?
Must I also include Referer, Content-Type and Content-Length headers? If so, should my request actually look like this?
r = 'POST /uas/oauth2/accessToken HTTP/1.1' + crlf;
r += 'Host: www.linkedin.com' + crlf ;
r += 'Referer: http://' + site.txMainServer + '/LinkedProfile' + crlf;
r += 'Content-Type: application/x-www-form-urlencoded' + crlf;
r += 'Content-Length: ' + parameters.length + crlf + crlf;
r += parameters;
Where site.txMainServer is the server's URL.
New info: If I try the above code, rather than returning JSON with the access token, the following error is returned when I make my POST request: "* Connection error: 1590".
New info 2: Somebody told me that LinkedIn would also accept a GET request. So instead of a POST I tried a GET request in the exact form of the URL shown above in the LinkedIn documentation. But I also get a "* Connection error: 1590" if I try that. So I am stuck.
New info 3: Since it is an HTTPS request I tried replacing the Host header above with
Host: www.linkedin.com:443
but that didn't help. I still get the same "* Connection error: 1590".
New info 4: I believe the 1590 error is a "failure to make an SSL connection" error from my server. I have since tested by making successful SSL POST requests from my server to other SSL sites with the exact same headers and parameters (adjusting the Host of course to match the other server) for testing and have returned successful replies. So there is something about the LinkedIn server that is different. It wants some different format of a POST request, but I don't know what it is.
New Info 5: It appears our server is trying to make a POST request via SSL3 to exchange the temporary authentication code for the access token needed to make API calls, but we are experiencing handshake failures. Is SSL3 not supported at all for the LinkedIn API now?
It's just not clear to me why, if LinkedIn docs say they want a POST they instead give an example showing a full URL with query parameters, rather than the exact format of the POST request they want.
It appears I am not doing it the way LinkedIn wants, and would appreciate any assistance here. If I could just see an example of the correct format of the POST request I'm sure I can proceed from there! But it's not in the LinkedIn docs.
Thanks,
doug
I'm not familiar with server-side js (you mean nodejs?).
so shot in the dark: some companies require params both in the URL & POST body and linkedin require HTTPS request, maybe www.linkedin.com is not right.
PS. can't edit comments,just post here;(
I believe I found the answer. At https://developer.linkedin.com/forum/oauth2-api-not-working-all-sudden LinkedIn employees post the following in response to people having problems which seem much like mine:
"In light of the recent disclosure of the "Poodle" SSL vulnerability, LinkedIn
is joining the large number of services that have actively removed support for
SSLv3, effective immediately. If you are experiencing errors related to
HTTPS-based communication with our APIs, please ensure you are using a
client/library that supports TLS 1.0+ instead of SSLv3 to avoid disruption.""
and
"There is no fix for this issue. It is the result of an unfixable vulnerability
in the SSLv3 protocol itself, which is well outside of LinkedIn's control. We
will not be re-enabling support for this. You will have to use a library that
can make a different SSL connection."
It appears we have to upgrade our SSL or cannot proceed.
doug

Search video with vimeo Api using javascript

I want to use the new vimeo api to fetch videos based on a query, but I getting a 401 Authorization Required with this message "error": "A valid user token must be passed."
I'm using this code :
var urlX = 'https://api.vimeo.com/videos?query=elvis&client_id='+VIMEO_API_KEY;
$.getJSON(urlX, function(data){
console.log(data);
});
So obviously I have an authentication problem.
As client_id I'm using my "Client Identifier" from my app created in Vimeo's dashboard.
The error I keep getting mention "user token", do I have to generate one via Vimeo's dashboard or via php ?
I'm a bit lost here.
client_id through the querystring is not a valid method of making API calls against the Vimeo API.
First you must request an access token either through the oauth2 redirect worfklow: https://developer.vimeo.com/api/authentication, or by generating it on your app page.
Second you must provide that access token with your api request either through the Authorization header:
Authorization: bearer <your_token>
or the querystring
https://api.vimeo.com/videos?query=elvis&access_token=<your token>.
The authorization header is more secure, and will continue to work indefinitely. Some changes will be made soon to the querystring form which could cause problems with your application.

Google OAuth2 - Exchange Access Code For Token - not working

I am currently in the process of implementing a server-side OAuth2 flow in order to authorize my application.
The JS application will be displaying YouTube Analytics data on behalf of a registered CMS account to an end user (who own's a channel partnered with the CMS account). As a result of this, the authorization stage needs to be completely hidden from the user. I am attempting to authorize once, then use the 'permanent' authorization code to retrieve access tokens as and when they're needed.
I am able to successfully authorize, and retrieve an access code. The problem begins when i attempt to exchange the access code for a token.
The HTTP POST Request to achieve this needs to look like this...
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
I am using this code to achieve this:
var myPOSTRequest = new XMLHttpRequest();
myPOSTRequest.open('POST', 'https://accounts.google.com/o/oauth2/token', true);
myPOSTRequest.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
myPOSTRequest.send('code=' + myAuthCode + '&redirect_uri=http%3A%2F%2Flocalhost%2FCMSAuth3.html&client_id=626544306690-kn5m3vu0dcgb17au6m6pmr4giluf1cle.apps.googleusercontent.com&scope=&client_secret={my_client_secret}&grant_type=authorization_code');
I can successfully get a 200 OK response to this Request however no access token is returned, and myPOSTRequest.responseText returns an empty string.
I have played with Google's OAuth Playground - and can successfully get a token using my own credentials.
Am i missing something here?
You cannot do this, because there is the same origin policy. This is a security concept of modern browsers, which prevents javascript to get responses from another origin, than your site. This is an important concept, because it gives you the ability, to protect you against CSRF. So don't use the code authorization flow, use instead the token authorization flow.
Try and build up the full URL. Then dump it in a webbrowser. If its corect you will get the json back. You have the corect format.
https://accounts.google.com/o/oauth2/token?code=<myAuthCode>&redirect_uri=<FromGoogleAPIS>&client_id=<clientID>&client_secret={my_client_secret}&grant_type=authorization_code
Other things to check:
Make sure that you are using the same redirect_uri that is set up in google apis.
How are you getting the Authcode back? If you are riping it from the title of the page i have had issues with it not returning the full authcode in the title try checking the body of the page. This doesnt happen all the time. I just ocationally.

Categories