Introduction
The JavaTM Authentication and Authorization Service (JAAS) can be used for two purposes:
- for authentication of users, to determine who is currently executing Java code, and
- for authorization of users to ensure they have the access control rights (permissions) required to do the actions performed.
JAAS implements a Java version of the standard Pluggable Authentication Module (PAM) framework. See Making Login Services Independent from Authentication Technologiesfor further information.
Core Classes in JAAS
Subject:
To authorize access to resources, applications first need to authenticate the source of the request. The JAAS framework defines the term subject to represent the source of a request. A Subject may be any entity, such as a person or a service.
Once the Subject is authenticated, it can be populated with Prinicipals. A Subject can have many principals, such as a name or an identification number.
The Method doAs and doAsPrivileged allows to perform an action as a particular Subject.
doAs vs. doAsPrivileged
The doAsPrivileged methods behave exactly the same as the doAs methods, except that instead of associating the provided Subject with the current Thread's AccessControlContext, they use the provided AccessControlContext. In this way, actions can be restricted by AccessControlContexts different from the current one.
Principals:
As mentioned previously, Principals may be associated with a Subject if authentication is successful. Principals represent Subject identities, and must implement the java.security.Principal and java.io.Serializable interfaces. The Subject section describes ways to update the Principals associated with a Subject.
Credentials:
Public and private credential classes are not part of the core JAAS class library. Any class can represent a credential. Developers, however, may elect to have their credential classes implement two interfaces related to credentials: Refreshableand Destroyable.
The above information is taken from the JAAS Reference Guide. If you are interested in more details visit the online JAAS Reference Guide.
Spike using JAAS in an OSGI Environment
Attached to this page you find a spike which demonstrates how to do user authorization based on JAAS in an OSGi Environment.
You need to run your OSGi container with security enabled, e.g., assuming the use of felix, run it as follows:
$ java -Djava.security.manager -Djava.security.policy=all.policy -jar bin/felix.jar
The content of the file all.policy reads as follows:
grant {
permission java.security.AllPermission;
};
In this spike there are two OSGi bundles defined: bundle permissionmanagement is used to assign rights to users and bundle fileaccessbyuser is used to perform a specific file access related action as a specific user.
The following code snippets in the bundle fileaccessbyuser create a Subject which is assigned with a Principal of a specific username. This code snippets can be placed after a user has been authenticated successfully (which is not within the scope of this spike).
Subject subject = new Subject(); subject.getPrincipals().add(new PrincipalImpl(username)); try { Subject.doAsPrivileged(subject, new PrivilegedExceptionAction() { @Override public Object run() throws Exception { ... // invoke methods that require access control ... // e.g., File f = new File("/tmp/testfile_"+username); if (!f.exists()) { f.createNewFile(); } return null; } }, null); } catch (PrivilegedActionException pae) { System.out.println("PrivilegedActionException: " + pae.toString()); } catch (SecurityException se) { System.out.println("SecurityException: " + se.toString()); }
The implementation of PrincipalImpl can be as simple as this:
import java.security.Principal; public class PrincipalImpl implements Principal { private String name; public PrincipalImpl(String name){ this.name = name; } @Override public String getName() { return name; } }
In bundle permissionmanagement we define users' rights. This is shown in the following code snippets:
origPolicy = Policy.getPolicy(); Policy.setPolicy(new Policy() { @Override public PermissionCollection getPermissions(ProtectionDomain domain) { int numberOfPrincipals = domain.getPrincipals().length; System.out.println("Getting permissions for " + numberOfPrincipals + " principals ..."); PermissionCollection pc; if (numberOfPrincipals > 0) { pc = new Permissions(); for (Principal p : domain.getPrincipals()) { System.out.println("Principal " + p.getName() + ": " + p); getUserPermissions(p.getName(), pc); } } else { pc = origPolicy.getPermissions(domain); } System.out.println("Returning " + pc); return pc; } });
As an example, the method getUserPermissions add a Read- or Read&Write-FilePermission on directory /tmp to the PermissionCollection depending on the username
private void getUserPermissions(String username, PermissionCollection pc) { if (username.equals("hasan")) { //add read & write permission for user hasan in directory /tmp pc.add(new FilePermission("/tmp/-", "read, write")); } else if (username.equals("clemens")) { //add read permission for user clemens in directory /tmp pc.add(new FilePermission("/tmp/-", "read")); } }
We hope this spike will be useful for developers dealing with java security in OSGi environment. If you have comments, please don't hesitate to post questions to our discussion forum on java security.