I would like to use a NodeJS Server to obtain the current users on my Website from Google Analytic using the Real Time Reporting API:
So far I try to do this via an HTTP request with request and gtoken. The getToken-Part works. I get a token. But the HTTP-Request doesnt work. I get an "Invalid Credentials" Error with Code 401.
Does anybody have an idea what to do? Maybe this is the completely wrong approach to get these data.
var received_token;
var url = "https://www.googleapis.com/analytics/v3/data/realtime";
var paramsObject = { ids:"ga:123456789"};
const gtoken = new GoogleToken({
keyFile: 'pathToServiceAccountJSONKeyFile:',
scope: ['https://www.googleapis.com/auth/analytics.readonly']
});
gtoken.getToken(function(err, token) {
if (err) {
console.log(err);
return;
}
received_token = token;
console.log(token);
request({
url: url,
qs: paramsObject,
headers: {
'Authorization': received_token
}
}, function(err, response, body) {
if(err) { console.log(err); return; }
// console.log(response);
console.log(body);
});
I found the error :-)
In the Authorization Header "Bearer" was missing, now it works like charm and I receive data from the Google Real Time API.
headers: {
'Authorization': "Bearer " +received_token
}
Related
*My goal here is to get the location of bikes from a bike-sharing company's API.
I did Steps 1 and 2 using Postman. but ill try to integrate it into my code once I get the hang of it.
The first step is to verify your email and generate an Auth token. This requires only a verifiable email address. Make a POST request to https://web.spin.pm/api/v1/magic_links with the body:
{"email": "sampleemail#gmail.com"}
From there, you will need to find the token within your email. This token needs to be sent with a POST request to
https://web.spin.pm/api/v1/auth_tokens with the body:
{
"grant_type": "magic_link",
"magic_link": {
"email": "<email>",
"token": "<token>"
}
}
This request returns a JSON that looks like this: {"jwt":"eyJ0eXAiOiJ.....cXVLw","refreshToken":"2cb07....bab5030","existingAccount":false}
To get the position of vehicles so a GET-Request to https://web.spin.pm/api/v3/vehicles?lng=-77.0146489&lat=38.8969363&distance=&mode= User Header Authorization: Bearer to Authenticate and use the jwt-Token we got from the Auth request.
You will get something like this as return JSON {"vehicles":[{"lat":37.69247,"lng":-122.46595,"last4":"3595","vehicle_type":"bicycle","batt_percentage":null,"rebalance":null}, … ]}
Step 3 is done using (async/awit function) using fetch where I am having the problem with. I copy-pasted the jwt in my .env file and set up the proper headers.
I get a 401 response when making the call. when I tested step 3 using postman everything seems to work fine.
I have attached a screenshot of the error in this post. Hopefully its more clear, Thanks in advance.
const fetch = require("node-fetch");
require('dotenv').config();
async function getBikes()
{
const lat = '38.897574612438575';
const lng = '-77.01855164084469';
const api_url = `https://web.spin.pm/api/v3/vehicles?lng=${lng}&lat=${lat}&distance=&mode=`;
const jwt_key = process.env.BERER_KEY;
try{
const config = { method: 'GET',
headers: {json: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer'+ jwt_key
} },
rejectUnauthorized: false
};
const response = await fetch(api_url,config );
const data = await response.json(); //response.json() //headers //.jwt; //response.json()
if (response.ok)
{
console.log("STATUS CODE IS: "+response.status);
console.log('My JWT:', response);
return data;
}
else{
console.log("something went wrong ");
console.log("STATUS CODE IS: "+ response.status);
console.log( response);
}
} catch (error) {
console.log(error);
}
}
const y = getBikes();
console.log(y)
BEARER_KEY=eyJhbGciOiJIUzI1NiJ9.eyJ1c2V
Hi All,
I got a scenario in which i am supposed to call a REST api that is secured by a AZURE ACTIVE DIRECTORY. Most of the code runs fine and i am able to get the token using myMSALObj.acquireTokenSilent function too.
401 ERROR COMES WHEN I SEND AJAX CALL USING THAT TOKEN, YOU CAN SEE FOLLOWING CODE
User is there in Active Directory for which i get proper token, i dont know why my ajax call fails when i send that token to rest-api, please help
<script type="text/javascript">
const msalConfig = {
auth: {
clientId: "94edf294-08ae-489f-8621-c6d98009afa8",
authority: "https://login.microsoftonline.com/c483b3c4-21a6-4c93-95ea-7436cf318a68",
redirectUri: "https://localhost:44334/",
},
cache: {
cacheLocation: "sessionStorage", // This configures where your cache will be stored
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
}
};
const myMSALObj = new Msal.UserAgentApplication(msalConfig);
function CallApi() {
// Add scopes for the id token to be used at Microsoft identity platform endpoints.
const loginRequest = {
scopes: ["User.Read"],
};
myMSALObj.loginPopup(loginRequest)
.then((loginResponse) => {
const accessTokenRequest = {
scopes: ["api://8c2b0253-f9e8-442c-bccf-b4a8bbe73b59/access_as_user"]
};
myMSALObj.acquireTokenSilent(accessTokenRequest).then((accessTokenResponse) => {
var accessToken = accessTokenResponse.accessToken;
var apiEndpoint = "https://localhost:44387/api/hello";
var bearer = "Bearer " + accessToken;
console.log("accessToken = ", accessToken);
$.ajax({
url: apiEndpoint,
type: "GET",
beforeSend: function (xhr) { xhr.setRequestHeader("Authorization", bearer) }
}).done(function (response) {
alert("SUCCESS");
console.log("response = ", JSON.stringify(response));
}).fail(function (err) {
console.error("Error Occurred");
console.log("error = ", JSON.stringify(err));
});
})
}).catch(function (error) {
console.log(error);
});
}
</script>
Screenshot of a NEW API Code
Screenshot of JWT.ms (Access Token)
New Screenshot of JWT Token
You should not set the client ID in the appsettings.json file to the client id of your api app. It should be the client id of your client app. According to the jwt analysis diagram you provided, I think it should be: 94edf294- 08ae-489f-8621-c6xxxxxxx.
My bad, Following call was missing in my startup.cs file
app.UseAuthentication();
thanks for your help guys
Specially - #Carl Zhao, #Purushothaman #Rass Masood
I am new to Alexa Skill / Lambda. I am trying to print the body of my request. I have tried using fetch with isomorphic-unfetch and now I am trying to use the npm request module. For some reason I cannot get the request body to print in CloudWatch Logs, everything else I am log shows up fine. I am also not getting an error because I am logging that too and it is not showing up. What am I doing wrong? I am using account linking and I know that I have the user accessToken and I am using that token to verify who the user is by hitting another endpoint so I know I have the token and the method I have works if I run it locally and with just node but as soon as I try and log the body in on aws/lambda CloudWatch I cant get the body of the request to log so im not sure if its working. Now when I mean it works locally I mean I remove ${event.session.user.accessToken} and hardcode in the access token then run node index.js and then I can see the body of the request.
All help is welcome. Thanks!
let skill;
exports.handler = async function (event, context) {
getUserInfo(event);
console.log(`REQUEST++++${JSON.stringify(event)}`);
if (!skill) {
skill = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
CreateQuoteIntent,
SessionEndedRequestHandler,
)
.addErrorHandlers(ErrorHandler)
.create();
}
// console.log("SESSION**** " + event.session.user.accessToken);
const response = await skill.invoke(event, context);
console.log(`RESPONSE++++${JSON.stringify(response)}`);
return response;
};
function getUserInfo(event) {
console.log("TOKEN: " +event.session.user.accessToken);
const options = {
url: 'not showing url but api url is fine ',
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Client-ID': 'not showing me key on stack',
'Authorization': `OAuth ${event.session.user.accessToken}`
}
};
console.log('BEFORE REQUEST');
request(options, function(err, res, body) {
console.log("ERROR: " + err);
// let json = JSON.parse(body);
console.log("BODY: " + body);
});
console.log('AFTER REQUEST');
}
I want to fetch my tasks within Javascript and possibly add new ones, but let's focus on fetching a task.
I made an app and use the msal.js file to get a token. I get prompted to allow the app to read/write from my account, the popup closes and I've obtained a token!
So far so good, but when I try to fetch my tasks the API responds with "unauthorized". When I check the headers I can see I sent along "bearer [token]" however.
I'm completely clueless on how to get my tasks by now since I did get a proper token and I've followed the guided setup to make sure I send along the token.
In my app (which I created on https://apps.dev.microsoft.com) I've set all Task related permissions and User.read for good measure. As for the platform I've set "Web".
Is there something I'm missing or mis-configuring?
My init method:
const self = this
this.userAgentApplication = new Msal.UserAgentApplication(this.clientID, null, function (errorDes, token, error, tokenType) {
// this callback is called after loginRedirect OR acquireTokenRedirect (not used for loginPopup/aquireTokenPopup)
})
this.userAgentApplication.loginPopup(['Tasks.readwrite']).then(function (token) {
let user = self.userAgentApplication.getUser()
if (user) {
self.token = token
localStorage.setItem('token', token)
self.getTasks()
}
}, function (error) {
console.log(error)
})
My getTasks method:
const bearer = 'Bearer ' + this.token
let headers = new Headers()
headers.append('Authorization', bearer)
let options = {
method: 'GET',
headers: headers
}
// Note that fetch API is not available in all browsers
fetch('https://outlook.office.com/api/v2.0/me/tasks', options).then(function (response) {
let contentType = response.headers.get('content-type')
if (response.status === 200 && contentType && contentType.indexOf('application/json') !== -1) {
response.json().then(function (data) {
console.log(data)
})
.catch(function (error) {
console.log(error)
})
} else {
response.json().then(function (data) {
console.log(data)
})
.catch(function (error) {
console.log(error)
})
}
})
.catch(function (error) {
console.log(error)
})
Your token is scoped for Graph, not Outlook. Tasks.readwrite will default to the Microsoft Graph and won't work against the Outlook endpoint.
Change this bit:
this.userAgentApplication.loginPopup(['Tasks.readwrite'])
To:
this.userAgentApplication.loginPopup(['https://outlook.office.com/Tasks.readwrite'])
You are trying to use Microsoft Graph, so the request should look like
GET https://graph.microsoft.com/beta/users/{id|userPrincipalName}/outlook/tasks
It's documented here:https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/outlookuser_list_tasks
I believe you got a Microsoft Graph token but you're trying to use it on the Outlook REST endpoint, which would not work.
Couldn't find any documentation on this, so before I dig deep in code does anyone out there know how to use basic authentication when making a REST request using 'fetch' (https://github.com/github/fetch).
Just tried the following line, but the header was not set in the request:
fetch('http://localhost:8080/timeEntry', {
mode: 'no-cors',
headers: { 'Authorization': 'Basic YW5kcmVhczpzZWxlbndhbGw=' }
})
.then(checkStatus)
.then(parseJSON)
.then(function(activities) {
console.log('request succeeded with JSON response', data);
dispatch(activitiesFetched(activities, null));
}).catch(function(error) {
console.log('request failed', error);
dispatch(activitiesFetched(null, error));
});
The username and password is my own first and last name, using curl it works.
If I put { 'Accept' : 'application/test' } Accept is set, just not Authorization... strange.
Just for me to able to continue I added credentials: 'include' which makes the browser to prompt for username and password which is used for communicationg with the REST backend. Just for testing, will use OAuth further on.
fetch('http://localhost:8080/timeEntry', {
mode: 'no-cors',
credentials: 'include'
})
.then(checkStatus)
.then(parseJSON)
.then(function(activities) {
console.log('request succeeded with JSON response', data);
dispatch(activitiesFetched(activities, null));
}).catch(function(error) {
console.log('request failed', error);
dispatch(activitiesFetched(null, error));
});
no-cors mode prevents the headers from being anything other than simple headers.
"Authorization" header doesn't fit to simple headers. See more here: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
Note that if you use fetch with Authorization header you will NOT establish a session. You will have to manually add that header for every request. Navigating to secured path would also not be possible.
So to make this work You should pre-authenticate with XMLHttpRequest. You can do this like so:
var authUrl = location.origin + '/secured-path/';
var http = new XMLHttpRequest();
http.open("get", authUrl, false, login, pass);
http.send("");
if (http.status == 200) {
//location.href = authUrl;
} else {
alert("⚠️ Authentication failed.");
}
Note that above is synchronous so you don't need a callback here.
So after doing this you can use fetch without headers e.g. this request should be successful:
fetch(authUrl, {
method: 'get',
}).then(function(response) {
console.log(response);
});
Since it looks like the library you are using is a polyfill for Fetch API, I'm going to work off of the assumption that the syntax should carry through as well.
The samples I found on Mozilla's page indicate that the fetch method signature is fetch('API_ENDPOINT', OBJECT) where object looks like:
myHeaders = new Headers({
"Authorization": "Basic YW5kcmVhczpzZWxlbndhbGw="
});
var obj = {
method: 'GET',
headers: myHeaders
})
So the method becomes:
fetch('http://localhost:8080/timeEntry', obj)
.then(checkStatus)
.then(parseJSON)...
I have not tested this code, but it seems consistent with what I was able to find. Hope this points you in the right direction.