What to implement when "msal:acquireTokenFailure" is thrown? - msal

I know this should be simple, but a little help would be appreciated; we're all a bit new to using industrial strength typescript packages.
We're building an Angular App and using the #azure/msal-angular library, which for most part works OK; following the tutorials and examples and it generally all make sense.
Apart from what to implement when the "msal:acquireTokenFailure" event is broadcast?
In the ngOnInit() method of our AppComponent we have this line
// Subscriptions and redirects are for jwtTokens
this.subscription = this.broadcastService.subscribe("msal:acquireTokenFailure", () => {
// ToDo: What should be implemented here?
});
In a few posts to the GitHub page for the project contributors have suggested something along the lines of
// Subscriptions and redirects are for jwtTokens
this.subscription = this.broadcastService.subscribe("msal:acquireTokenFailure", () => {
this.subscription.unsubscribe();
this.authService.loginRedirect();
});
Which, as far as I can, will redirect to an AzuerAD login screen but will lose the underlying call details that we trying to get a Token for.
What looks more useful (in pseudo-code) would be something like
// Subscriptions and redirects are for jwtTokens
this.subscription = this.broadcastService.subscribe("msal:acquireTokenFailure", () => {
this.subscription.unsubscribe();
if (isIE) {
this.authService.acquireTokenRedirect(userRequest);
} else {
this.authService.acquireTokenPopup(userRequest);
}
});
The question being, is this a valid approach; and where would we recover the userRequest parameters from?
Please, please, don't redirect me to the Microsoft docs; I've spent hours going round in circles following the same links...

Related

Logout in case of a bad request

thanks for the amazing job you've done with AOR, this have been a great source of inspiration for me, especially in how to implement a proper redux store.
My question :
If I make a bad request, (code 400), AOR log me out of the app.
How can I prevent this and instead show a notification to my user ?
You can follow the instructions to achieve it:
import { AUTH_ERROR } from 'admin-on-rest';
export default (type, params) => {
if (type === AUTH_ERROR) {
// As I noticed, this code is executed for any error, not only for auth-one.
// So process the error as you wish (show message), don't log out.
}
// Then resolve the promise.
return Promise.resolve();
};

Sails JS: How to store and access current user data?

I already checked a lot of references and found good sources like this one: Get current user from inside the model in Sails. So I'm asking for best practices and your experiences.
As I've developed a quite complex platform based on JWT-Authentication I have to fix the major mistake to store the current user data (while user requests something) on my sails instance. I know that this leads to major security leaks (for more than one user).
The question is: How can I store and access current user data without passing the session object through almost all methods I've created?
Is passing the session object around through all helpers, utilities etc. the only way to solve this? Instead of using a centralized Service like: UserService.getCurrentUser();
Any help is highly appreciated. Thanks!
If you're asking if there's a way to globalize the user data so that it's magically available to all your methods, the short answer is that there's no safe way to do this in Node (let alone in Sails.js). Node's single-threaded nature makes it impossible to maintain state in that way.
Some folks have solved this in Sails by using a globally-applied policy that looks up the user and adds it to the request:
// api/policies/fetch-user.js
module.exports = function fetchUserPolicy (req, res, next) {
// Get the user ID out of the session.
var userId = req.session.userId;
// If there's no user logged in, just continue.
if (!userId) { return next(); }
// Look up the user by ID.
User.findOne({id: userId}).exec(function(err, user) {
if (err) { return res.serverError(err); }
if (!user) { return res.serverError(new Error('Could not find user in session!')); }
// Add the user info to the request.
req.user = user;
// Continue the request.
return next();
});
};
There's nothing wrong with this code, but we don't recommend it because best practice is to use policies purely for access control. Instead, you can do pretty much the same exact thing in a custom hook:
// api/hooks/fetch-user.js
module.exports = function fetchUserHook(sails) {
return {
// Add some routes to the app.
routes: {
// Add these routes _before_ anything defined in `config/routes.js`.
before: {
// Add a route that will match everything (using skipAssets to...skip assets!)
'/*': {
fn: function(req, res, next) {
// Get the user ID out of the session.
var userId = req.session.userId;
// If there's no user logged in, just continue.
if (!userId) { return next(); }
// Look up the user by ID.
User.findOne({id: userId}).exec(function(err, user) {
if (err) { return res.serverError(err); }
if (!user) { return res.serverError(new Error('Could not find user in session!')); }
// Add the user info to the request.
req.user = user;
// Continue the request.
return next();
});
},
skipAssets: true
}
}
}
};
};
Either way, you'll still need to pass req around to any methods that want to use the user info that was fetched.

Meteor: Make Meteor.method return a callback

