What is the best way to sign in with Angularjs?

6

In an app using AngularJS and Ionic, what is the best way to authenticate to an API? Do I check login on all screens or do I use some session engine?

I guess authentication on all controllers may consume too much data ... What is the best way?

    
asked by anonymous 06.02.2016 / 19:43

2 answers

5

The ideal is to use APIs that support OAuth 2, you then perform the initial procedures to get the bearer token and store it in a cookie to be used on every request to the API (or at least the endpoints that require this authentication). I'm going to give you an example of a service that I'm using in an application to perform all authentication procedures with an API that makes use of OAuth 2.

Here is the service code:

(function () {
    'use strict';

    angular
        .module('zigforumApp')
        .service('users', users);

    users.$inject = ['$http', '$cookies', 'TOKEN_URL'];

    function users($http, $cookies, TOKEN_URL) {
        var sv = this;

        function NoAuthenticationException(message) {
            this.name = 'AuthenticationRequired';
            this.message = message;
        }

        function AuthenticationExpiredException(message) {
            this.name = 'AuthenticationExpired';
            this.message = message;
        }

        function AuthenticationRetrievalException(message) {
            this.name = 'AuthenticationRetrieval';
            this.message = message;
        }

        sv.userData = {
            isAuthenticated: false,
            username: '',
            bearerToken: '',
            expirationDate: null
        };

        function isAuthenticationExpired(expirationDate) {
            var now = new Date();
            expirationDate = new Date(expirationDate);

            if (expirationDate - now > 0) {
                return false;
            } else {
                return true;
            }
        }

        function saveData() {
            removeData();
            $cookies.putObject('auth_data', sv.userData);
        }

        function removeData() {
            $cookies.remove('auth_data');
        }

        function retrieveSavedData() {
            var savedData = $cookies.getObject('auth_data');

            if (typeof savedData === 'undefined') {
                throw new AuthenticationRetrievalException('No authentication data exists');
            } else if (isAuthenticationExpired(savedData.expirationDate)) {
                throw new AuthenticationExpiredException('Authentication token has already expired');
            } else {
                sv.userData = savedData;
                setHttpAuthHeader();
            }
        }

        function clearUserData() {
            sv.userData.isAuthenticated = false;
            sv.userData.username = '';
            sv.userData.bearerToken = '';
            sv.userData.expirationDate = null;
        }

        function setHttpAuthHeader() {
            $http.defaults.headers.common.Authorization = 'Bearer ' + sv.userData.bearerToken;
        }

        this.isAuthenticated = function () {
            if (!(sv.userData.isAuthenticated && !isAuthenticationExpired(sv.userData.expirationDate))) {
                try {
                    retrieveSavedData();
                } catch (e) {
                    return false;
                }
            }

            return true;
        };

        this.removeAuthentication = function () {
            removeData();
            clearUserData();
            $http.defaults.headers.common.Authorization = null;
        };

        this.authenticate = function (username, password, persistData, successCallback, errorCallback) {
            this.removeAuthentication();
            var config = {
                method: 'POST',
                url: TOKEN_URL,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                data: 'grant_type=password&username=' + username + '&password=' + password
            };

            $http(config)
                .success(function (data) {
                    sv.userData.isAuthenticated = true;
                    sv.userData.username = data.userName;
                    sv.userData.bearerToken = data.access_token;
                    sv.userData.expirationDate = new Date(data['.expires']);
                    setHttpAuthHeader();
                    if (persistData === true) {
                        saveData();
                    }
                    if (typeof successCallback === 'function') {
                        successCallback();
                    }
                })
                .error(function (data) {
                    if (typeof errorCallback === 'function') {
                        if (data && data.error_description) {
                            errorCallback(data.error_description);
                        } else {
                            errorCallback('Unable to contact server; please, try again later.');
                        }
                    }
                });
        };

        try {
            retrieveSavedData();
        } catch (e) { }
    }
})();

The most important function is authenticate it receives the user login data, makes an API request to get the token , stores the token in a cookie and to automatically authenticate all requests that will be made from here onwards it adds that token as the default header.

You can use this service as a basis to build your own.

    
06.02.2016 / 20:51
3

The best way to sign in with AngularJS is ...

Do not sign in with angularJS.

Seriously. Being a technology that runs on the client, any credential validation rule (connecting to an endpoint to verify user and password, for example) can be exploited by a malicious user.

The best way, in this case, would involve delegating responsibility for sign-in and sign-out actions to another part of the application - in the well-given example of Zignd , this technology would be OAuth .

The end result of an OAuth tightening is a token , which can be stored in LocalStorage or in a cookie. Use this token to get information about the currently logged in user.

    
06.02.2016 / 23:22