Авторизация пользователей с AngularJS и Firebase

в 21:34, , рубрики: AngularJS, firebase, javascript

В прошлой статье, я рассказывал о Firebase. Сегодня я хочу рассказать как я организовал авторизацию пользователей с использованием AngularJS и Firebase.

На данный момент я работаю, в свободное время над своим проектом, если в вкратце, то это сервис для создания прототипов SPA-приложений, думаю в скором времени я смогу расказать о нем больше, но пока только об авторизации. Почему я выбрал Firebase? Все просто, я очень ленивый программист и не люблю писать велосипеды, а данный сервис предлагает кучу готовых решений среди которых и авторизация и регистрация пользователей.

Для основы проекта я использую ngBoilerplate, так считаю его достаточно удачной сборкой не требующей каких-то особых доработок. В сборке предустановлены Twitter Bootstrap, Angular UI, Angular Bootstrap, Font Awesome и LESS. Также замечательно настроен Grunt и Bower. Для установки и запуска чистого приложения, нужно всего лишь выполнить следующие команды:

$ git clone git://github.com/joshdmiller/ng-boilerplate
$ cd ng-boilerplate
$ sudo npm -g install grunt-cli karma bower
$ npm install
$ bower install
$ grunt watch


Что-то я отошел немного от темы, продолжим. В проекте я создал модуль аутентификации и назвал его, как ни странно, Auth. Вот собственно так он и выглядит:

angular.module('Auth', [
    'firebase'
])

.service('AuthService', [  '$rootScope','$firebase', '$firebaseAuth', '$location', '$q',
function AuthService( $rootScope, $firebase, $firebaseAuth, $location, $q ){
    var firebaseObj = new Firebase('https://your-firebase-app.com/');
    var userStorageKey = 'authUser';
    var authUser = $.jStorage.get(userStorageKey) || { status:false, data: false };

    return {
        createUserByEmail: function(email, password){
            var deferred = $q.defer();
            firebaseObj.createUser({
                email    : email,
                password : password
            }, function(error) {
                if (error === null) {
                    deferred.resolve({
                        status: true
                    });
                } else {
                    deferred.resolve({
                        status: false,
                        error: error
                    });
                }
            });

            return deferred.promise;
        },
        signInUserByEmail: function(email, password){
            var deferred = $q.defer();
            firebaseObj.authWithPassword({
                email    : email,
                password : password
            }, function(error, data) {
                if (error === null) {
                    // user authenticated with Firebase
                    authUser = {
                        status: true,
                        data: data
                    };
                    deferred.resolve(authUser);
                    $.jStorage.set(userStorageKey, authUser);
                } else {
                    deferred.resolve({
                        status: false,
                        error: error
                    });
                }
            });

            return deferred.promise;
        },
        changeUserPass: function(email, password, newPassword){
            firebaseObj.changePassword({
                email       : email,
                oldPassword : password,
                newPassword : newPassword
            }, function(error) {
                if (error === null) {
                    console.log("Password changed successfully");
                } else {
                    console.log("Error changing password:", error);
                }
            });
        },
        resetAndSendPassword: function(email){
            firebaseObj.resetPassword({
                email : email
            }, function(error) {
                if (error === null) {
                    console.log("Password reset email sent successfully");
                } else {
                    console.log("Error sending password reset email:", error);
                }
            });
        },
        deleteUser: function(email, password){
            firebaseObj.removeUser({
                email    : email,
                password : password
            }, function(error) {
                if (error === null) {
                    console.log("User removed successfully");
                } else {
                    console.log("Error removing user:", error);
                }
            });
        },
        getUserState:function(){
            //console.info(Date(authUser.data.expires));

            console.info(authUser);
            if(authUser.data){
                var data = firebaseObj.getAuth();
                authUser = {
                    status: data ? true : false,
                    data: (data == null) ? {} : data
                };
                $.jStorage.set(userStorageKey, authUser);
            }
            return authUser.status;
        },
        logOut: function(){
            $firebaseAuth(firebaseObj).$unauth();
            $.jStorage.deleteKey(userStorageKey);
            $rootScope.$userState = this.getUserState();
        },
        getAuthUser: function(){
            return authUser.data;
        }
    };
}])

.directive('signInForm', [ '$rootScope', 'AuthService', '$location', function( $rootScope, AuthService, $location){
    return{
        restrict: 'A',
        templateUrl: 'auth/templates/sign-in.tpl.html',
        link: function(scope, element, attrs){
            scope.userEmail = '';
            scope.userPassword = '';
            scope.userState = AuthService.getUserState();

            scope.signInUserByEmail = function(){
                AuthService.signInUserByEmail(scope.userEmail, scope.userPassword)
                .then(function(response){
                    scope.userState = AuthService.getUserState();
                    if(scope.userState) {
                        alert('You are logged in');
                        $location.path('profile');
                    }
                    else{
                        alert('Incorrect user email or password');
                    }
                });
            };
        }
    };
}])

.directive('signUpForm', [ '$rootScope', 'AuthService', '$location', function( $rootScope, AuthService, $location){
    return{
        restrict: 'A',
        templateUrl: 'auth/templates/sign-up.tpl.html',
        link: function(scope, element, attrs){
            scope.userEmail = '';
            scope.userPassword = '';
            scope.facebookEnabled = false;
            scope.userState = AuthService.getUserState();
            scope.isRegistered = false;

            scope.createUser = function(){
                AuthService.createUserByEmail(scope.userEmail, scope.userPassword)
                .then(function(response){
                    if(response.status){
                        alert("Congratulations! You've successfully signed up. You can authorize");
                        scope.isRegistered = true;
                    }
                    else{
                        alert(response.error);
                    }
                });
            };
        }
    };
}])
;

Он состоит из трех частей: сервис (AuthService) и две директивы (одна для формы логина — signInForm, а вторая для регистрации — signUpForm). Директивы особого интереса не представляют, нам интересен сервис, в котором все и происходит. Внутри сервиса есть ряд функций:

  • createUserByEmail — создает нового пользователя используя email
  • signInByEmail — авторизация пользователя по email
  • changeUserPass — функция для изменения пароля
  • resetAndSendPassword — тоже функция для изменения пароля, но отличается тем, что старый пароль будет сброшен, а новый придет пользователю на почту
  • deleteUser — удаление пользователя
  • getUserState — функция проверяющая авторизован пользователь или нет и возвращает его состояние
  • logOut — это логаут (спасибо кэп)
  • getAuthUser — возвращает данные авторизованного пользователя.

В директивах можно увидеть простую реализацию авторизации и регистрации пользователя.

Также, в коде можно увидеть, что я решил использовать jStorage для хранения данных о авторизованном пользователе. Выбор на него пал потому что он простой и замечательно поддерживается разными браузерами (даже IE6).

Ну это собственно и все что нужно для авторизации/регистрации пользователей используя Firebase. Также есть возможность очень просто добавить авторизацию/регистрацию с использованием социальных сетей (Google, Facebook, Twitter, GitHub) для этого всего лишь нужно зайти на страницу администратора на сайте Firebase, отметить несколько чекбоксов и указать ключи к своим приложениям.

Больше я не знаю что написать, по этому буду рад ответить на любые ваши вопросы в комментариях. Советам и пожеланиям тоже буду очень рад.

Автор: jenezis

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js