Outlook REST API 403 error while trying to fetch user emails - azure-active-directory

I am trying to fetch emails from user's outlook mail using Outlook REST API. I have been able to successfully authenticate user and get user access token, however, when I try to make an AJAX call to Outlook REST API, I get the following error:
GET https://outlook.office.com/api/v2.0/me/messages?callback=jQuery31008093694845457056_1490285639120 403 (Forbidden)
Also, I get following error from error function callback of AJAX:
Object {readyState: 4, status: 404, statusText: "error"}
Here is my code:
var ADAL = new AuthenticationContext({
instance: 'https://login.microsoftonline.com/',
tenant: 'common',
clientId: '', //Intentionally left blank here
redirectUri: 'http://localhost:8383/',
callback: userSignedIn,
popUp: true
});
function signIn() {
ADAL.login();
}
function userSignedIn(err, token) {
console.log('userSignedIn called');
if (!err) {
console.log(token); //This works!
fetchUserSentMails(token);
} else {
console.error("error: " + err);
}
}
function fetchUserSentMails(token) {
var user = ADAL.getCachedUser();
console.log(user.profile.name); //This works!
$.ajax({ //This doesn't work
type: 'GET',
crossDomain: true,
url: 'https://outlook.office.com/api/v2.0/me/messages',
dataType: 'jsonp',
headers: {'Authorization': 'Bearer ' + token},
success: function (res) {
console.log(res);
},
error: function (x, t, m) {
console.log(x);
console.log(t);
console.log(m);
}
});
}
What am I doing wrong??

The most likely answer is your token doesn't have the proper scope. Parse your token at https://jwt.io and see what you have in the scp claim.
It looks like you're missing a call to AcquireToken. The login method just signs the user in and gets their identity, it doesn't provide an access token. You need something like this:
ADAL.acquireToken("https://outlook.office.com", function(error, accessToken){
if (error) {
console.log('ERROR: ' + JSON.stringify(error));
} else {
fetchUserSentMails(accessToken);
}
}

I see that you are getting timeout error. I had the exact same issue with timeout and I could only fix this by manipulating adal.js library. In this library there is a timeout of 6 seconds and it seems like it is very tight for some applications being loaded locally. To give it a quick test, you can find LOADFRAME_TIMEOUT: '6000' in adal.js and replace it with LOADFRAME_TIMEOUT: '30000', which will give you 30 seconds to load your application. I hope it works for you!

Related

How to GET to LinkedIn API?

I am trying to retrieve user info from LinkedIn API, calling api.linkedin.com/me and sending token within axios. But I am getting 404 error - https://gyazo.com/b08b3eba1cbfd5809ede994b1af67fb5
I am able to get an access token from their API, but I stuck on getting user info
Here is a piece after I get a token I call api.linkedin.com/me like:
.then(function (response) {
axios.get('https://api.linkedin.com/me', {
headers: {
Authorization: 'Bearer ' + response.data.access_token
}
}).then(function (response) {
console.log(response)
})
})
.catch(error => {console.log(error)})
}
I need to be able to fetch data of the user, but I cannot make a valid request
Thank you in advance!
Changing the get URL to https://api.linkedin.com/v2/me should solve the problem.
I say this because https://api.linkedin.com/me redirects to a 404 page on linkedin, however, https://api.linkedin.com/v2/me returns a json response.

Cookies are not being accessible in Angular JS

