Wednesday, January 21, 2015

Adding Authentication (and a Sidebar into Form Validation)

One of the nice features of Firebase is that they provide a simple but robust mechanism to handle authentication (and authorization). To get started with these features, one logs into the Firebase dashboard for their app and select the "Login & Auth" tab and:
  1. Under the "Email & Password" tab, check the "Enable Email & Password Authentication".
  2. At the bottom of the screen, add a new user.
note: To see the newly created user under "Registered Users", reload the screen (this seems to be a bug).

While there a mechanism to add new users from the SPA, for this simple example we will only create a login screen to support authenticating.

The first step is to add a Login and Logout option to the home page view (say as list items right above the Wineries and Wines) list items.  The intent is to show the Login option when not authenticated and the Logout option when authenticated.

HTML
 
            <ul class="list-group">
                <li ng-if="! authenticated" ng-click="navigate('/login');" class="list-group-item">Login</li>
                <li ng-if="authenticated" ng-click="logout();" class="list-group-item">Logout</li>
                <li ng-click="navigate('/wineries');" class="list-group-item">Wineries</li>
                <li ng-click="navigate('/wines');" class="list-group-item">Wines</li>
            </ul>

Then one needs to update the home screen controller with some familiar code and two new Firebase functions getAuth() and unauth(); documented at <https://www.firebase.com/docs/web/guide/user-auth.html>.

JavaScript
controllers.controller('HomeCntrl', ['$scope', '$location', '$window', function($scope, $location, $window) {
    var myDataRef;
    $scope.navigate = function(path) {
        $location.path(path);
    };
    $scope.authenticated = false;
    myDataRef = new $window.Firebase('https://wineapp.firebaseio.com');
    $scope.logout = function() {
        $scope.authenticated = false;
        myDataRef.unauth();
    };
    var authData = myDataRef.getAuth();
 if (authData != null) {
        $scope.authenticated = true;
    }
}]);

Next we, create a login screen first by adding the routes to the routes (say just after the "/" route):

JavaScript
            when('/login', {
                   templateUrl: 'views/login.html',
                    controller: 'LoginCntrl'
            }).

Next we create the login screen view (say just below the home page view). The new concepts introduced here are:

HTML
 
 <!-- /views/login.html (obmit work-around script tag)-->
    <script type="text/ng-template" id="views/login.html">      
        <div class="panel panel-default">
            <div class="panel-heading">
                 <h3 class="panel-title"><button ng-click="navigate('/');" class="btn btn-default"><span class="glyphicon glyphicon-chevron-left"></span> Back</button> Login</h3>                
            </div>
            <div class="panel-body">
                <form name="login_form" role="form" novalidate>
                    <div ng-class="{'form-group': true, 'has-feedback': true, 'has-error': login_form.email.$invalid}">
                        <label class="control-label" for="email">Email</label>
                        <input type="email" name="email" class="form-control" id="email" placeholder="Email" ng-model="email" required />
                    </div>
                    <div ng-class="{'form-group': true, 'has-feedback': true, 'has-error': login_form.password.$invalid}">
                        <label class="control-label" for="password">Password</label>
                        <input type="password" name="password" class="form-control" id="password" placeholder="Password" ng-model="password" required />
                    </div>
                </form>
                <p ng-if="failed" style="text-align: center" class="text-danger">email or password incorrect</p> 
            </div>
            <div class="panel-footer">
                <button ng-click="login();" type="button" class="btn btn-default btn-sm" ng-disabled="login_form.$invalid" ><span class="glyphicon glyphicon-user"></span> Login</button>
            </div>
        </div>
    </script>
    <!-- EOF -->    

Lastly we need to add in the login screen controller:

JavaScript
controllers.controller('LoginCntrl', ['$scope', '$location', '$window', '$timeout', function($scope, $location, $window, $timeout) {
    var myDataRef;
    $scope.navigate = function(path) {
        $location.path(path);
    };
    $scope.failed = false;
    myDataRef = new $window.Firebase('https://wineapp.firebaseio.com');
    $scope.login = function() {
        myDataRef.authWithPassword({
            email: $scope.email,
            password: $scope.password
        }, function(error, authData) {
            $timeout(function() {   
                if (! error) {
                    $scope.navigate('/');
                } else {
                    $scope.failed = true;
                    $scope.password = '';
                }
            });
        });;
    };
}]);

No comments:

Post a Comment