user3276940
user3276940

Reputation: 487

How to handle view logic (on the client side) based on authorization token (Angular SPA + JWT + web API)

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

Answers (1)

Jesse Carter
Jesse Carter

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

Related Questions