New to Meteor, and I love it so far. I use vzaar.com as video hosting platform, and they have a node.js package/API which I added to my Meteor project with meteorhacks:npm. Everything in the API works great, but when I upload a video, I need to fetch the video ID from the API when successfully uploaded.
Problem:
I need to save the video id returned from the vzaar API after uploading, but since it happens in the future, my code does not wait on the result and just gives me "undefined". Is it possible to make the Meteor.method wait for the response?
Here is my method so far:
Meteor.methods({
vzaar: function (videopath) {
api.uploadAndProcessVideo(videopath, function (statusCode, data) {
console.log("Video ID: " + data.id);
return data.id;
}, {
title: "my video",
profile: 3
});
console.log(videoid);
}
});
And this is how the Meteor.call looks like right now:
Meteor.call("vzaar", "/Uploads/" + fileInfo.name, function (err, message) {
console.log(message);
});
When I call this method, I immediately get undefined in browser console and meteor console, and after some seconds, I get the video ID in the meteor console.
Solution
I finally solved the problem, after days of trial and error. I learned about Fibers (here and here), and learned more about the core event loop of Node.js. The problem were that this call answered in the future, so my code always returned undefined because it ran before the api had answered.
I first tried the Meteor.wrapAsync, which I thought were going to work, as it is actually the Future fiber. But I ended up using the raw NPM module of Future instead. See this working code:
var Future = Npm.require('fibers/future');
Meteor.methods({
vzaar: function (videopath) {
var fut = new Future();
api.uploadAndProcessVideo(videopath, function (statusCode, data) {
// Return video id
fut.return (data.id);
}, {
// Video options
title: "hello world",
profile: 3
});
// The delayed return
return fut.wait();
}
});
Remember to install the npm module correctly with meteorhacks:npm first.
I learned about how to use the Future fiber in this case via this stackoverflow answer.
I hope this can be useful for others, as it was really easy to implement.

Passport and Passport Local req.isAuthenticated always returns false

I haven't been able to track this down, but for my set up, isAuthenticated always returns false even after a successful login. Here's the passport code:
req.isAuthenticated = function() {
var property = 'user';
if (this._passport && this._passport.instance._userProperty) {
property = this._passport.instance._userProperty;
}
return (this[property]) ? true : false;
};
But in a quick look around I don't see the _userProperty proeprty anywhere in the local strategy (sorry if I didn't look hard enough), so I suppose that might be why it's always returning false?
I'd leave a code sample of my application code, but I feel it's probably easier to have a quick look at the repo for my work in progress:
passport api token sessionless
Ultimately, my goal is to have logout work properly for that boilerplate project (which it currently it doesn't).
I guess you forgot to put: req.login(...) inside passport.authenticate('local', function(...){}).
See here (at the end of the page)
Apologies if my original question is not that useful in the first place, but...
I found that my combination of passport, passport-local, and passport-local-mongoose, a solution was to simply create an invalidation method on my mongoose Schema (that has the passportLocalMongoose "plugged in", and when my /logout route gets hit I essentially remove that user's token. Here's that method:
Account.statics.invalidateUserToken = function(email, cb) {
var self = this;
this.findOne({email: email}, function(err, usr) {
if(err || !usr) {
console.log('err');
}
usr.token = null;
usr.save(function(err, usr) {
if (err) {
cb(err, null);
} else {
cb(false, 'removed');
}
});
});
};
I presume it's more interesting to see this in context so again please feel free to refer to the repo listed in question...hope this helps someone.
Also, if a core from one of the aformentioned libs wants to suggest a better way I'd of course love to refactor my code to make it idiomatic; if not, this approach seemed to work.

How do I properly handle delayed operations in Node.JS?

I'm new to ASYNC programming so please bear with me. I have a call to a web service API that can be unpredictably slow. On the front end, I can handle it with a "loading" lightbox or something. However, on the backend, I have my request:
var req = http.request( options, function(res) {
res.on('data', function(chunk) {
doStuff();
} );
res.on('end', function() {
doMoreStuff(); // This can take a while to get to.
return someInfo();
} );
} );
req.end();
All of this is in a makeRequest module. So should I pass my callback function into makeRequest and then have it run after the 'end' event? It seems like this can lead to a very long chained event structure.
So any help on how to structure this would be greatly appreciated.
note: the above is mostly pseudocode so if there are syntax errors, please understand that it's pseudocode
Yes, generally you would pass a callback into whatever function you have this in, and when 'end' is emitted, you should take the data that you collected in the request, and pass it to your callback.
I realize it's pseudocode and you may know, I just want to say it anyways. Remember that 'data' can be called more than once, and that 'return' in your end function won't do anything.
For an example of doing a request, you can look at my answer over here.
Why won't my ExpressJS properly execute a request command?

Resources