Yahoo New Weather API oAuth call in jQuery - javascript

As of the 3rd of January Yahoo Weather has a new weather API that requires oAuth https://developer.yahoo.com/weather/
Now I have gotten my Client ID (Consumer Key) and my Client Secret (Consumer Secret) from yahoo. My question is how would I call this API with oAuth in jquery or javascript?
Here is what a call looks like:
GET /forecastrss?location=sunnyvale,ca HTTP/1.1
Host: weather-ydn-yql.media.yahoo.com
Yahoo-App-Id: YOUR_APP_ID
Authorization: OAuth
oauth_consumer_key="YOUR_CONSUMER_KEY",oauth_signature_method="HMAC-SHA1",oauth_timestamp="YOUR_TIMESTAMP",oauth_nonce="YOUR_NONCE",oauth_version="1.0",oauth_signature="YOUR_GENERATED_SIGNATURE"
cache-control: no-cache
and it states "Please also include your OAuth app id in the header."
What would this look like in jquery?
I have tried the following:
$.get("https://weather-ydn-yql.media.yahoo.com/forecastrss", { location: "sunnyvale,ca", format: "json", oauth_consumer_key: "Client ID (Consumer Key)", oauth_signature_method: "HMAC-SHA1" } ).done(function( data ) {
console.log("Data Loaded: " + data);
});
and I get this error:
ERR_ABORTED 401 (Unauthorized)

Though I didn't run this code specifically but this should work like every other get request in jQuery
$.get( url, { location: "sunnyvale,ca", format: "json", oauth_consumer_key: oauth_consumer_key, oauth_signature_method: oauth_signature_method, ... } )
.done(function( data ) {
alert( "Data Loaded: " + data );
});
Ref1: jQuery API https://api.jquery.com/jQuery.get/
Ref2: Yahoo API: https://developer.yahoo.com/weather/documentation.html

Related

Error 400 Cognito /oauth2/token endpoint from client-side javascript

I am using AWS Cognito-hosted UI for my signup and login. There is no app client secret defined.
I am trying to make an API call from the browser javascript code to the /oauth2/token endpoint in order to exchange autohorization_token with an ID token.
The problem is, when I make the call through Postman, Insomnia it works fine. However, when I make the same call through javascript from the browser it fails with the 400 response type and I can't get much about the reason.
This is the Insomnia call which is a success;
However, when I make the same call via javascript it fails.
I have used both fetch and XMLHttpRequest and the same result.
const XHR = new XMLHttpRequest();
let urlEncodedData = "",
urlEncodedDataPairs = [],
name;
urlEncodedDataPairs.push( encodeURIComponent( 'grant_type' ) + '=' + encodeURIComponent( 'authorization_code' ) );
urlEncodedDataPairs.push( encodeURIComponent( 'code' ) + '=' + encodeURIComponent( code ) );
urlEncodedDataPairs.push( encodeURIComponent( 'client_id' ) + '=' + encodeURIComponent( 'xxxxx' ) );
urlEncodedDataPairs.push( encodeURIComponent( 'redirect_url' ) + '=' + encodeURIComponent( 'https://www.xxx.me/xxx' ) );
XHR.addEventListener( 'load', function(event) {
alert( 'Yeah! Data sent and response loaded.' );
} );
// Define what happens in case of error
XHR.addEventListener( 'error', function(event) {
alert( 'Oops! Something went wrong.' );
});
// Set up our request
XHR.open( 'POST', 'https://xxx.auth.us-west-2.amazoncognito.com/oauth2/token' );
// Add the required HTTP header for form data POST requests
XHR.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
// Finally, send our data.
XHR.send( urlEncodedData );
This is the response I am getting:
I have tried the same request with fetch and the result is the same.
let tokenRequest = new Request(tokenURL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Origin' : 'https://www.xxx.me'
},
body: new URLSearchParams({
'grant_type': 'authorization_code',
'code': code,
'client_id': 'xxx',
'redirect_url': 'https://www.xxx.me/xxx'
}).toString()
});
let response = await fetch(tokenRequest);
let data = await response.json();
One thing I have realized when I check the browser developer tool for other POST calls made to auth endpoints with content type=application/x-www-form-urlencoded, it shows query params added to URL like shown below, however, for my call, params are not encoded as part of URL. I am not sure if the problem might be related to this.
Any idea how I can make this call with client-side javascript?
Looks like the browser is using redirect_url which is wrong, and Postman is using redirect_uri which is correct. Also you should use PKCE to make the message more secure - see steps 4 and 8 of my blog post to understand how this looks.
Note also that in OAuth it is common to not return error details, or return to the app, if an unrecognised Client ID or Redirect URI are supplied. If these are both correct you should instead receive the standard OAuth error and error_description fields in a response payload.

