User authentication with Vue.js 2 and Express.js with Passport - angularjs

I need to set up an authentication system with Node.js Express framework and Vue.js. I saw up to now solutions only with JWT. It would be nice for me to found a solution as this in AngularJS, with promises: https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs .
Is it possible with Vue.js router or somehow otherwise to set up a resolve parameter with promise function as in this guide with AngularJS?
Thank you!

I am currently looking into this myself, and having worked with vue-router a little bit I think that router.beforeEach might do the trick: https://router.vuejs.org/en/advanced/navigation-guards.html
The way I see it is that a promise inside beforeEach route guard would be calling the backend api route and in case of success would be resolved and navigation to our route can continue, in case it's rejected - user's redirected to login route.
Will respond later once I've looked into this propertly myself as I'm still learning. Let me know if you have learnt anything about it since you've created this question.

Related

How to deal with extra hash in route? (AngularJS 1.5 + new/component router)

We're attempting to build an app using Angular 1.5 with the new component router bits. We've run into a bit of an edge case and we're wondering if there's any way around it.
The Key Players
IdentityServer v2: our client uses this for OAuth currently. It causes a part of this problem. It's legacy, and we don't have control over its usage.
AngularJS 1.5 as our front-end framework.
The new angular router, called ngComponentRouter now I believe? We figured this style would help us bridge between Angular v1.5 and Angular v2, and it was easy enough to port.
oauth-ng as a wrapper for our OAuth implicit flow..
Older browsers: In the sense that we have to support IE9+, meaning we can't use Angular's HTML5 mode.
The Goal
We'd like to take a URL such as http://mysite/#!/auth/#auth_token=xyz123 (structure not under our control, e.g. can't remove second hash) and:
Get it into an actual auth controller
Have the auth_token value available, either through parameters or directly through $location. (it currently is scrubbed before it ever gets to the controller).
Background / Problem
Our client has a central login system where they're using IdentityServer v2. As far as I understand, when we request a token from IdSrv v2, it responds by appending #auth_token=xyz123 to your redirect URL. It was written back when it thought you'd have my.com/login.html, thus resulting in login.html#auth_token=xyz123.
With an Angular app that uses a hash already, though, it becomes a problem, as the URL ends up along the lines of mysite.com/#/auth#auth_token=xyz123.
This, as you might expect, makes Angular angry. We have yet be able to find a way to get this to work under the component router.
How it Would Work With the Older Routers
Per the oauth-ng docs, if we were using the older router without html5 enabled, we'd do something like the following:
angular.module('app').config(function ($routeProvider) {
$routeProvider
.when('/access_token=:accessToken', {
template: '',
controller: function ($location, AccessToken) {
var hash = $location.path().substr(1);
AccessToken.setTokenFromString(hash);
$location.path('/');
$location.replace();
}
})
What We've Tried
Defining a component route in a similar way. This didn't work, because /access_token=:accessToken contains an =, which doesn't appear to be allowed by component router.
Seeing if we can get IdentityServer v2 to change the format of the response. It doesn't seem like it's possible; the response seems to be hard-coded to [URL we define]#auth_token=xyz123.
Faking out the URL using other hashes, etc. Generally wound up with bad / inconsistent behavior.
What We Think our Options Are
Use a catch-all / not found controller. If we let the route fall all the way through to /**, we can retrieve the token value from $location. That's sort of gross though; we'd like to avoid it.
Find a way to get the full URL into the controller. We can capture the route and put it through to a controller, but the URL isn't available at that point.
Go back to using the older router or ui-router (which we'd like not to do at this point).
Anything that could point us in the right direction would be greatly appreciated!
To follow up on this: in the end, we decided that this was a strange enough edge-case that it warranted returning to ui-router.
While we think the component router makes the most sense, the deciding factor here is that, unfortunately, we don't have 100% control over our routes. The route constraint included the edge case that component-router did not seem capable of handling at the current time.
For those who are working with older oauth server systems, I hope this will serve as a warning / some background as you're making your choice of router.
Hopefully ngComponentRouter will better support this edge case in the future, though I wouldn't blame them for leaving it out.

ReactJS Add local path

I am just starting with ReactJS and trying to integrate with Stormpath for user login. They provide default behaviors for /register and /login path.
I want ReactJS to redirect to those local links for now rather than creating new routes and components. How can this be achieved.
Thanks!
I also work at Stormpath and just a few days ago I released the Stormpath React SDK. With this you'll be able to integrate Stormpath into your React application with very little effort.
To get started checkout our example application or read the blog post I wrote for it.
And if you have any questions, feel free to hit me up at robin [at] stormpath [dot] com.
Cheers!
I work at Stormpath. We're recommending that you try to use our express-stormpath module. But we do have some issues that we're working on fixing.
It is not yet possible to disable the default HTML views, but still retain the JSON API. We will be fixing this in a future release. This creates a problem for React Flux applications that want to use the /login route in their browser application, but not use our default HTML views.
To work around the problem, you can change the uri of the route to a different URL than /login. For example:
app.use(stormpath.init(app, {
website: true,
web: {
login: {
uri: '/api/login'
}
}
}));
Your browser code will need to make it’s login POST to /api/login
Can you give this a try and let me know if is helps? Thanks!

Node Angular authentication

I want to use frontend routing with angular js (with $routeProvider), and login using passport js. I found out that there are many problems while redirecting, communication between frontend and backend, showing messages and etc. Does there exist any complete tutorial on this?
I learned it here but it's long. Maybe it helps. They use what you need.

Angular adding extra logic to 404 handling on non angular routes

I have an angular site hosted in S3, and I have a 404 route set up (I use hash), if someone for example does
mysite/#/gibberish
goes to
mysite/#/404
and on the s3 bucket we have a redirect rule in place for
mysite/gibberish
goes to
mysite/404.html
all is well
Now I just want to add an extra logic on top that if someone types in
mysite/customerid
which is a 404 to somehow redirect this to an angular controller so I can send this request to right page.
So somehow in my redirect in S3 rule add a reg exp for some incoming request and rather than serve 404.html send it i.e. mysite/#/handlethis
Is this possible ?
Depending on the router of your choice, you could do something like the following (which is what we've done (well, not precisely this, but close)):
ui-router
app.config(function ($urlRouterProvider) {
var regx = /\/#\//; // match against /#/
$urlRouterProvider.otherwise(function ($state, $location) {
if (!regx.test($location.path()) { // if no match
$state.go('customHandlingState', /** params **/, /** configuration **/ });
// Transition to your custom handler state, with optional params/config.
}
});
});
You could pair this up with custom stateChange[Start|Stop|Error|Success] handlers in the run block of your app to customise it to your liking.
I would supply an example of how to do this with ngRoute, but I gave up on ngRoute two years ago and haven't looked back since. As such I have no suggestion to give, nor was I able to find a solution to the problem you present.
I would strongly suggest you scrap the S3 portion of this recipe as it will make your life a lot easier when it comes to client side routing (speaking from personal experience here, it's my opinion on the matter - not fact) and handle your 404's/500's on the client with custom state handlers.
If need be you could hook into some logging service and store some data whenever a client/person ends up in an erroneous state.
I suppose my 'counter question' is; What do you gain from using S3 redirect rules? So as to get a better understanding for the needs and goals here.
Some reference material to go along:
ui-router#$state.go
ui-router#$urlRouterProvider.otherwise
I would suggest using routeParams
https://docs.angularjs.org/api/ngRoute/service/$routeParams
the route would look like this:
/mysite/:cid
then access the id with the controller:
$routeParams.cid
I hope this could help
You can manually configure your server to always serve your index.html(your main html file which includes reference to angular script) on all incoming http requests. Client routing will be handled by Angular

Passport.js, Express.js, and Angular.js routing: how can they coexist?

I apologize this question turned out a bit long, but I have worked on this for some time and really needed to explain all the story.
Background: App based on MEAN stack, trying to authorize Facebook logins using Passport.js.
Following Passport.js guide I implemented something similar to:
// HTML
Add a Facebook login
// send to facebook to do the authentication
app.get('/connect/facebook',isLoggedIn, passport.authorize('facebook',
{ scope : 'email' })
);
// handle the callback after facebook has authorized the user
app.get('/connect/facebook/callback',
passport.authorize('facebook', {
successRedirect : '/profile',
failureRedirect : '/profile'
}));
Notice the target=_self in the html in order to skip Angular routing.
Clearly, authorization works fine. However, redirection does not work, as the routing is handled by Angular. After authorization I never land on /profile (but on the default Angular route).
Therefore, I tried with a custom callback as suggested by Passport.js here, with the hope of passing json data to Angular, and let Angular do the routing. I ended up doing something like:
// In the controller
$http.get("/connect/facebook").success(function(data){
// here I wait for json data from the server and do the routing
});
// I call this route from Angular
app.get('/connect/facebook',isLoggedIn,passport.authorize('facebook',
{ scope : 'email' })
);
// But Facebook lands here!
app.get('/connect/facebook/callback',function(req, res, next) {
passport.authorize('facebook', function(err, user, info) {
res.json({something:smtg});
...
Clearly custom callbacks work for local-login, as Passport.js explains. But here do you see the problem? I call /connect/facebook from Angular, but I should receive some json from /connect/facebook/callback.
I am about to give up Passport, but before this, do you see any solution which would allow landing on /profile after FB authorization, perhaps with a custom message? Many thanks for reading through.
EDIT:
The same question had been reported as an issue on the Passport-Facebook GitHub account. Some additional attempts have been posted there, but not quite the fix yet.
This is a bit more in depth than can be described in one answer, but I'll try to start pointing you in the right direction.
Essentially, Angular.js routes are not really HTML routes at all, but an internal route structure that happens to use the URL for use of the end user. Remember that Angular.js is a client script, and that a full page reload is not desired, as this will reload the entire script. Therefore, /# is used to trick the browser into jumping to a specific bit of code within the already loaded script. (as opposed to the traditional anchor location in the HTML document). Unfortunately (or fortunately), HTML 5 mode allows you to hide the /# part of the url, so instead of seeing http://somesite.com/#/someroute you just see http://somesite.com/someroute. Rest assured, however, that the /# is still there. Angular.js uses the HTML5 pushState (AKA HistoryAPI) to perform the magic replacement.
Given this, if you have called a server route, you are outside the Angular.js script, and any call to load the angular script again will start from the very beginning. You can't actually call your Angular.js route from the server without a full reload. Therefore, you are really doing a double route redirect here. Your server should be calling it's default route for angular, appending /#/someroute to the call. The angular.js page will load, parse off the /#, and redirect to the correct angular route. Keep in mind, however, that if there was any dependency on already loaded objects, those are no longer in memory. Therefore, any route accessed this way should operate as if it is an entry point to your application.
Effectively, you should try using successRedirect : '#/profile', keeping in mind that the profile route in angular should be treated as an app entry point.
Hopefully this gets you started.
If #Claies's way is not working, is it possible you have not get rid of the #= fragment from the facebook callback.
Have a read of this post

Resources