In the last months I played a lot with these issues and questions and I got to the following conclusion:
For my purposes, I needed an app that relies almost entirely on Angular, without a separate backend, and the present backend should be from Angular.
Why? Because I want all of my eggs in one basket, I don’t want to configure a ton of stuff on a lot of different parts.
As a basis for my project I ended up using ng-boilerplate, as a boilerplate :), with some changes to the development process, Grunt tasks etc, this is for everybody to figure out, depending on each particular project.
Well, the main issue I’m gonna touch here is that, for a true backend, made in Angular, we need secure routes and a secure persistence method, a database.
For the app, I took advantage of the ng-boilerplate's modular and dependency aware structure, I think it’s perfect for a Angular app.
Anyhow, I’m gonna take things top to bottom (final product wise, the build env as I said above, it’s up to you, but ng-boilerplate is awesome), here we go.
- On the upper layer we have the actual Angular app, made just the way we want
- The server container, is a NodeJS server with express and other modules to take PARTIAL care of the routing on different browsers and devices (In my app, I made HTML5 routing that is augmented by express, .htaccess like settings whenever there’s a partial URL it should redirect to index where Angular will read the path requested and zapp you to that location)
- For my case, the whole things runs on Heroku, on a Node.JS application, you can install several other things there if you want to.
Now, for the persistency, to have authentication and security, and NOT to rely on backend for that, I am using firebase (https://www.firebase.com/), there’s some great tutorials there to help you going and have true persistence in your Angular APP, with routes when you are logged in, access to custom tables/objects in DB when you are logged in etc. It’s the real deal.
If you don’t want to rely OAuth’s possible sites to log in with (Facebook, github, persona or twitter) and want custom emails and addresses you can do that directly with Firebase, to create accounts and delete them etc.
FIREBASE Angular Backend.
So, Firebase, just like they say on the site is a powerful API to store and sync data in realtime.
I don’t know exactly how to approach this, so I’m gonna start it with creating a Firebase database. Once we create it, in the backend we have several options, one of which is security.
{
"rules": {
".read": true,
".write": "auth != null"
}
}
Here, if we read the documentation on https://www.firebase.com/docs/security/security-rules.html we’ll learn that we can add rules for each ‘table' in our database, so we can have like 3 protected ’table’ objects and some that are not protected.
We can protect tables per user basis, per different rules, if logged in or not, we also have inheritance for rules etc, pleas read the documentation there, it really is a good read.
Now, for these rules to take effect we need to enable the Firebase Simple Login and select the desired login method, from Facebook, Twitter, Github, Persona, Email&Password and Anonymous.
For a real app, we need to write info to DB also as anonymous (user sessions etc) and also as logged (with either of the options above) to store and read information.
Me, I wanted to go the quick easy way and made a Facebook authentication, reading the docs there I made a quick Facebook app, and in the settings of the application on Facebook I’m putting Firebase’s backend https://www.dropbox.com/s/xcd4b8tty1nlbm5/Screenshot%202014-01-22%2013.51.26.png
This gives a interim link to login to Facebook and have access to ’tables’ that are otherwise locked if the rule is auth !=null
.
NOW, onto the Angular backend.
Firebase provides a library for us to put in our app, and a SimpleLogin lib, also, for Angular, a factory service called AngularFire.
In my case, I made local firebaseService with use methods that connects to my DB:
angular.module('firebaseService', ['firebase'])
.service('firebaseService', function ($firebase, $rootScope) {
//Input data in Firebase
var URL = "https://glowing-fire-xxxx.firebaseio.com";
var tellFirebase = function(ID, JSON) {
users = $firebase(new Firebase(URL + '/' + ID));
users.details = JSON;
users.$save('details');
};
return {
addUser: function(ID, JSON) {
tellFirebase(ID, JSON);
if ($rootScope.debugStatus === true) {
console.log('Firebase Service .addUSer Called');
}
},
getUser: function(ID) {
if ($rootScope.debugStatus === true) {
console.log('Firebase Service .getUser Called');
}
}
};
})
From here we do our READ/WRITE, on the controller’s page I have this:
It’s worth noticing that I have a middleware service (storageManagement) where I switch between Firebase and MongoDB, to avoid confusion.
.controller( 'SomeCtrl', function SomeController( $scope, storageManagement, $firebase, $firebaseSimpleLogin ) {
/*===========================
* ==== FIREBASE LOGIN
* ===========================*/
var URL = "https://glowing-fire-XXXXX.firebaseio.com";
var users = new Firebase(URL);
$scope.auth = $firebaseSimpleLogin(users, function(error, user){});
if ($scope.auth.user == null) {
//$scope.auth.$login('facebook');
}
console.log($scope.auth);
//$scope.auth.$logout('facebook');
$scope.doLogin = function() {
console.log($scope.facebookemail);
console.log($scope.facebookpassword);
$scope.auth.$login('facebook');
$scope.$on("$firebaseSimpleLogin:login", function(evt, user) {
storageManagement.runFirebase();
});
/* example of logging in while asking access to permissions like email, user_list, friends_list etc.
* auth.$login('facebook', {
rememberMe: true,
scope: 'email,user_likes'
});*/
};
$scope.doLogout = function() {
$scope.auth.$logout();
};
});
I’m adding the $firebase service to my controller, and the $firebaseSimpleLogin one.
This here exposes to scope two buttons, login/logout, that popup the OAuth window from Facebook, with email/password setting you won't need to to go through this I think, for a full understanding please read the full docs at firebase.
SO, once we are logged, we can access tables described in the rules, if we choose email/password, actually even for Facebook or other methods, we can assign certain rules for certain IDENTITIES, so you could have a ADMIN table where you could save settings that get READ on page load to apply whatever you want.
Now, with routes, we can check for the $scope.auth status, if WE PUT IT IN $rootScope, and check for the status when going to a route, if the status checks, we get to that route and it gets populated with stuff from the DB, otherwise, even if someone hacks it’s way to that route it won’t see anything because there are no permissions to read that table for unauthorized/wrong email users.
This is loosely based on this article, http://www.ng-newsletter.com/posts/back-end-with-firebase.html … I had a hard time changing the mindset from what the guy wrote there, but, after ONE WHOLE day, of reading the docs (and setting up middleware, mind you) from Firebase I figured it out, and it works.
The connection to the DB is exposed like one BIG object where you can do whatever operations you want.
This isn't the most complete explanation, but it should get you well on your way to making some awesome things:D