http basic authorization with Flask REST

I am developing a simple REST service in flask.
I have been trying to implement basic authorization.
Whilst, I can pass the username and password from the webpage using manual entry, I can't seem to read them from the header.
Here is my code:
On the server
def test():
if request.authorization and request.authorization.username == '***' and request.authorization.password == '***':
return "Authorized"
else:
return make_response('Authorization failed', 401, {'WWW-Authenticate': 'Basic realm ="Login Required"'})
On the client - using JavaScript
<script>
$(document).ready(function(){
$("#authButton").click(function(){
$.ajax({
xhrFields: {
withCredentials: true
},
headers: {
'Authorization': "Basic " + btoa("***:***")
},
url: "********:5001/",
type: 'GET',
success: function(){
console.log("success");
},
error: function (){
console.log("error");
},
});
});
});
</script
>
I have also tried the Javascript code without the xhr fields section, but for neither do I get anything returned at all.
If I don't send the headers from the client it works and simply asks for manual input of the username and password.
All I'm trying to do is authenticate from the header.
Any pointers would be very gratefully received.

How to use an API with an app Fiori (SAPUI5)

I am trying to use this Mercedes Benz API in my app. Inside controller I have a ajax request:
onInit : function () {
var oModel = new JSONModel();
var url = 'https://api.mercedes-benz.com/image/v1/vehicles/WDDZH3HB8JA394212/components?apikey=my_apikey';
$.ajax({
beforeSend: function() {
//armamos la url y la asignamos a una var
},
url: url,
type: 'GET',
accepts: "application/json",
success: function (resp) {
console.log(resp)
},
error: function (jqXHR, estado, error) {
console.log(error +":" + " " + estado)
},
timeout: 10000
});
},
I just want response as OK but getting some error:
Request header field X-XHR-Logon is not allowed by
Access-Control-Allow-Headers in preflight response.
Responses
If you take a look to the documentation API I just need the API key. Maybe I am doing something wrong? Guide me if you has use an API inside a FIORI app it will be thankful
NOTE: my fiori server is on premise so we don't use SCP
If you really want to do an XHR you need to whitelist APIKEY in neo-app.json like this
{
"welcomeFile": "/webapp/index.html",
"routes": [{
...
],
"sendWelcomeFileRedirect": true,
"headerWhiteList": [
"APIKey"
]
}
Otherwise I strictly recommend using destinations, explained in here:
SAPUI5 / AJAX, submitting Basic Authentication Details (solved)
Authentication API in SAPUI5 without SAP Cloud Platform and Destinations (not solved)

jQuery.ajax to $http

I used this function
jQuery.ajax({
type: 'POST',
url: urlSubmit,
timeout: 5000,
dataType: 'text',
data: {
date : dataDate,
url : dataUrl,
domaine : dataDomaine,
email : dataEmail,
destinataire : dataDestinataire,
msg : dataMsg
},
"success": function (jqXHR, textStatus, errorThrown) {
console.log("AJAX success :) - statut " + textStatus);
$timeout(successMailZR_alerte, 3000);
},
"error": function (jqXHR, textStatus, errorThrown) {
console.log("AJAX fail :/ - statut " + textStatus);
$timeout(errorMailZR_alerte, 3000);
}
});
Whats the code is doing : code POST to a php script who send an email.
but, since i rewrited my code in a complete angularjs app, i do it like this :
$http({
method: 'POST',
url: urlSubmit,
timeout: 5000,
cache: false,
data: {
date : dataDate,
url : dataUrl,
domaine : dataDomaine,
email : dataEmail,
destinataire : dataDestinataire,
msg : dataMsg
},
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
responseType: 'text',
}).
success(function(data, status, headers, config) {
console.log("AJAX success :) - statut " + status);
$timeout(successMailZR_alerte, 3000);
}).
error(function(data, status, headers, config) {
console.log("AJAX fail :/ - statut " + status);
$timeout(errorMailZR_alerte, 3000);
});
Problem is : with $http, i have a success 200 but nothing is posted and i have no return in my email. What's the problem ?
The problem is that jQuery's POST does send your data as form data (e.g. key-value pairs) (https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Sending_and_retrieving_form_data) whereas AngularJS sends your data in the request payload. For a difference between the two see the following SO question: What's the difference between "Request Payload" vs "Form Data" as seen in Chrome dev tools Network tab
In order to make your angular script works with your server you have to convert your data to a URL encoded string as described here: How can I post data as form data instead of a request payload?. Simply setting headers: {'Content-Type': 'application/x-www-form-urlencoded'} is not enough.
A different approach would be to adapt the back-end of your application to parse the message payload instead of the form data parameters.
To understand this one need to understand the request headers set by angular and jquery, There are differences with the headers like when request is post by jQuery then header might look like this:
POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded // default header set by jQuery
foo=bar&name=John
You can see this in form data in the request made in the browser, if you use chrome then you can see this in chrome inspector at network tab, if you click the request then you can see the form data and content headers set by the jQuery.
On the other side with angular js $http service, when a request is made then you can find these:
POST /some-path HTTP/1.1
Content-Type: application/json // default header set by angular
{ "foo" : "bar", "name" : "John" }
The real difference is this you have a request payload not usual form data which is used by jQuery. so you need to do something extra at the server side like below.
Use this:
$data = json_decode(file_get_contents("php://input"));
echo $data->date;
// and all other params you have sent
This is due to its default headers
Accept: application/json, text/plain, * / *
Content-Type: application/json
and jQuery unlikely have something else:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

Yammer Open Graph Post - How do i do it?

I am trying to figure out how the payload should be constructed for a Open Graph object to submit to yammer. I can post a standard message, but i would like to post an opengraph message instead.
{
"activity":{
"actor":{"name":"Sidd Singh",
"email":"sidd#xyz.com"},
"action":"create",
"object": {
"url":"https://www.sched.do",
"title":"Lunch Meeting"
},
"message":"Hey, let’s get sushi!",
"users":[
{"name":"Adarsh Pandit",
"email":"adarsh#xyz.com"}
]
}
}
This is some code nicked from their API documentation but doesn't show me how i should use this in javascript. Can someone assist me? Below is my existing code that posts a standard message...
yam.request({
url: "https://www.yammer.com/api/v1/messages.json?network_id=networkname", //this is one of many REST endpoints that are available
method: "POST",
beforeSend: function (req) { //send the access_token in the HTTP header
req.headers.Authorization = "Bearer " + access_token;
},
data: {
"network": "networkname",
"body": "Test Post",
"group_id": "3719771"
},
success: function (data) { //print message response information to the console
toastr.success('An Item was successfully posted to Yammer', "Yammer Network");
},
error: function (user) {
toastr.error('There was an error eith the request', "Yammer Network");
}
});
This post answered your question: Yammer Open Graph API Error 400
Simply replace the key value pairs in the data{} with the activity json strings. Also remember to change the RESTful api endpoint to https://api.yammer.com/api/v1/activity.json

Categories