Denied!

Securing Your Application with Better User Authorization

brian childress

i build things @ Capital One

that have highly-sensitive data

brian.childress@capitalone.com

  • what is authorization?

  • how to authorize

  • types of authorization

authentication  &  authorization

authentication

... is the process of verifying that "you are who you say you are"...

authorization

... is the process of verifying that "you are permitted to do what you are trying to do"...

authentication flow

local

client

server

POST { username: password }

Status: 200

authentication flow

Oauth / OpenId Connect

client

server

GET /authentication

Status: 200

Auth Provider

Status: 301

GET /userInfo

Response: {

      "name" : "jim halpert",

      "email" : "jim@email.com"

}

Response: {

      " . . ."

}

Status: 200

{ JSON Web Token }

JSON Web Token (JWT) is an open standard ( RFC 7519 ) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

[ jot ]

eyJhbGciOiJIUzI1N9.3ODkwIiwibmFtZSI6.u6aVTx2CHvo

Header

{
  "alg": "HS256",
  "typ": "JWT"
}

JSON web token

eyJhbGciOiJIUzI1N9.3ODkwIiwibmFtZSI6.u6aVTx2CHvo

Payload

{
  "sub": "1234567890",
  "name": "Jim Halpert",
  "email": "jim@email.com",
  "iat": 1516239022,

  "exp": 1782348521

}

JSON web token

eyJhbGciOiJIUzI1N9.3ODkwIiwibmFtZSI6.u6aVTx2CHvo

Signature

HMACSHA256(header + "." + payload,pa$sw0rd)

JSON web token

Payload

{
  "sub":  "1234567890",
  "admin":  true
  "name":  "Jim Halpert",
  "email":  "jim@email.com",
  "iat":  1516239022,

  "exp":  1516240022,
  "uid:  "573hdk",
  "roles":  [   

             "manager" ,

             "superAdmin"

   ]

}

JSON web token

Payload

{
  "sub":  "1234567890",
  "admin":  true
  "name":  "Jim Halpert",
  "email":  "jim@email.com",
  "iat":  1516239022,

  "exp":  1516240022,
  "uid:  "573hdk",
  "groups":  [   

             6,

             42,

         67

   ]

}

JSON web token

make a request

client

server

GET /users

Status: 200

Authorization: Bearer { JWT }

authentication

who are you?

authorization

what can you do?

authorization

is hard!!

types of authorization

role-based

user

role

permissions

types of authorization

role-based

role canRead canEdit canDelete
user
editor
admin

types of authorization

role-based

users can have many roles

roles can have many permissions

permissions can be assigned to many roles

types of authorization

role-based

claims-based

user

permission

action

types of authorization

claims-based

user canReadProducts canEditProducts canDeleteProducts
bob
sue
morgan

types of authorization

role-based

claims-based

attribute-based

policy

authorization

user

types of authorization

attribute-based

IF

THEN

editor

can edit products

types of authorization

attribute-based

IF

THEN

before 9am

can read-only

who? what?

routes

components

how do we authorize?

Example of menu

Compare user, admin

Code example fade in

<ul>
...
  <li *ngIf="role === 'admin'">
    <a routerLink="/admin"
        routerLinkActive="active">Admin</a>
  </li>
...
  <li *ngIf="admin">
    <a routerLink="/users"
        routerLinkActive="active">Users</a>
  </li>
...
</ul>

Example of menu

Compare user, admin

Code example fade in

<ul>
...
  <li *ngIf="canViewAdmin || role === 'auditor' || 
        role === 'superAdmin'">
    <a routerLink="/admin"
        routerLinkActive="active">Admin</a>
  </li>
  <li>
    <a routerLink="/products"
        routerLinkActive="active">Products</a>
  </li>
...
</ul>

C

R

U

D

reate

ead

pdate

elete

C

R

U

D

authorization flow

client

server

GET /routescomponents

Status: 200

Authorization: Bearer { JWT }

Response: {

      "routes" : [ ... ],

      "components" : [ ... ]

}

Example of menu

Compare user, admin

Code example fade in

<ul>
...
  <li>
    <a routerLink="/products"
        routerLinkActive="active">Products</a>
  </li>
  <li *ngIf="getRouteAuth('users')">
    <a routerLink="/users"
        routerLinkActive="active">Users</a>
  </li>
...
</ul>


Authorization Service

// API Response
const routeAuth = [..{
                      "name": "users",
                      "create": true,
                      "read": true,
                      "update": true,
                      "delete": true
 }];

// Authorization Service
let getRouteAuth = (route: string) => {
  
  // Find a matching route authorization for provided route
  const auth = routeAuth.find((obj) => { return obj.name === route; });
  
  if (auth){
    return auth.read;
  }

  return false;
 
}
Authorization Service

// API Response
const routeAuth = [..{
                      "name": "users",
                      "create": true,
                      "read": true,
                      "update": true,
                      "delete": true
 }];
// Route is the information about a specific route
canActivate(route: ActivatedRoute): boolean {
    if (!this.auth.isAuthenticated() ||
      !this.auth.getRouteAuth(route)) {
      this.router.navigate(['login']);
      return false;
    }
    
    return true;
}

route

guard

// Angular Route Guard

