uPortal Authorization System 2.0 Design

Proposal

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Author: Bernie Durfee

Design: Alex Vigdor, Bernie Durfee, Dan Ellentuck, Don Fracapane

 

1        Introduction

This document outlines the design of a new permission based authorization system. The goal is for this system to be combined with a group management system and to replace the existing uPortal authorization service. The initial version of uPortal authorization was based on the storage and manipulation of simple role information. Below is the original API:

 

public interface IAuthorization

{

  public boolean isUserInRole(IPerson person, IRole role);

  public Vector  getAllRoles();

  public int     setChannelRoles(int channelID, Vector roles);

  public boolean canUserPublish(IPerson person);

  public Vector  getAuthorizedChannels(IPerson person);

  public boolean canUserSubscribe(IPerson person, int channelID);

  public boolean canUserRender(IPerson person, int channelID);

  public Vector  getUserRoles(IPerson person);

  public void    addUserRoles(IPerson person, Vector roles);

  public void    removeUserRoles(IPerson person, Vector roles);

}

 

The problem with this API is that it mixes role management functionality with authorization functionality. “Can principal X perform activity Y on target Z” is commonly used to define the authorization. In the old API, this question is only answered by the following methods:

 

public boolean canUserPublish(IPerson person);

public Vector  getAuthorizedChannels(IPerson person);

public boolean canUserSubscribe(IPerson person, int channelID);

public boolean canUserRender(IPerson person, int channelID);

 

While the remaining methods deal with role management:

 

public boolean isUserInRole(IPerson person, IRole role);

public Vector  getAllRoles();

public int     setChannelRoles(int channelID, Vector roles);

public Vector  getUserRoles(IPerson person);

public void    addUserRoles(IPerson person, Vector roles);

public void    removeUserRoles(IPerson person, Vector roles);

 

 

 

 

 

 

 

 

 

 

 

 

2        The New System

 

After some discussions at Columbia University it has become evident that splitting up these two sets of methods would benefit the overall design of the authorization system. In doing so, a very simple and yet powerful system emerges. The former set of methods can be represented by a generic authorization system and the latter set of methods need to be incorporated into a group/role management system. This document proposes a solution for a generic authorization system.

 

PermissionManager

The new authorization system would be based on an API that would be available and useful to both the framework and channels. Its API is based on answering the “Can principal X perform activity Y on target Z” question. The API for the new authorization system consists of the following methods:

 

public abstract class PermissionManager

{

  // Store the name of the owner of this instance

  protected String m_owner = null;

 

  // Constructor that makes sure that an owner

  // is bound to each instance of a PermissionManager

  public PermissionManager(String owner)

  {

    m_owner = owner;

  }

 

  // This method adds a Permission object to the system

  public void setPermission(Permission newPermission);

 

  // This method adds a set of Permissions objects to the system

  public void setPermissions(Permission [] new Permissions);

 

  // This method retrieves a set of Permission objects based

  // on the given parameters. Null parameters are ignored.

  public Permission [] getPermissions( String principal,

         String activity,

         String target )

}

 

 

 

 

 

 

 

 

 

 

 

 

Permission

This object represents a single permission in the system. This object contains the answer to a single “Can principal X perform activity Y on target Z” question. These permission objects can be bound to either the uPortal framework, a single channel or even shared among all uPortal entities.

 

public abstract class Permission

{

  // Store the name of the owner of this instance

  protected String m_owner = null;

 

  // Constructor that makes sure each Permission has an owner

  public Permission(String owner);

 

  // Returns the owner of this Permission

  public String getOwner();

 

  // Getter and setter methods for Permission information

  public String getPrincipal();

  public void   setPrincipal(String principal);

  public String getActivity();

  public void   setActivity(String activity);

  public String getTarget();

  public void   setTarget(String target);

  public String getType();

  public void   setType(String type);

  public Date   getEffective();

  public void   setEffective(Date effective);

  public Date   getExpires();

  public void   setExpires(Date expires);

}

Owner

This is a token that describes who ‘owns’ the Permission. This token generally denotes the entity that created and uses the Permission. As a result this is most likely the only entity to which the Permission will have meaning.

An example of an owner would be a channel ID. The framework will create a PermissionManager object for each channel published in the system. This channel specific PermissionManager would only allow channels to create/read/modify Permission objects that they own. This will prevent channels from manipulating Permission objects that don’t belong to them.

Principal – Activity - Target

