I'm trying to build a home automation system by myself. For this, I use the Blynk server to control my hardware. I can control my hardware by requesting the URL of the blynk server.
For example: When I make a request to https://139.59.206.133/myprivatekey/update/V1?value=1 and update a Virtual Pin to "1" and my light turns on.
I used this to make an Alexa custom skill which is able to turn my light on by making an HTTPS request to the Blynk server. For example when I say "Alexa ask my Room to turn the light on". The custom Skill is working how it should.
But a Custom skill is not really what I was looking for, so I decided to build an Alexa Smart Home Skill. So I set one up and simply tried to make an HTTPS request when "TurnON" or "TurnOFF" is called.
My problem is that every time I try to make an HTTPS request Alexa says that the device is not responding.
I tried a lot of things, but I couldn't solve my problem on my own.
Code:
The Code is from the node.js Alexa Smart Home Example.
exports.handler = function (request, context) {
if (request.directive.header.namespace === 'Alexa.Discovery' && request.directive.header.name === 'Discover') {
log("DEBUG:", "Discover request", JSON.stringify(request));
handleDiscovery(request, context, "");
}
else if (request.directive.header.namespace === 'Alexa.PowerController') {
if (request.directive.header.name === 'TurnOn' || request.directive.header.name === 'TurnOff') {
log("DEBUG:", "TurnOn or TurnOff Request", JSON.stringify(request));
handlePowerControl(request, context);
}
}
function handleDiscovery(request, context) {
var payload = {
"endpoints":
[
{
"endpointId": "demo_id",
"manufacturerName": "Smart Device Company",
"friendlyName": "Zimmerlicht",
"description": "Smart Device Switch",
"displayCategories": ["SWITCH"],
"cookie": {
"key1": "arbitrary key/value pairs for skill to reference this endpoint.",
"key2": "There can be multiple entries",
"key3": "but they should only be used for reference purposes.",
"key4": "This is not a suitable place to maintain current endpoint state."
},
"capabilities":
[
{
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
},
{
"interface": "Alexa.PowerController",
"version": "3",
"type": "AlexaInterface",
"properties": {
"supported": [{
"name": "powerState"
}],
"retrievable": true
}
}
]
}
]
};
var header = request.directive.header;
header.name = "Discover.Response";
log("DEBUG", "Discovery Response: ", JSON.stringify({ header: header, payload: payload }));
context.succeed({ event: { header: header, payload: payload } });
}
function log(message, message1, message2) {
console.log(message + message1 + message2);
}
function handlePowerControl(request, context) {
// get device ID passed in during discovery
var requestMethod = request.directive.header.name;
var responseHeader = request.directive.header;
responseHeader.namespace = "Alexa";
responseHeader.name = "Response";
responseHeader.messageId = responseHeader.messageId + "-R";
// get user token pass in request
var requestToken = request.directive.endpoint.scope.token;
var powerResult;
if (requestMethod === "TurnOn") {
const Http = new XMLHttpRequest();
const url='https://139.59.206.133/myprivatekey/update/V1?value=1';
Http.open("GET", url);
Http.send();
// Make the call to your device cloud for control
// powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
powerResult = "ON";
}
else if (requestMethod === "TurnOff") {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", 'http://myprivatekey/update/V0?value=0', false ); // false for synchronous request
xmlHttp.send( null );
// Make the call to your device cloud for control and check for success
// powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
powerResult = "OFF";
}
var contextResult = {
"properties": [{
"namespace": "Alexa.PowerController",
"name": "powerState",
"value": powerResult,
"timeOfSample": "2017-09-03T16:20:50.52Z", //retrieve from result.
"uncertaintyInMilliseconds": 50
}]
};
var response = {
context: contextResult,
event: {
header: responseHeader,
endpoint: {
scope: {
type: "BearerToken",
token: requestToken
},
endpointId: "demo_id"
},
payload: {}
}
};
log("DEBUG", "Alexa.PowerController ", JSON.stringify(response));
context.succeed(response);
}
};
My Requests:
if (requestMethod === "TurnOn") {
const Http = new XMLHttpRequest();
const url='https://139.59.206.133/myprivatekey/update/V1?value=1';
Http.open("GET", url);
Http.send();
// Make the call to your device cloud for control
// powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
powerResult = "ON";
}
else if (requestMethod === "TurnOff") {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", 'http://myprivatekey/update/V0?value=0', false ); // false for synchronous request
xmlHttp.send( null );
// Make the call to your device cloud for control and check for success
// powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
powerResult = "OFF";
}
Additional Info:
Programming language node.js
account linking, IAM role, and everything to create a smart home skill should be set up right
I am rather new to Alexa Skill building, and I'm also not very good at JavaScript.
If the request went through, I mean your code is being called, and light is being turned on/off, the problem is with the response.
My guess is that you are missing correlation id.
you need to add something like:
responseHeader.correlationToken = request.directive.header.correlationToken;
You should also implement the EndpointHealth: https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-endpointhealth.html
Related
I am trying to make a console app in C# through which I want to migrate more than 100000 users to Azure AD B2C.
We are using Graph API for this purpose.
My current approach creates a single user account per API call and it takes more than 12 hours to migrate around 50000 users.
To reduce the overall time I want to send data in bulk instead of one by one using the API. But, I am unable to find any solution for it.
Is there an API endpoint available for creating users in batch. Please help.
Also, If I want to delete these users in batch. Is it possible to do that?
Here are some Microsoft docs references which I have used for implementing my solution.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-user-migration?tabs=applications
https://learn.microsoft.com/en-us/previous-versions/azure/ad/graph/api/users-operations#CreateLocalAccountUser
You can use JSON batching to combine multiple requests in one HTTP call.
Here is an example:
POST https://graph.microsoft.com/v1.0/$batch
{
"requests": [{
"id": "1",
"method": "POST",
"url": "/users",
"body": {
"accountEnabled": true,
"displayName": "allentest01",
"mailNickname": "allentest01",
"userPrincipalName": "allentest01#{tenant}.onmicrosoft.com",
"passwordProfile": {
"forceChangePasswordNextSignIn": true,
"password": "{password-value}"
}
},
"headers": {
"Content-Type": "application/json"
}
}, {
"id": "2",
"method": "POST",
"url": "/users",
"body": {
"accountEnabled": true,
"displayName": "allentest02",
"mailNickname": "allentest02",
"userPrincipalName": "allentest02#{tenant}.onmicrosoft.com",
"passwordProfile": {
"forceChangePasswordNextSignIn": true,
"password": "{password-value}"
}
},
"headers": {
"Content-Type": "application/json"
}
}
]
}
You can also delete user with it. (use DELETE method)
Just to add onto the Allen Wu Answer. This is how you would use it in c# for example.
string json = #"
{
""requests"": [{
""id"": ""1"",
""method"": ""POST"",
""url"": ""/users"",
""body"": {
""accountEnabled"": true,
""displayName"": ""zetawarsTest01"",
""mailNickname"": ""zetawarstest01"",
""userPrincipalName"": ""zetawarstest01#projecttarget.onmicrosoft.com"",
""passwordProfile"": {
""forceChangePasswordNextSignIn"": false,
""password"": ""zetawars123!##""
}
},
""headers"": {
""Content-Type"": ""application/json""
}
}, {
""id"": ""2"",
""method"": ""POST"",
""url"": ""/users"",
""body"": {
""accountEnabled"": true,
""displayName"": ""zetawarsTest02"",
""mailNickname"": ""zetawarsTest02"",
""userPrincipalName"": ""zetawarsTest02#projecttarget.onmicrosoft.com"",
""passwordProfile"": {
""forceChangePasswordNextSignIn"": false,
""password"": ""zetawars123!##""
}
},
""headers"": {
""Content-Type"": ""application/json""
}
}
]
}
";
//Credentials
var tenantId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var scopes = new string[] { "https://graph.microsoft.com/.default" };
//This to get the Access Token
var confidentialClient = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
.WithClientSecret(clientSecret)
.Build();
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build();
var result = await confidentialClientApplication
.AcquireTokenForClient(new string[] { "https://graph.microsoft.com/.default" })
.ExecuteAsync(); ;
// This is to send Json Request using Client
using (HttpClient http = new HttpClient())
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/$batch"))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
if (!string.IsNullOrEmpty(json))
{
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
}
using (HttpResponseMessage response = await http.SendAsync(request))
{
string error = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == (HttpStatusCode)429)
{
// TBD: Add you error handling here
}
throw new Exception(error);
}
await response.Content.ReadAsStringAsync();
}
}
I have read that there is limit of 20 users/request in batch. But i haven't tested that out yet.
The approach of using JSON batching seems more reasonable but last time we had imported 160,000 users to Azure AD B2C via Graph API using Parallel.ForEach loop with MaxDegreeOfParallelism to 10. We were providing a batch of 40,000 users per run. It took 30 minutes to migrate 40,000 users batch.
I'm trying to call appsync from a lambda function that I set up using aws amplify. I can tell that my lambda function has read/write permission for appsync, but when I make the POST request from lambda to appsync, I get a Unable to parse JWT token error. The weird thing is that when I look at the header, I don't see the authorization jwt that I see when I am requesting from the web application, so that could be why I'm seeing this error. Instead, I see an x-amz-security-token and a different type of authorization string that you can see in the image below.
My code is pulled from a blog I found from Adrian Hall:
const env = require('process').env
const fetch = require('node-fetch')
const URL = require('url')
const AWS = require('aws-sdk')
AWS.config.update({
region: env.AWS_REGION,
credentials: new AWS.Credentials(
env.AWS_ACCESS_KEY_ID,
env.AWS_SECRET_ACCESS_KEY,
env.AWS_SESSION_TOKEN
),
})
exports.handler = (event, context, callback) => {
const ListCourses = `query ListCourses(
$filter: ModelTodoFilterInput
$limit: Int
$nextToken: String
) {
listCourses(filter: $filter, limit: $limit, nextToken: $nextToken) {
items {
id
}
nextToken
}
}`
// const details = {
// userId: event.request.userAttributes.sub,
// userDetails: {
// name: event.request.userAttributes.name,
// },
// }
const post_body = {
query: ListCourses,
operationName: 'ListCourses',
variables: details,
}
console.log(env)
console.log(`Posting: ${JSON.stringify(post_body, null, 2)}`)
// POST the GraphQL mutation to AWS AppSync using a signed connection
const uri = URL.parse(env.API_GRAPHQLAPIENDPOINTOUTPUT)
const httpRequest = new AWS.HttpRequest(uri.href, env.REGION)
httpRequest.headers.host = uri.host
httpRequest.headers['Content-Type'] = 'application/json'
httpRequest.method = 'POST'
httpRequest.body = JSON.stringify(post_body)
AWS.config.credentials.get(err => {
const signer = new AWS.Signers.V4(httpRequest, 'appsync', true)
signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate())
const options = {
method: httpRequest.method,
body: httpRequest.body,
headers: httpRequest.headers,
}
console.log('here is the uri and options')
console.log(uri.href)
console.log(options)
fetch(uri.href, options)
.then(res => res.json())
.then(json => {
console.log(`JSON Response = ${JSON.stringify(json, null, 2)}`)
callback(null, event)
})
.catch(err => {
console.error(`FETCH ERROR: ${JSON.stringify(err, null, 2)}`)
callback(err)
})
})
}
Does anyone know why the credentials methods are authorizing the way that they are and how I can fix this UnauthorizedException error? Just to sanity check me, in amplify, I did select that I wanted this lambda function to have read/write access and I can see in the CF template that:
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:Create*",
"appsync:StartSchemaCreation",
"appsync:GraphQL",
"appsync:Get*",
"appsync:List*"
],
"Resource": [
{
"Fn::Join": [
"",
[
"arn:aws:appsync:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":apis/",
{
"Ref": "apiGraphQLAPIIdOutput"
},
"/*"
]
]
}
]
}
]
}
You would have to use AWS_IAM as the authorization mode for your API if you want to call it from the lambda. Based on the error, it seems your API is setup to use AMAZON_COGNITO_USER_POOLS as the authorization. If you want to mix the 2 in your API, you might want to look at the following blog:
https://aws.amazon.com/blogs/mobile/using-multiple-authorization-types-with-aws-appsync-graphql-apis/
I have problems with the discovery of devices of my Alexa Smart Home skill.
Steps which work:
activate Alexa skill
OAuth login screen appears. After successful login, the discovery of devices is triggered
in the lambda function I get the bearer token which I use to call the .../devices endpoint
I get the devices from the REST endpoint and construct the payload as described in https://developer.amazon.com/de/docs/smarthome/steps-to-build-a-smart-home-skill.html
The payload (same structure as in the example) is provided to context.succeed
My problem:
After the Alexa Skill returns from discovery of devices task, no new devices are visible in the Alexa Skill.
When I use the code from the sample (where no request to an external Rest API happens), the device is visible in the Alexa skill after the Alexa discovery task.
var https = require('https');
const AWS = require('aws-sdk');
exports.handler = function(request, context) {
var options = {
method: 'GET',
hostname: 'xyz.azurewebsites.net',
path: '/devices',
headers: {
Authorization: 'Bearer ' + request.directive.payload.scope.token,
'Content-Type': 'application/json'
}
};
var req = https.get(options, (response) => {
var data = '';
response.setEncoding('utf8');
response.on('data', function(x) { data += x; } );
response.on('error', console.error);
response.on('end', () => {
var dataObj = JSON.parse(data);
console.log("Retrieved response: " + JSON.stringify(dataObj.items));
const payload = {
"endpoints": []
};
dataObj.items.forEach(item => {
const device = {
"endpointId": item.id,
"manufacturerName": item.manufacturer,
"friendlyName": item.displayName,
"description": item.description,
"displayCategories": ["SWITCH"],
"cookie": {
"key1": "arbitrary key/value pairs for skill to reference this endpoint.",
"key2": "There can be multiple entries",
"key3": "but they should only be used for reference purposes.",
"key4": "This is not a suitable place to maintain current endpoint state."
},
"capabilities":
[
{
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
},
{
"interface": "Alexa.PowerController",
"version": "3",
"type": "AlexaInterface",
"properties": {
"supported": [{
"name": "powerState"
}],
"retrievable": true
}
}
]
};
payload.endpoints.push(device);
});
console.log('payload ' + JSON.stringify(payload));
var header = request.directive.header;
header.name = "Discover.Response";
console.log("DEBUG", "Discovery Response: ", JSON.stringify({ header: header, payload: payload }));
//NEXT LINE IS EXECUTED WITHOUT ANY ERROR
context.succeed({ event: { header: header, payload: payload } });
});
});
req.on('error', (e) => {
console.log('problem with request: ' + e.message);
});
};
I found the problem...
The value of the property 'endpointId' contained a '#'. Then I changed the name to only letters, and it worked.
Although in this article it says '#' can be used, the discovery of devices then has problems.
Hope this answer helps others from wasting time...
I found another cause for the same symptom: for the entity's additionalAttributes (manufacturer, model etc.), one cannot use non-English characters. You can actually use any character ASCII from 32 to 126 (space to tilde), but you cannot use the backslash. So, no accent characters (international or extended ASCII) allowed.
On the other hand, I could include a entity with '#' inside its endpointId. I cannot explain why you couldn't.
I am still new to Node Js. Please help me out.
I am calling a web service and based on its results I need to call another web service. The code is given below, however, I am not sure how to call the second web service (ex: foo()).
The 2nd method (That calls the 2nd web service) accepts 2 parameter:
Subject
Body
I need to call the web service 'https://somenew.com/v1/', and need to pass the following as headers as well :
`Content-Type : application/json`
Then As the body I need to pass the following properties :
"name": "My name is alex",
"gender": ["All"],
"Subject": "french",
"Body": "men",
"arrayOfLikes": {"sf": "tennis"}
// 1st Method
app.post('/createthehospital/',function(req,res){
var hos = req.body;
Hos.create(hos, function(err,hos){
if(err){
// Do nothing
} else {
foo('Subject', 'Body'); // CALLING NEW METHOD
}
}
})
});
// 2nd Method
function foo(subject,body) {
app.post('https://somenew.com/v1/',function(req,res){
});
}
You need to use request module
var request = require('request');
request.post({
url: 'https://somenew.com/v1/',
headers: {
'content-type': 'application/json',
},
json: {
"name": "My name is alex",
"gender": ["All"],
"Subject": "french",
"Body": "men",
"arrayOfLikes": {
"sf": "tennis"
}
}
}, function(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // your response body
}
})
the mistake you have made use express instance app to make call to external url that is not possible use above module to do so.
I can't get a user's id_token (https://developers.google.com/accounts/docs/CrossClientAuth) from the Chrome identity api (https://developer.chrome.com/apps/identity).
I can get an access_token using the chrome identity sample when the oauth section in the manifest is:
"oauth2": {
"client_id": "<chrome-app-client-id>.apps.googleusercontent.com",
"scopes": ["https://www.googleapis.com/auth/plus.login"]
}
But when I try to get the id_token the same way I get it on my android client a get the error:
"OAuth2 request failed: Service responded with error: 'invalid scope: {0}'"}
The manifest section is now:
"oauth2": {
"client_id": "<chrome-app-client-id>.apps.googleusercontent.com",
"scopes": ["audience:server:client_id:<app-engine-client-id>.apps.googleusercontent.com"]
}
On Android I get the id_token by passing the same scope string to android.gms.auth.GoogleAuthUtil.getToken(), but I can't get it to work with the chrome identity api.
Is it possible to get an id_token with Chrome App Indentity Api? If not, how can I get an id_token for my Chrome app?
Thanks for your help!
I've came to the same problem yesterday and since I've found a solution, I might as well share it, as it wasn't that obvious. As far as i know Google does not provide a direct and documented way to do this, but you can use the chrome.identity.launchWebAuthFlow() function.
First you should create an Web application credentials in google console and add the following url as a valid Authorized redirect URI: https://<EXTENSION_OR_APP_ID>.chromiumapp.org. The URI does not have to exist, chrome will just catch the redirect to this URL and call your callback function later.
manifest.json:
{
"manifest_version": 2,
"name": "name",
"description": "description",
"version": "0.0.0.1",
"background": {
"scripts": ["background.js"]
},
"permissions": [
"identity"
],
"oauth2": {
"client_id": "<CLIENT_ID>.apps.googleusercontent.com",
"scopes": [
"openid", "email", "profile"
]
}
}
background.js:
// Using chrome.identity
var manifest = chrome.runtime.getManifest();
var clientId = encodeURIComponent(manifest.oauth2.client_id);
var scopes = encodeURIComponent(manifest.oauth2.scopes.join(' '));
var redirectUri = encodeURIComponent('https://' + chrome.runtime.id + '.chromiumapp.org');
var url = 'https://accounts.google.com/o/oauth2/auth' +
'?client_id=' + clientId +
'&response_type=id_token' +
'&access_type=offline' +
'&redirect_uri=' + redirectUri +
'&scope=' + scopes;
chrome.identity.launchWebAuthFlow(
{
'url': url,
'interactive':true
},
function(redirectedTo) {
if (chrome.runtime.lastError) {
// Example: Authorization page could not be loaded.
console.log(chrome.runtime.lastError.message);
}
else {
var response = redirectedTo.split('#', 2)[1];
// Example: id_token=<YOUR_BELOVED_ID_TOKEN>&authuser=0&hd=<SOME.DOMAIN.PL>&session_state=<SESSION_SATE>&prompt=<PROMPT>
console.log(response);
}
}
);
Google OAuth2 API (for OpenID Connect) documentation can be found here: https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters
PS: If you don't need the oauth2 section in your manifest. You can safely omit it, and provide the identifiers and scopes in code only.
EDIT:
For those interested, you don't need the identity API. You can even access the token using a little trick with tabs API. The code is a little longer, but you have better error messages and control. Keep in mind that in the following example, you need to create Chrome App credentials.
manifest.json:
{
"manifest_version": 2,
"name": "name",
"description": "description",
"version": "0.0.0.1",
"background": {
"scripts": ["background.js"]
},
"permissions": [
"tabs"
],
"oauth2": {
"client_id": "<CLIENT_ID>.apps.googleusercontent.com",
"scopes": [
"openid", "email", "profile"
]
}
}
background.js:
// Using chrome.tabs
var manifest = chrome.runtime.getManifest();
var clientId = encodeURIComponent(manifest.oauth2.client_id);
var scopes = encodeURIComponent(manifest.oauth2.scopes.join(' '));
var redirectUri = encodeURIComponent('urn:ietf:wg:oauth:2.0:oob:auto');
var url = 'https://accounts.google.com/o/oauth2/auth' +
'?client_id=' + clientId +
'&response_type=id_token' +
'&access_type=offline' +
'&redirect_uri=' + redirectUri +
'&scope=' + scopes;
var RESULT_PREFIX = ['Success', 'Denied', 'Error'];
chrome.tabs.create({'url': 'about:blank'}, function(authenticationTab) {
chrome.tabs.onUpdated.addListener(function googleAuthorizationHook(tabId, changeInfo, tab) {
if (tabId === authenticationTab.id) {
var titleParts = tab.title.split(' ', 2);
var result = titleParts[0];
if (titleParts.length == 2 && RESULT_PREFIX.indexOf(result) >= 0) {
chrome.tabs.onUpdated.removeListener(googleAuthorizationHook);
chrome.tabs.remove(tabId);
var response = titleParts[1];
switch (result) {
case 'Success':
// Example: id_token=<YOUR_BELOVED_ID_TOKEN>&authuser=0&hd=<SOME.DOMAIN.PL>&session_state=<SESSION_SATE>&prompt=<PROMPT>
console.log(response);
break;
case 'Denied':
// Example: error_subtype=access_denied&error=immediate_failed
console.log(response);
break;
case 'Error':
// Example: 400 (OAuth2 Error)!!1
console.log(response);
break;
}
}
}
});
chrome.tabs.update(authenticationTab.id, {'url': url});
});
First, I assume that in your manifest.json snippet you don't mean that your client_id is literally "<chrome-app-client-id>.apps.googleusercontent.com. It should be something like 9414861317621.apps.googleusercontent.com -- something you got from the Developer Console, or whatever Google site you used to register the app.
Assuming the above is OK, and you have the client_id right, and the scope right, you get what's called an "OAuth2 access token" with a call to chrome.identity.getAuthToken. As you don't show us any JavaScript code, I can't tell if this is what you're doing. The access token you get you need to save for subsequent use when you call an API function. For example:
var access_token;
chrome.identity.getAuthToken(
{
'interactive': true
},
function(token) {
access_token = token;
// do something if you like to indicate
// that the app is authorized
}
);
Then, when you make an API call, you supply that access token, like this:
var url = 'https://www.googleapis.com/' + method;
Ajax.ajaxSend(url, "json",
function (status, response) {
if (response && response.error && response.error.message)
errorCallback(response.error.message);
else if (status == 200)
successCallback(response);
else
errorCallback('Result code: ' + status);
},
function (e) {
if (errorCallback)
errorCallback('Communication error');
},
{
Authorization: 'Bearer ' + access_token
}
);
Ajax.ajaxSend is my own function:
var Ajax = (function () {
var api = {
ajaxSend: function (url, responseType, successCallback, errorCallback, headers) {
var req = new XMLHttpRequest();
req.onload = function (e) {
successCallback(req.status, req.response);
};
req.onerror = errorCallback;
req.responseType = responseType ? responseType : "text";
req.open("get", url);
if (headers)
for (var v in headers)
req.setRequestHeader(v, headers[v]);
req.send();
}
};
return api;
})();
The other undefined functions also are what you'd expect. The third argument to Ajax.ajaxSend is a header to be sent along. (Sorry, I don't have time to develop standalone code just for this answer.)
I hope the above is useful.
I guess it depends on why one would want token id, but in my case
access_token was enough to authorize user - by pulling user info from https://www.googleapis.com/oauth2/v2/userinfo?alt=json ( with Authorization header = access_token).