I am working on login application.
For that, I am calling a backend service which is a post call. It returns a cookie. Inside cookie, there is a token. I need that token.
I am trying to get that token, but it is coming null when I try to access in using $cookie.get method.
Can anyone suggest me what could be the possible reason?
Here is the code:
$http({
url:"http://10.11.0.11:4440/j_security_check",
method:"POST",
data:data,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function successCallback(response) {
console.log("Login Success!!");
console.log( "cookie ", response.headers('Set-Cookie') ); //Returning NULL
console.log("cookies"+$cookies.get('JSESSIONID')); //Returning undefined
$location.url("/report");
}, function errorCallback() {
$scope.loginError = "Invalid username/password combination.";
$scope.result = 'error';
console.log('Login failed');
});
Here is the snap of response which I am getting in my browser's network tool:

How to pass JsonWebToken x-access-token through angular js

I created a node express RESTful API with jsonwebtoken as authentication method. But unable to pass the x-access-token as headers using angular js.
my JWT token authentication script is,
apps.post('/authenticate', function(req, res) {
// find the item
Item.findOne({
name: req.body.name
}, function(err, item) {
if (err) throw err;
if (!item)
{
res.json({ success: false, message: 'Authentication failed. item not found.' });
}
else if (item)
{
// check if password matches
if (item.password != req.body.password)
{
res.json({ success: false, message: 'Authentication failed. Wrong password.' });
}
else
{
// if item is found and password is right
// create a token
var token = jwt.sign(item, app.get('superSecret'), {
expiresIn: 86400 // expires in 24 hours
});
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
}
});
});
Middleware which checks the token is correct is,
apps.use(function(req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.params.token || req.headers['x-access-token'];
// decode token
if (token)
{
// verifies secret and checks exp
jwt.verify(token, app.get('superSecret'), function(err, decoded) {
if (err)
{
return res.json({ success: false, message: 'Failed to authenticate token.' });
}
else
{
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
}
else
{
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
Finally the GET method script is,
app.get('/display', function(req, res) {
Item.find({}, function(err, items) {
$http.defaults.headers.common['X-Access-Token']=token;
res.json(items);
});
});
But it always failed to authenticate. Please any one help me to solve this issue. I am really stucked here.
It always shows only the following authentication failed message.
{"success":false,"message":"No token provided."}
If you use $http as the dependency in your angular controller then this would help you I guess -
var token = this.AuthToken.getToken();
$http.get('/api/me', { headers: {'x-access-token': token} });
I will change this according to your code once you upload your angular code.
The client should be sending the token in the Authorization header, using the Bearer scheme, as 'X-' headers have been deprecated since 2012:
Your node would now be along the lines of:
apps.post('/authenticate', function(req, res) {
.....
var token = 'Bearer' + ' ' + jwt.sign(item, app.get('superSecret'), {
expiresIn: 86400 // expires in 24 hours
});
.....
}
apps.use(function(req, res, next) {
// Trim out the bearer text using substring
var token = req.get('Authorization').substring(7);
....
}
Then your angular code would become:
var token = this.AuthToken.getToken();
$http.get('/api/me', { headers: {'Authorization': token} });
You could create a interceptor that catches all ajax calls and injects the token into the header. That way you would not have inject it every time you make an ajax call.
This is a good place to start if you wanted to go that route:
http://www.webdeveasy.com/interceptors-in-angularjs-and-useful-examples/

How to get user.email in server using auth0 and node.js?

On my frontend, I can see the email through:
console.log(auth.profile.email)
Then I call this service to retrieve some information from the backend, it's protected so you need to be logged in to get anything back:
var metadata_req = {
method: "GET",
url: "http://localhost:80/protected/all/metadata"
}
On the backend, I'm using node.js and this to verify that the user is logged in before doing a request:
var jwtCheck = express-jwt({
secret: new Buffer(config.secret, 'base64'),
audience: config.client_id
});
But if I print out req.user, I only see iss, sub, aud, exp and iat. I would like to see the email as well.
You can get profile information in req.user by including the email permission when your user initially logs in.
For example, using lock in angular would look like this:
auth.signin({
authParams: {
scope: 'openid email'
}
}, function(profile, token) {
// stuff
}, function(err) {
// error handling
});
Change your API definition from "all/metadata" to "all/metadata/:emailId"
Call your API
var metadata_req = {
method: "GET",
url: "http://localhost:80/protected/all/metadata/{your_email_id}"
}
In NodeJS retrieve you email_id from req.params.emailId

Angular auth-0 - How to NOT send "Bearer" token in certain requests

I'm trying to wrangle the auth-0 angular plugin for JWTs and I'm stuck in a spot where I've setup the jwtInterceptor to push a JWT token into the headers of every single request made.
Here is my code:
// Send JWT with every request
jwtInterceptorProvider.tokenGetter = ['config', function(config) {
var user = JSON.parse(localStorage.getItem('ngStorage-user'));
var token = user.token;
return token;
}];
$httpProvider.interceptors.push('jwtInterceptor');
The problem is that there are a few instances where I need to make a call where I DON'T send the token in the headers of the request, such as getting the initial JWT token on registration. As of right now, with my code, if there is no JWT set, it results in an error.
One of other thought I had was to just edit each call to send the token in the headers manually, however I can't seem to get the request to work with ngResource:
function getCourseCatalog(token) {
return Registrar.checkToken($localStorage.user.token).then(function(data) {
return $resource($rootScope.APIBaseURL + 'catalog',{
query: {
method: 'GET',
isArray: true,
headers: {
Authorization: 'Bearer ' + $localStorage.user.token
}
}
});
});
}
^ With this function, the call never gets made and I'm pretty sure this is exactly how you're supposed to setup the $resource call. Is there something I'm missing? This particular call is hitting an endpoint that gets an array of objects.
It turns out that the function was missing a parameter, but additionally, I needed to still run the query() function on $resource in order to actually make the call. The new function looks like this:
function getCourseCatalog(token) {
return Registrar.checkToken($localStorage.user.token).then(function(data) {
return $resource($rootScope.APIBaseURL + 'catalog',{},{
query: {
method: 'GET',
isArray: true,
headers: {
Authorization: 'Bearer ' + $localStorage.user.token
}
}
}).query();
});
}

Resources