// API Response
const routeAuth = [..{
                      "name": "users",
                      "create": true,
                      "read": true,
                      "update": true,
                      "delete": true
 }];

// Authorization Service
let getRouteAuth = (route: string) => {
  
  // Find a matching route authorization for provided route
  const auth = routeAuth.find((obj) => { return obj.name === route; });
  
  if (auth){
    return auth.read;
  }

  return false;
 
}
<!-- User Component -->

<form *ngIf="role === 'admin' || role === 'user'">
  <div class="form-row">
    <div class="form-group col-md-6">
      <label for="firstName">First Name</label>
      <input type="text" id="firstName" placeholder="First Name">
    </div>
    <div class="form-group col-md-6">
      <label for="lastName">Last Name</label>
      <input type="text" id="lastName" placeholder="Last Name">
    </div>
  </div>
  <div class="form-group">
    <label for="address">Address</label>
    <input type="text" id="address" placeholder="1234 Main St">
  </div>
  <div class="form-group">
    <label for="address2">Address 2</label>
    <input type="text" id="address2" 
    placeholder="Apartment, studio, or floor">
  </div>
...
  <button type="submit">Update</button>
</form>
// User Role
{
    "name": "userForm",
    "create": false,
    "read": true,
    "update": true,
    "delete": false
}
<!-- User Component -->

<form *ngIf="auth.read">
  <div class="form-row">
    <div class="form-group col-md-6">
      <label for="firstName">First Name</label>
      <input type="text" id="firstName" placeholder="First Name"
        [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
    </div>
    <div class="form-group col-md-6">
      <label for="lastName">Last Name</label>
      <input type="text" id="lastName" placeholder="Last Name"
        [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
    </div>
  </div>
  <div class="form-group">
    <label for="address">Address</label>
    <input type="text" id="address" placeholder="1234 Main St"
      [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
  </div>
  <div class="form-group">
    <label for="address2">Address 2</label>
    <input type="text" id="address2" 
    placeholder="Apartment, studio, or floor"
    [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
  </div>
...
  <button type="submit" *ngIf="auth.update">Update</button>
</form>
<div *ngIf="!auth.read">
    You are not authorized to view this content. Please contact your administrator.
</div>
<!-- User Component -->

<form *ngIf="auth.read">
  <div class="form-row">
    <div class="form-group col-md-6">
      <label for="firstName">First Name</label>
      <input type="text" id="firstName" placeholder="First Name"
        [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
    </div>
    <div class="form-group col-md-6">
      <label for="lastName">Last Name</label>
      <input type="text" id="lastName" placeholder="Last Name"
        [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
    </div>
  </div>
  <div class="form-group">
    <label for="address">Address</label>
    <input type="text" id="address" placeholder="1234 Main St"
      [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
  </div>
  <div class="form-group">
    <label for="address2">Address 2</label>
    <input type="text" id="address2" 
    placeholder="Apartment, studio, or floor"
    [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
  </div>
...
  <button type="submit" *ngIf="auth.update">Update</button>
</form>
<div *ngIf="!auth.read">
    You are not authorized to view this content. Please contact your administrator.
</div>
<!-- User Component -->

<form *ngIf="auth.read">
  <div class="form-row">
    <div class="form-group col-md-6">
      <label for="firstName">First Name</label>
      <input type="text" id="firstName" placeholder="First Name"
        [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
    </div>
    <div class="form-group col-md-6">
      <label for="lastName">Last Name</label>
      <input type="text" id="lastName" placeholder="Last Name"
        [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
    </div>
  </div>
  <div class="form-group">
    <label for="address">Address</label>
    <input type="text" id="address" placeholder="1234 Main St"
      [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
  </div>
  <div class="form-group">
    <label for="address2">Address 2</label>
    <input type="text" id="address2" 
    placeholder="Apartment, studio, or floor"
    [disabled]="!auth.create || !auth.update" *ngIf="auth.read">
  </div>
...
  <button type="submit" *ngIf="auth.update">Update</button>
</form>
<div *ngIf="!auth.read">
    You are not authorized to view this content. Please contact your administrator.
</div>
// Admin Role
{
    "name": "userForm",
    "create": true,
    "read": true,
    "update": true,
    "delete": true
}
// Admin Role
{
    "name": "userForm",
    "create": true,
    "read": true,
    "update": true,
    "delete": true
}
// Auditor Role
{
    "name": "userForm",
    "create": false,
    "read": true,
    "update": false,
    "delete": false
}
// API Response
const routeAuth = [..{
                      "name": "userForm",
                      "create": true,
                      "read": true,
                      "update": true,
                      "delete": true
}];

@Component({
  selector: 'user-form',
  templateUrl: './user-form.component.html'
})

export class UserFormComponent {
... 
    getData(authorization: Object){

        if(authorization.read){

            this.http.get('users').subscribe(response => {
                // do something
            });

        }
    }
}

additional uses for CRUD-based authorization:

beta testing

system maintenance

feature rollout

a/b testing

testing

  • what is authorization?

  • authentication: who are you?

  • authorization: what can you do?

  • what is authorization?

  • types of authorization

  • role-based

  • claims-based

  • attribute-based

  • what is authorization?

  • how to authorize

  • types of authorization

  • CRUD

questions?

brian childress

brian.childress@capitalone.com

thank you!

bit.ly/auth_auth

slides and resources: