Reputation: 487
I am designing an AngularJS SPA App that fetches the views from an asp.net server that hosts static html.
On backend, I have a resource table that dictates whether the specific role has a permission to Read, Modify that resource. Those read , writes are then mapped as claims in the application.
E.g of that would be
say for a role : Accountant
Feature User Management
**Path Name** Read Write
/User {includes /User/API + /User/Views} UserManangement Yes No
Valid Claims for Accountant : CanReadUser
Now for admin role, the backend permission table would look like
**Path Name** Read Write
/User {includes /User/API + /User/Views} UserManangement Yes Yes
Valid Claim for Accountant : CanWriteUser
Now, let's take a case of a view called "Get User". When an Accountant logs in , I want an accountant to see the list of users, but when an Admin user logs in, I want admin to see the list of users with a button at a bottom saying "Add New User".
My static HTML already includes a button .. Since this is a static HTML, and not an MVC view, I don;t have the capability of writing server side code. Neither I want to , otherwise, I would be switching to MVC views.
My Web APIs are completely safe . I have no problem there. Since the JWT token is authorized and checked for claims before API returns the JSON data.
My question is how to handle UI based operations such as above. Do I need to hard code claims in my JWT and use them in my javascript ?
Upvotes: 1
Views: 611
Reputation: 21207
For my client side validation, I usually encode the user's roles in the JWT and then make that available to a central Auth service. Then you can do ng-if
logic on any UI elements that you don't want a user to see. An example from one of my apps. Note that I use Auth0 so the injected auth
service conveniently exposes the users roles through the auth.profile
variable. Depending on how you do JWT you might have to switch that up:
(function() {
'use strict';
angular
.module('app.core')
.factory('AuthService', AuthService);
AuthService.$inject = ['auth'];
function AuthService(auth) {
var permissions = [];
return {
authorized: authorized
};
function authorized(permission) {
if (!_.includes(permissions, permission)) {
permissions.push(permission);
console.log(permissions);
}
if (permission === '') return true;
if (!auth.profile) return false;
var userRoles = auth.profile.roles;
return _.includes(userRoles, permission) || _.includes(userRoles, 'tinygod');
}
}
})();
My Angular apps usually have a shell or wrapper controller which will expose this function so that it can easily called anywhere in the UI like this:
<div ng-if="app.authorized('CanWriteUser')">
Obviously this by itself doesn't suffice but as you have your backend routes secured from returning any data the worst case scenario would be that someone with JS skills could find some empty HTML templates with no ability to get data.
Upvotes: 1