Loopback creates a services file that is registered as a module with angular. This allows local bindings to remote methods, both built in and custom written, and authenticates with the loopback server by bundling the current access token with the request automatically. However, to figure out who was making a request, we were using the current user ID, which is stored in local storage in the browser along with the access token. Changing the user ID in local storage is trivial, whereas changing the access token to another valid token would be much more challenging. Our solution was to use the bundled access token to get the role of the user in the background.

 

The SystemUser model has a custom remote method `getRole` which returns a promise, allowing you to chain other methods. This uses node.js promise syntax, not jQuery promises.

How it works
// We retrieve the context of the request and pull the access token from it
var ctx = loopback.getCurrentContext();
var token = ctx.get("accessToken");           
// The SystemUser model has a through model that connects it to the Role model through the RoleMapping model                                                                                                                                                                                  
var promise = SystemUser.findById(token.userId, {include: "roles"});
promise.then(                                    
	function(s) {
		var r = JSON.parse(JSON.stringify(s));
		// Our system has users only having a single role, so index 0 is the only role
		deferred.resolve(r.roles[0]);
	},
...

Here is an example of using the getRole method to only proceed if the requesting user is an Administrator.

Example
SystemUser.getRole()
.then(
	function(userRole) {
		// userRole is a javascript object that fits the schema of the default loopback Role model
		if (userRole.name == "Administrator") {
			// do things
		} else {
			// Other roles are not allowed
			var err = new Error("Unauthorized access");
			err.status = 401;
			return err;
		}
	});