These are tokens that make up the X, Y and Z in “Can principal X perform activity Y on target Z”. These tokens will most likely only have meaning in the context of the object that uses them.

Effective – Expires

These dates represent suggested effective and expires dates relate to the Permission. These tokens will most likely only have meaning in the context of the object that uses them.

 

Type

This field is intended to specify the Permission type, such as GRANT or DENY.

.

 

3        Reference Implementation

 

As with most parts or uPortal the authorization system is based on the Factory design pattern. There will be an interface that can be implemented by any uPortal site to meet any specific needs. However, a solid reference implementation of this system is needed because this design is meant to meet the needs of most uPortal implementers. The reference implementation being proposed consists of the following parts:

 

Database

The Permission objects will be stored persistently in a relational database. The schema for the database simply reflects the structure of the Permission objects themselves:

 

OWNER            VARCHAR(255)

PRINCIPAL            VARCHAR(255)

ACTIVITY            VARCHAR(255)

TARGET            VARCHAR(255)

EFFECTIVE            TIMESTAMP

EXPIRES            TIMESTAMP

 

Caching

A well performing authorization system is crucial due to the fact that it will be queried very often by many pieces of uPortal during use. An efficient and robust caching mechanism must be in place in order for any implementation to be viable. This caching can be done through the use of entity beans inside of an EJB server, but for the uPortal’s needs a custom solution is required.

This solution would most likely cache the Permission object as they are retrieved from the database. This cache would keep the objects alive for a specified period of time. After this time the cache would expunge the Permission so that it is retrieved from the database again. This would compensate for the fact that Permissions may change in the database, but should not change often enough to forgo the use of a cache.

 

 

 

 

 

4        Example Usage

Can the current user publish channels?

From inside the CHeader channel you would…

 

// Get the IPerson object for the current user

String personID = staticData.getPerson().getID() + “”;

 

// Get the Permission manager object that has been

// created for the CHeader channel and stored in the

// StaticData object by the framework.

PermissionManager pm = staticData.getPermissionManager();

 

// Check to see if the current user has the Permission to publish.

// Ask the question, “Can principal (personID) publish?”

Permission [] permissions =

      pm.getPermissions(personID, “publish”, null);

 

…at this point the reference implementation would check for a row that contained the person’s ID in the PRINCIPAL column and the string ‘Publish’ in the ACTIVITY column. Permission objects would be built based on the results.

 

// Check to see if anything was returned

if(permissions != null && permissions.length > 0)

{

  // Allow the user to publish

}

 

This is a very simple example. To make better use of the system the framework could check the effective and expires dates. Another option would be for the framework to render a publish link based on who the current user can publish too. Each returned Permission object could be checked for a target, these rows could exist…

 

OWNER    PRINCIPAL       ACTIVITY     TARGET

chan01   english_prof    Publish      english_student

chan01   physics_prof    Publish      physics_student

chan01   administrator   Publish      NULL

 

…this would say that…

 

User’s in the english_prof group can publish to user’s in the english_student group.

 

User’s in the physics_prof group can publish to the user’s in the physics_student group.

 

User’s in the administration group can publish to anyone.

 

…each of the above statements would be up to the interpretation of the CHeader channel. Group information could be retrieve from a group management system. All rows in the UP_PERMISSIONS table would be created by an administration tool, XML descriptor file, etc.

 

5        Additional Issues

 

Permission creation and security

As addressed above, creation of Permission objects needs to be carefully controlled. With the proliferation of channels written by third parties, uPortal implementers should be wary of inter-portal security. For instance, it’s possible that third part can write a channel that acts maliciously inside of the uPortal server. Allowing channels to create Permission objects with any owner field would allow for channels to add or modify the Permission objects owned by other channels.

The owner field of a Permission object should be used to effectively prevent channels from manipulating each others Permission objects. So a PermissionManager should be carefully implemented to only dole out Permission objects that belong to the requestor. Permission objects themselves should have an immutable owner field to make sure that they are stored properly.

 

Why not the java.security or JAAS package?

It is the goal of uPortal to utilize as many standard Sun Java packages as possible. There will be debate as to why the standard Java security package is not utilized for Authorization. After much review it is the author’s opinion that this package was designed and written for code level authorization.

The components of uPortal are concerned with authorization on a higher level. Channels will use the authorization system to determine how to render their content. Try to fit code-level authorizations into this task does not seem reasonable.

The system described in this document is sufficiently simple and abstract as to provide high usefulness with little effort. It is also modeled after the standard Java packages to make migration to a future Java standard that fits the uPortal model better.