The purpose of this document is to provide a comprehensive introduction to OACC. This introduction assumes familiarity with the Java™ programming language; any application security concepts are introduced as needed.
An application security framework provides a systematic means to manage access to privileged operations in an application. The entity requesting access is typically a human user that is logged in to the application; the requesting entity does not, however, always need to be a human user: for example, it could also be another system interacting with the application. The requesting entity is called the subject in some security frameworks, in OACC it is called the accessor. The object or asset that is accessed in a security relationship is called the accessed in OACC.
Typically, the first step in interacting with a security framework involves verifying that the subject is who it claims to be; this step is referred to as authentication.
Before the subject is allowed to perform a privileged operation in the application, the application checks with the security framework to see if the subject has permission to perform the respective operation; this step is known as authorization.
OACC is an advanced Application Security Framework for Java™ applications; that provides authentication and authorization services.
OACC delegates authentication to the registered authentication provider. OACC uses the built-in password based authentication provider by default. The built-in password based authentication provider employs a number of best practices including one-way hashing, salting, binding, and lets you choose between BCrypt or Jasypt encryption. An application may use a custom authentication provider implementation to integrate with an LDAP, biometrics or any other type of credential store.
OACC provides a comprehensive set of authorization services. It provides a powerful set of primitives to define and query authorization relationships. An example of an authorization relationship is the following:
(JohnDoe) has (READ,WRITE) permissions on (Sales2014.xls).
Most application security frameworks, ironically, do not provide production ready support for managing authorization relationships. To manage authorization relationships a framework needs to have an abstraction for the application entities participating in a authorization relationship (and most security frameworks do not have such an abstraction in their design).
OACC provides the abstraction of a resource to represent an application entity, i.e. a resource is used as a surrogate for an application entity. Both the accessor and accessed that participate in an OACC authorization relationship are simply two resources.
Therefore the application does not need to design and implement a means to store and manage authorization relationships; it simply needs to register with OACC the application entities it wishes to secure. Alternatively, the application could store an association between an application object and the corresponding OACC resource by adding an attribute to an application object that stores the id of the OACC resource. In either case, the authorization relationships are stored in OACC's security data repository (implemented using a set of relational database tables).
To make things concrete, let's look at sample code that uses OACC to secure a document object in an application.
public Document getDocument(String documentId) {
// before we load the document, we ask OACC to check if the current user has
// permissions to READ it; we will throw an application-specific exception if
// the current user does not have the specified permission.
if (!accessControlContext.hasResourcePermissions(accessControlContext.getSessionResource(),
Resources.getInstance(documentId),
ResourcePermissions.getInstance("READ"))) {
throw new DocumentException("Not authorized to read document");
}
Document document = DocumentPersister.loadById(documentId);
return document;
}
The operative OACC call from the above code is shown below.
accessControlContext.hasResourcePermissions(accessControlContext.getSessionResource(),
Resources.getInstance(documentId),
ResourcePermissions.getInstance("READ"))
The call essentially checks if the currently authenticated resource has the specified "READ"
permission to the resource associated with the document that the user wants to load from the database.
Alternatively, OACC also provides an assert version of the above call:
accessControlContext.assertResourcePermissions(accessControlContext.getSessionResource(),
Resources.getInstance(documentId),
ResourcePermissions.getInstance("READ"))
The latter would throw a NotAuthorizedException
if the currently authenticated resource does not have the specified "READ"
permission to the resource specified by documentId
.
OACC provides the concept of a resource class to group resources of the same "class" of objects in an application domain. A resource class is identified by its unique string name (e.g. "DOCUMENT"
). Every resource belongs to exactly one resource class. For example, if an application domain has documents, it will likely have a resource class named DOCUMENT
for all resources that represent documents. Additionally, a resource class has the following properties:
If a resource belongs to a resource class with the authenticable property set to false, then passing an instance of the resource to the authenticate()
or setCredentials()
API calls will throw an exception. Resources that represent users will typically have the authenticable property set to true.
The unauthenticatedCreateAllowed property is a more rarely used facility. A typical resource class will have unauthenticatedCreateAllowed set to false, this means that resources of this class can only be created from an authenticated OACC context. If unauthenticatedCreateAllowed is set to true, then resources of this resource class can be created from an OACC context that is unauthenticated, in addition to an authenticated context.
OACC provides four different types of permissions to represent different types of security relationships. The table below summarizes each type of permission:
Permission type | Purpose |
---|---|
ResourcePermission | Used to grant an accessor permissions on one or more resources. |
ResourceCreatePermission | Used to grant an accessor the permission to create resources of a specific resource class. This permission is also used to specify the permissions an accessor gets on the new resource it creates (aka post create resource permissions). |
DomainPermission | Used to grant an accessor permissions on a specific domain. |
DomainCreatePermission | Used to grant an accessor the permission to create domains. The permission is also used to specify the permissions an accessor gets on a new domain it creates (these are called post create domain permissions). |
Each of the four permission types above operate in a particular scope. The table below shows the scope of each permission type. The ResourcePermission type has two possible scopes as shown below.
Permission type | Supported scope | Purpose |
---|---|---|
ResourcePermission | Resource | Used to grant an accessor permissions on a specific resource. |
ResourceClass + Domain (aka Global) | Used to grant an accessor permissions on all resources of a specific ResourceClass in a specific Domain. | |
ResourceCreatePermission | ResourceClass + Domain | Used to grant an accessor the permission to create resources of a specific ResourceClass in a specific Domain. |
DomainPermission | Domain | Used to grant an accessor permissions on a specific domain. |
DomainCreatePermission | System wide | Used to grant an accessor the permission to create domains. This permission is system-wide in scope. |
Shown below are the API methods that are used to get and set the permission types.
Permission type | Supported scope | API methods |
---|---|---|
ResourcePermission | Resource | setResourcePermissions(...) grantResourcePermissions(...) revokeResourcePermissions(...) getResourcePermissions(...) — getEffectiveResourcePermissions(...) |
ResourceClass + Domain (aka Global) | setGlobalResourcePermissions(...) grantGlobalResourcePermissions(...) revokeGlobalResourcePermissions(...) getGlobalResourcePermissions(...) — getEffectiveGlobalResourcePermissions(...) getEffectiveGlobalResourcePermissionsMap(...) | |
ResourceCreatePermission | ResourceClass + Domain | setResourceCreatePermissions(...) grantResourceCreatePermissions(...) revokeResourceCreatePermissions(...) getResourceCreatePermissions(...) — getEffectiveResourceCreatePermissions(...) getEffectiveResourceCreatePermissionsMap(...) |
DomainPermission | Domain | setDomainPermissions(...) grantDomainPermissions(...) revokeDomainPermissions(...) getDomainPermissions(...) — getEffectiveDomainPermissions(...) getEffectiveDomainPermissionsMap(...) |
DomainCreatePermission | System wide | setDomainCreatePermissions(...) grantDomainCreatePermissions(...) revokeDomainCreatePermissions(...) getDomainCreatePermissions(...) — getEffectiveDomainCreatePermissions(...) |
(...the rest of this document is currently being written, we decided to make available the part written so far instead of waiting until the document is complete)