"use strict";
        .module("Test", ["ngRoute"])
                .when("/", {
                    templateUrl: "public",
                    controller: "GeneralController",
                    controllerAs: "context"
                .when("/login", {
                    templateUrl: "login",
                    controller: "LoginController",
                    controllerAs: "context"
                .when("/private", {
                    templateUrl: "private",
                    controller: "GeneralController",
                    controllerAs: "context",
                    authorize: true
                    redirectTo: "/"

        .run(function($rootScope, $location){
            // logging helper
            function getPath(route) {
                if (!!route && typeof(route.originalPath) === "string")
                    return "'" + route.originalPath + "'";
                return "[unknown route, using otherwise]";
            $rootScope.$on("$routeChangeStart", function(evt, to, from){
                console.log("Route change start from", getPath(from), "to", getPath(to));
                if (to.authorize === true)
                    to.resolve = to.resolve || {};
                    if (!to.resolve.authorizationResolver)
                        to.resolve.authorizationResolver = function(authService) {
                            console.log("Resolving authorization.");
                            return authService.authorize();
            $rootScope.$on("$routeChangeError", function(evt, to, from, error){
                console.log("Route change ERROR from", getPath(from), "to", getPath(to), error);
                if (error instanceof AuthorizationError)
                    console.log("Redirecting to login");
                    $location.path("/login").search("returnTo", to.originalPath);
            // NOT needed in authorization / logging purposes only
            $rootScope.$on("$routeChangeSuccess", function(evt, to, from){
                console.log("Route change success from", getPath(from), "to", getPath(to));
        .controller("LoginController", function($location, authService){
            console.log("Instantiating login controller");
            this.login = login(true, $location.search().returnTo);
            this.logout = login(false, "/");
            // DRY helper
            function login(doWhat, whereTo){
                return function() {
                    console.log("Authentication set to", doWhat, "Redirecting to", whereTo);
                    authService.authenticated = doWhat;
                    $location.path(whereTo && whereTo || "/");
        .controller("GeneralController", function($scope){
            console.log("Instantiating general controller");
            $scope.console = console;
        .service("authService", function($q, $timeout){
            console.log("Instantiating auth service");
            var self = this;
            this.authenticated = false;
            this.authorize = function() {
                return this
                        console.log("Checking authentication status", info);
                        if (info.authenticated === true)
                            return true;
                        // anonymous
                        throw new AuthorizationError();
            this.getInfo = function() {
                console.log("Acquiring authentication info");
                return $timeout(function(){
                    console.log("Authorization info acquired");
                    return self;
                }, 1000);
        // Custom error type
        function AuthorizationError(description) {
            this.message = "Forbidden";
            this.description = description || "User authentication required.";
        AuthorizationError.prototype = Object.create(Error.prototype);
        AuthorizationError.prototype.constructor = AuthorizationError;

<!DOCTYPE html>
<html ng-app="Test">

    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.4.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js" data-semver="1.4.6"></script>
    <script data-require="angular-route@*" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular-route.js"></script>
    <script src="app.js"></script>

    <h3>Angular routing authorization implementation</h3>
        Home and login are public views and load immediately because they don't have
        any promises to resolve (set by <code>route.resolve</code>).
        Authorized view is only accessible after user is authenticated.
        Authorization resolves in 1 second.
        Anonymous users are <strong>auto-redirected to login</strong> when trying to
        access Authorized view. After login they're auto-redirected back to where they
        were before redirection to login view. If users manually accesses login view
        (clicking Login) they're redirected to home after login/logout.
    <p class="important">Open <strong>development console</strong> to observe execution log.</p>
    <a href="#/home">Home</a>
    <a href="#/private">Authorized</a>
    <a href="#/login">Login</a>
    <script type="text/ng-template" id="login">
        <h1>Login view</h1>
        <p>This is a publicly accessible login view</p>
            <a href="" ng-click="context.login()">click here</a> to auto-authenticate
            <a href="" ng-click="context.logout()">logout</a> to prevent authorized view access.
    <script type="text/ng-template" id="public">
        <h1>Public view</h1>
        <p>This is a publicly accessible view</p>
    <script type="text/ng-template" id="private">
        <h1>Authorized view</h1>
        <p>This is an authorized view</p>
        {{console.log("Rendering private view")}}

/* Put your css in here */

body {
    font-family: Segoe UI;

section {
    margin-top: 2em;
    border: 1px solid #ccc;
    padding: 0 2em 1em;

.important {
    color: #e00;