I'm currently working on an adapter call that takes an OAuth token in the Authorization header. The request works just fine in a FireFox RestClient AND an xhr get... but is failing from the Worklight adapter with an error saying the user needs to login. Which is the same error that the user would see if they didn't pass in the authorization header.
wl adapter:
function getFriends(accessToken) {
var authtok = 'Bearer ' + accessToken;
var input = {
method : 'get',
headers: {Authorization: authtok},
path : '/connections/opensocial/rest/people/#me/#self'
};
return WL.Server.invokeHttp(input);
}
Anyone else seeing an error like this? Is there a way to trace the worklight adapter invocation to inspect that the headers sent into the request are as expected?
Looks like your server was also expecting the hostname in the headers. Try changing your input to this:
var input = {
method : 'get',
returnedContentType : 'json',
path : '/connections/opensocial/rest/people/#me/#self',
headers: {
'Authorization': authtok,
Host: "HOSTNAME THAT IS USED IN THE .XML FILE"
}
};
So if your adapter's xml file looks like this:
<connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
<protocol>https</protocol>
<domain>jeremy.server.whatever.com</domain>
<port>443</port>
-->
</connectionPolicy>
Then your headers should look like this:
headers: {
'Authorization': authtok,
Host: "jeremy.server.whatever.com"
}
Related
I'm trying to pull an access token from Office365's /token identity platform endpoint via OAuth 2.0 client credentials grant flow. I have my app registered, the client ID & secret, etc...
I can make the POST request in Postman and receive the access token without issue:
However, when I try the POST request via JavaScript (by way of Google Apps Script), I receive an error message: AADSTS900144: The request body must contain the following parameter: 'grant_type'
I've already Google'd this error and found a bunch of different solutions, and have tried implementing them to no avail. I imagine this has to do with the URL encoding, but cannot figure it out.
Code:
function getO365() {
// POST Request (To get Access Token)
var tenantID = 'longstringhere'
var appID = 'longstringhere'
var appSecret = 'longstringhere'
var graphScore = 'https://graph.microsoft.com/.default'
var url = 'https://login.microsoftonline.com/' + tenantID + '/oauth2/v2.0/token'
var data = {
'client_id': appID,
'scope': graphScore,
'client_secret': appSecret,
'grant_type': 'client_credentials'
};
var postOptions = {
'method': 'POST',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
'body': data,
'redirect': 'follow'
};
var authToken = UrlFetchApp.fetch(url, postOptions);
}
The only real difference between my code and the JavaScript Fetch code I pulled off of Postman is:
var urlencoded = new URLSearchParams();
urlencoded.append("client_id", "longstringhere");
urlencoded.append("scope", "https://graph.microsoft.com/.default");
urlencoded.append("client_secret", "longstringhere");
urlencoded.append("grant_type", "client_credentials");
When I try to use URLSearchParams in Google Apps Script, I keep getting this error: ReferenceError: URLSearchParams is not defined
Any ideas? Thanks in advance!
This was resolved by changing 'body' to 'payload' for UrlFetchApp per the documentation. Edited code to reflect the change. Credit to #TheMaster for pointing out my mistake.
'payload': data,//from 'body': data,
Normally, when I make a jQuery request to a non-local server, it applies Cross-site HTTP request rules and initially sends an OPTIONS request to verify the existence of an endpoint and then it sends the request, i.e.
GET to domain.tld/api/get/user/data/user_id
jQuery works fine, however I would like to use Vue Resource to deal with requests. In my network log, I see only the actual request being made (no OPTIONS request initially), and no data is being received.
Anybody has an idea how to solve this?
Sample Code:
var options = {
headers: {
'Authorization': 'Bearer xxx'
}
};
this.$http.get(config.api.base_url + 'open/cities',[options])
.then(function(response){
console.log('new request');
vm.cities = response;
}, function(error){
console.log('error in .js:');
console.log(error);
});
jquery-request
Solution:
As #Anton mentioned, it's not necessary to have both requests (environment negligible). Not sure what I have changed to make it work, but the request gave me an error. It consisted in setting the headers correctly. Headers should not be passed as options but as a property of http:
this.$http({
root: config.api.base_url + 'open/cities', // url, endpoint
method: 'GET',
headers: {
'Authorization': 'Bearer xxx'
}
}).then(function(response){
console.log('new request');
vm.cities = response;
}, function(error){
console.log('error in .js:');
console.log(error);
});
Thank you guys, it was a team effort :)
Is it a requirement that an additional OPTIONS request is being made? I have created a small (32 LOC) example which works fine and retrieves the data:
https://jsfiddle.net/ct372m7x/2/
As you can see, the data is being loaded from a non-local server. The example is located on jsfiddle.net and the request is made to httpbin.org - this leads to CORS being applied (you can see the Access-Control-Allow-Origin header in the screenshot below).
What you also see is that only the GET request has been executed, no OPTIONS before that.
I have an app which calls a adapter and which has a procedure that connects to rest service to fetch me the required data and I am sending the data back to app.
The request body comes fine to app. But how do I send headers that I receive from rest services to app .i.e I want my adapter to send the headers that it receive from rest service to my app.
I am using the following adapter code.
function getFeed(tag,json) {
var input = {
method : 'post',
returnedContentType : 'json',
path : 'myservice',
headers : {'head1': 'value'},
body: {
contentType: 'application/json' ,
content: json
},
};
return WL.Server.invokeHttp(input);
}
The response JSON that reaches the client (the result of WL.Server.invokeHttp(input) ), contains a key "responseHeaders".
This responseHeaders is a relay of the headers that were received from the backend.
I'm developing a React-Native App with Open Bank Project and I can't use suggested SDKs, not even the nodeJS one as Oauth1.0 is not available in RN.
And I'm stuck with a Bad Signature error on Access Token request '/oauth/token' after passed '/oauth/initiate' and '/oauth/authorize' without any problem.
As specified in docs here before accessing to a Protected Resource we need an Access Token via a POST Request, which gives me the Bad Signature answer.
Here is my code for the request:
getAccessToken(verifier){
let request = {
url: 'https://api.openbankproject.com/oauth/token',
method: 'POST',
data: {
oauth_verifier: verifier,
oauth_token: this.auth.oauth_token,
oauth_token_secret: this.auth.oauth_token_secret
}
}
return fetch(this.url_login, {
method: request.method, //POST
form: request.data,
headers: this.oauth.toHeader(this.oauth.authorize(request))
})
.then((res) => {return res.text()})
.then((txt) => {
console.log('setUID', txt, this.url_login, {
method: request.method,
form: request.data,
headers: this.oauth.toHeader(this.oauth.authorize(request))
})
})
Here is the signed request:
Object {method: "POST", form: Object, headers: Object}
form:
oauth_token:"..."
oauth_token_secret:"..."
oauth_verifier:"71531"
headers:
Authorization:
"OAuth oauth_consumer_key="...", oauth_nonce="3UlQ5dx958tibf6lSg0RUGPQFZeV7b8V", oauth_signature="weyE1lFkoIjAErYLKdSi9SDlCZsNBi7%2BuAkLV2PWePo%3D", oauth_signature_method="HMAC-SHA256", oauth_timestamp="1464248944", oauth_token="...", oauth_token_secret="...", oauth_verifier="71531", oauth_version="1.0""
I've tried with and without Oauth_token_secret, also moving oauth_verifier from body to query but with the same Bad Signature result.
Any idea? thx
You can use oauth module https://github.com/ciaranj/node-oauth
var oauth=require('oauth');
var consumer = new oauth.OAuth(
"https://twitter.com/oauth/request_token", "https://twitter.com/oauth/access_token",
_twitterConsumerKey, _twitterConsumerSecret, "1.0A", "http://127.0.0.1:8080/sessions/callback", "HMAC-SHA1");
then generating signature like this :
var parameters = consumer._prepareParameters("user_access_token", "user_access_token_secret", "http_method", "request_url");
var headers = consumer._buildAuthorizationHeaders(parameters);
parameters array contains signature, also you can build authorization headers if needed. Hope it helps :)
I have an authentication webservice sitting at http://example.com:9080/auth/login that accepts a POST request with www-url-form-encoded encoding and responds back in JSON format.
I am currently going through the Adapter-based Authentication tutorial. Inside the body of submitAuthentication(username, password) in SingleStepAuthAdapter-impl.js, I have the following:
function submitAuthentication(username,password):
var input = {
method: "post",
path: '/auth/login',
returnedContentType: 'json',
body: {
content: JSON.stringify({"username":username, "password":password}),
contentType: "application/x-www-url-formencoded;charset=utf-8"
}
var returnData = WL.Server.invokeHttp(input)
The problem I am having is that the server (locally hosted websphere) is not receiving my username and password. Am I missing something here?
You could add a header to the request with basic authentication credentials such as:
var input = {
method: "post"
returnedContentType: 'application/json',
path: path,
headers: {
'Authorization': 'Basic '+ base64_encode(username+':'+password),
You could also make the request and then store a secure cookie and attach it as a header on future requests following this post:
Attaching cookie to WorkLight Adapter response header