Using Microsoft Graph with client credentials and message subscriptions - javascript

My goal is to use client credentials and Graph subscriptions for messages, for several users in my tenant.
I'm successfully getting the access token via client credentials, and can use it with Graph for things like creating calendar events for multiple users.
However, when I use the access token to create a Graph subscription for messages, I get a failure of "Unsupported segment type".
Does graph support client credentials for subscriptions? If yes, am I doing something wrong?
Thanks for any help.
"error": {
"code": "BadRequest",
"message": "Unsupported segment type. ODataQuery: users//subscriptions",
"innerError": {
"request-id": "e92caf14-0343-40b0-8720-30946d7fd236",
"date": "2018-05-17T17:53:34"
}
}
Here's my subscribe function:
graph.subscribe = function(token, userid) {
var subscription = {
changeType: 'Created',
notificationUrl: 'my notification url',
resource: '/users/<userid removed>/messages',
clientState: 'blah'
};
request.post({
url: 'https://graph.microsoft.com/v1.0/users/<userid removed>/subscriptions',
headers: {
'content-type': 'application/json',
authorization: 'Bearer ' + token
},
body: JSON.stringify(subscription)
}, function(err, response, body) {
if (err) {
console.error('>>> Application error: ' + err);
} else {
console.log('>>> Subscription returned ' + body);
}
});
};

The POST should be issued to the /v1.0/subscriptions endpoint, not /v1.0/users/{upn}/subscriptions.
You may want to take a look at this Node.js example to see how they're doing it.

Related

Spring: request body missing error when sent from client but works with postman?

I have a Spring Rest backend setup as well as a react client. Both are setup on different local ports. I am trying to send a simple request from my React client using a fetch call to my spring rest api.
When sending the POST request using Postman, the API responds as expected.
When sending the request from the React client I receive the following 400 error:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing: public
org.springframework.http.ResponseEntity<?>
I have done the following:
Disabled CSRF on my spring application.
Set global CORS config to accept all requests.
Ensured on multiple occasions that the request body is correct and identical to that sent via Postman.
Here is my Fetch request from react client:
fetch(API_BASE_URL + '/api/auth/signin', {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json;charset=UTF-8',
'Access-Control-Request-Method': 'POST'
}),
body: {
username: this.state.uname,
password: this.state.password,
}
}).then(
function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function (data) {
let json = JSON.parse(data);
let token = json.tokenType + " " + json.accessToken;
localStorage.setItem(ACCESS_TOKEN, token);
alert('successfully saved token:' + token);
});
}
)
.catch(function (err) {
console.log('Fetch Error :-S', err);
});
For those interested:
The data passed in payload was of an incorrect format. While this may not appear logical, creating a variable as so:
let payload = {
username: this.state.username,
password: this.state.password,
};
And passing that as the body to fetch seems to work.
Hopefully this may help others facing the same problem..

Nodejs Auth0 read users with api not working (err: 400, msg: Bad HTTP authentication header format)

