On this page
JAAS Policy
JAAS authorization uses Policy files to grant permissions to authenticated principals. Combined with Subject.doAs(), it controls what code a user can execute.
Permission Model
Java SE uses java.security.Permission subclasses:
| Permission | Controls |
|---|---|
FilePermission |
File read/write/execute |
SocketPermission |
Network connections |
RuntimePermission |
System operations |
AllPermission |
Everything (admin) |
Policy File
policy:
grant principal com.example.UserPrincipal "alice" {
permission java.io.FilePermission "/home/alice/-", "read,write";
permission java.net.SocketPermission "api.example.com:443", "connect";
};
grant principal com.example.UserPrincipal "admin" {
permission java.security.AllPermission;
};
grant codeBase "file:/app/lib/-" {
permission java.io.FilePermission "/tmp/-", "read,write";
};
Enable with:
java -Djava.security.policy=policy MyApplication
Subject.doAs()
Execute code with a subject’s permissions:
Subject subject = lc.getSubject();
Subject.doAs(subject, (PrivilegedAction<String>) () -> {
// Runs with alice's permissions
try {
Files.readString(Path.of("/home/alice/data.txt"));
return "success";
} catch (IOException e) {
return "denied";
}
});
PrivilegedAction vs PrivilegedExceptionAction
// No checked exceptions
String result = Subject.doAs(subject, (PrivilegedAction<String>) () -> "done");
// With checked exceptions
Subject.doAs(subject, (PrivilegedExceptionAction<Void>) () -> {
socket.connect(new InetSocketAddress("api.example.com", 443));
return null;
});
Custom Permission
public class OrderPermission extends Permission {
private final String action;
public OrderPermission(String name, String action) {
super(name); // e.g., "order:123"
this.action = action;
}
@Override
public boolean implies(Permission p) {
if (!(p instanceof OrderPermission)) return false;
OrderPermission other = (OrderPermission) p;
return (getName().equals("*") || getName().equals(other.getName()))
&& (action.equals("*") || action.equals(other.action));
}
@Override
public boolean equals(Object obj) { /* ... */ }
@Override
public int hashCode() { /* ... */ }
@Override
public String getActions() { return action; }
}
Policy.refresh()
Reload policy without restart:
Policy.getPolicy().refresh();
Modern Alternatives
JAAS policy-based authorization is largely superseded by:
- Spring Security method/URL security
- Java Security Manager (deprecated since Java 17, removed in Java 24)
- Container-level RBAC (Kubernetes, cloud IAM)
Best Practices
- Treat JAAS policy as legacy — use Spring Security for new projects
- Principle of least privilege: grant minimum permissions needed
- Separate authentication (LoginModule) from authorization (Policy)
- Audit policy files — they are security-critical configuration
- Test permission boundaries with integration tests using
doAs()