da.eXecutoR
da.eXecutoR

Reputation: 313

Bestpractice Authentication in AngularJS 1x with ui router

I got a working angular code to successfully get/store/retrieve a jwt token for authentication.

Also I got the following route controller:

// Router configuration
App.config(['$stateProvider', '$urlRouterProvider',
    function ($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise('/dashboard');
        $stateProvider
            .state('dashboard', {
                url: '/dashboard',
                templateUrl: 'assets/views/dashboard.html'
            })
            .state('customers', {enter code here
                url: '/customers',
                templateUrl: 'assets/views/customers.html'
            })
            .state('customersAdd', {
                url: '/customers/add',
                templateUrl: 'assets/views/customers_add.html'
            })
            .state('account', {
                url: '/account',
                templateUrl: 'assets/views/account.html'
            })
            .state('login', {
                url: '/login',
                templateUrl: 'assets/views/login.html'
            });
    }
]);

I went through different tutorials on the net and I think, for my understanding the best approach would be using resolve on my routes. Yet I don't know how to bring the pieces togehter. I got a working auth service with a function auth.isAuth() that returns true or false.

But how can I bind this into my routes? And also I would like to explicit mark routes that doesn't need auth.isAuth() to be true, because there are only like two states that doesn't require an authenticated user.

Greetings eXe

Upvotes: 1

Views: 1297

Answers (2)

da.eXecutoR
da.eXecutoR

Reputation: 313

Just in case someone is looking for the same, this is my final solution:

// Router configuration
App.config(['$stateProvider', '$urlRouterProvider',
    function ($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise('/dashboard');
        $stateProvider
            .state('auth', {
                url: '',
                abstract: true,
                resolve: {
                  loginRequired: loginRequired
                },
            })
            .state('auth.dashboard', {
                url: '/dashboard',
                templateUrl: 'assets/views/dashboard.html'
            })
            .state('auth.customers', {
                url: '/customers',
                templateUrl: 'assets/views/customers.html'
            })
            .state('auth.customersAdd', {
                url: '/customers/add',
                templateUrl: 'assets/views/customers_add.html'
            })
            .state('auth.account', {
                url: '/account',
                templateUrl: 'assets/views/account.html'
            })
            .state('login', {
                url: '/login',
                templateUrl: 'assets/views/login.html'
            });
    }
]);

function loginRequired($q, $location, auth) {
    var deferred = $q.defer();
        if (auth.isAuthed()) {
        deferred.resolve();
    } else {
        $location.path('/login');
    }
    return deferred.promise;
}

By using nested states my 'auth' state acts like a middleware. Now I can easily manage my routes.

Upvotes: 2

Taylor Ackley
Taylor Ackley

Reputation: 1437

Here is how I do it. Borrowed from the Satellizer library. Works great!

//note the resolve block.
$stateProvider
  .state('home', {
    url: '/home',
    controller: 'HomeCtrl',
    templateUrl: 'views/home.html',
    data: {
      pageTitle: 'Home'
    },
    resolve: {
      loginRequired: loginRequired
    }
  })
  .state('splash', {
    url: '/',
    templateUrl: 'views/auth/splash.html',
    controller: 'SplashCtrl',
    data: {
      pageTitle: 'Welcome'
    },
    resolve: {
      skipIfLoggedIn: skipIfLoggedIn
    }
  })

//add to your apps config block, below your route definitions
function skipIfLoggedIn($q, auth) {
  var deferred = $q.defer();
  if (auth.isAuth()) {
    deferred.reject();
  } else {
    deferred.resolve();
  }
  return deferred.promise;
}

function loginRequired($q, $location, auth) {
    var deferred = $q.defer();
    if (auth.isAuth()) {
      deferred.resolve();
    } else {
      $location.path('/');
    }
    return deferred.promise;
  }

Upvotes: 0

Related Questions