I'm trying to receive my users that are stored in Auth0. So, I tried using this website Auth0 management API docs with my API token and API domain. This works fine!
Then I tried to do the same in node js, but when I do that it returns an error. The error message is:
"statusCode":400,"error":"Bad Request","message":"Bad HTTP authentication header format","errorCode":"Bearer"
This is the code that i fount in the documentation
var request = require("request");
var options = { method: 'GET',
url: 'https://<api_url>/api/v2/users',
headers: { authorization: 'Bearer ACCESS_TOKEN' }
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The only thing that is changed is that I deleted the query string and inserted my api_url and the same access token that I used on the Auth0 management API docs (which works). Am I missing something?
The code looks perfectly fine. I edited it with my hostname/access token as follows and it returned the users:
var request = require("request");
var token = 'eyJ0...'
var options = { method: 'GET',
url: 'https://tenant_name.auth0.com/api/v2/users',
headers: { authorization: 'Bearer ' + token }
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The two things that might have gone wrong in your case are:
You didn't properly replace the ACCESS_TOKEN in the code.
The access token does not have the read:users permission. You can verify this by pasting the token in jwt.io and inspecting the payload.

How to make a POST request using CustomVision api with NodeJS

I'm trying attach an image using the bot emulator tool and sending this image off to the microsofts customvision api, the issue I'm having is that I get
{ Code: 'BadRequestImageFormat', Message: '' }
back from custom the custom vision api call.
I'm using the the request module from npm to handle the calls
// Receive messages from the user and respond by echoing each message back (prefixed with 'You said:')
var bot = new builder.UniversalBot(connector, function (session) {
session.send("Hello"); //session.message.text
// If there is an attachment
if (session.message.attachments.length > 0){
console.log(session.message.attachments[0])
request.post({
url: 'xxx',
encoding: null,
json: true,
headers: {
'Content-Type': 'application/octet-stream',
'Prediction-Key': 'xxx'
},
body: session.message.attachments[0]
}, function(error, response, body){
console.log(body);
});
}
});
I believe that I may be sending the wrong format through to custom vision however I have been unable to figure it out as of yet.
I replicated your issue and it looks like the problem is your 'Content-Type'. You're attempting to pass JSON in your request, but setting the content-type as octet-stream. See my modified code below:
var bot = new builder.UniversalBot(connector, function (session) {
session.send("Hello"); //session.message.text
// If there is an attachment
if (session.message.attachments.length > 0){
console.log(session.message.attachments[0])
request.post({
url: 'https://northeurope.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures',
encoding: null,
json: true,
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'Your API Key...'
},
body: session.message.attachments[0]
},
function (err, response, body) {
if (err) return console.log(err)
console.log(body);
});
}
});
When I run this, I get the error InvalidImageUrl which is to be expected as it's looking for a content on localhost. You could get round this by exposing your localhost using Ngrok.

Using request HTTP client library to post to FastSpring API

I am attempting to use request to POST to FastSpring's API for updating subscriptions for my customers. I am able to GET subscriptions without problem, but when it comes to POST, I cannot seem to get it to work.
Here is my code:
var options = {
method: 'POST',
url: 'https://api.fastspring.com/subscriptions',
headers: {
'Authorization': auth,
'User-Agent': 'request',
'Content-Type': 'application/json'
},
formData : {
'subscriptions': [
{
"subscription": subscriptionId,
"quantity": newQty,
"product": product,
"prorate": true
}
]
}
};
request.post(options, function (error, response, body) {
_logger.error('Fastspring API response: ' + JSON.stringify(response));
_logger.error('Fastspring API error: ' + JSON.stringify(error));
_logger.error('Fastspring API body: ' + JSON.stringify(body));
if (!error && response.statusCode === 200) {
res.status(200).send(JSON.parse(body));
} else {
_logger.error('Fastspring API Error: ' + error);
res.status(500).send({ 'error': error});
}
});
The result of attempting the POST results in the following error:
TypeError: source.on is not a function
I looked it up and saw that the reason why it was failing is that request cannot accept the formData I'm sending. Problem is that without it, I cannot POST to FastSpring's API (I get the error message "subscriptions not found." if I send anything else).
My question is this: Can I send my formData in any way that will be accepted by request? I've looked this issue up on the issues page of request and couldn't find a satisfactory answer.
Are you trying to pass some JSON data? Usually that kind of data are written in body not in formData.
Try something like this:
var myreq = request.post(...)
myreq.write(myJsonData);
myreq.end();

Connecting to my Visual Studio Online API returns HTTP 302

I'm trying to connect to my VSTS build 2.0 api through Node to create a new build definition. I'm getting HTTP 302 , which is an redirect. I'm not sure why this happening, I was able to submit same request, with same URL through SOAP UI without any issue. Below is the code snippet.
var Client = require('node-rest-client').Client;
var client = new Client();
var accessToken = 'MY ACCESS TOKEN';
var args = {
data: JSON.stringify(configJSON),
headers: {
"Content-Type": "application/json",
"Accept": "application/json"}
,auth: {
'bearer': accessToken
}
};
client.post("https://firstname.lastname.visualstudio.com/SampleApp/_apis/build/definitions?api-version=2.0", args, function (data, response) {
console.log(response.statusCode);
}).on('error', function (err) {
console.log('something went wrong on the request', err);
});
The reason is that the authentication is failed, so it redirects to the login page, that's why you get the 302 response code.
I modify the code to add Authorization to header and remove auth parameter, after that it works fine.
var args = {
data: JSON.stringify(configJSON),
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer " + accessToken
}
//, auth: {
// "Bearer":accessToken
//}
};
On the other hand, I suggest that you can create build definition through vsts-node-api or PowerShell.
For VSTS-node-api, there is createDefinition function in BuildApi (xxx), there is a sample about how to use it.
For PowerShell, you can use Invoke-RestMethod to call REST API, there are some samples in this article.

Categories

Resources