Michael,
On 5/26/25 9:14 AM, Michael Osipov wrote:
Hi folks,
I seek guidance on a larger problem I need to solve where I do have a few ideas,
but am also considering to what degree it would make sense to add code to the
Tomcat codebase for the common good:
I have a realm impl called MyRealm which sources from "store A", is has roles
(groups) in a specific format and user attributes. It returns MyPrincipal.
Consider you have a webapp which has logical roles "user", "editor", "admin",
etc. and also uses those specific attributes. The webapp context maps the
roles from "store A" into the logical roles with the
PropertiesRoleMappingListener.
Now an additional MyRealm with "store B" comes into play. Of course, the
CombinedRealm works perfectly, but "store B" has different role names and
different attribute names.
The problem: Both "String Context#findRoleMapping(String)" and
"#addRoleMapping(String, String)" do not support 1:n mapping, e.g.,
"user" role maps to "store_a_role_1" and "store_b_role_5".
This would require changing/extending the interface and other classes.
The other problem is, of course, realm-specific. Say "store A" has attribute
"gid" which is semantically identically identical "store B" attribute
"employeeID". From an application PoV this is a consolidation nightmare
to touch every single spot to accommodate that.
My idea is going from:
<CombinedRealm>
<MyRealm source="store A" />
<MyRealm source="store B" />
</CombinedRealm>
to
<TransformingRealm roleMapper=... attributeMapper=...>
<CombinedRealm>
<MyRealm source="store A" />
<MyRealm source="store B" />
</CombinedRealm>
</TransformingRealm>
While the attributeMapper cannot be part of Tomcat because it is realm-specific,
do you see a benefit of modifying Context to accommodating 1:n mappings and of
course the aftermath?
Let me know your opinion whether this is of good use for the Tomcat code base.
For the same of completeness, I cannot add "user1", etc. to the application
because it will require some hefty code changes as well.
I must admit I've never used the role-mapping capabilities of the
servlet context before; I've only written applications that use the
one-and-only-one set of roles exposed by my user database. So perhaps my
comments come from a position of ignorance to your particular situation.
It seems to me that this can be entirely fixed by using a custom
Principal object: one that is already under the control of the Realm.
public class MyRealm extends RealmBase {
public Principal authenticate(...) {
...
return new CustomPrincipal(...);
}
public boolean isInRole(Wrapper wrapper, Principal principal, String
role) {
if(principal instanceof CustomPrincipal
&& ((CustomPrincipal)principal).isMine(this) {
return super.isInRole(reverseMapRole(role));
} else {
// Principal is not from this Realm
return false;
}
}
protected String reverseMapRole(String role) {
if("user".equals(role)) {
// Obviously, implement this as a configurable Map
return "CN=users,OU=groups,DC=example,DC=org";
} else {
return role;
}
public class CustomPrincipal extends GenericPrincipal {
private boolean isMine(MyRealm realm) {
return realm == MyRealm.this;
}
...
}
}
You can use the same class MyRealm for both of your Realms, each with a
different configuration. Since Tomcat already supports any attribute you
want to configure, just do something like:
<Realm class="com.example.authn.MyRealm"
roleMappings="user=CN=users,OU=groups,DC=example,DC=org;
editor=CN=editors,OU=groups,DC=example,DC=org"; and so on" />
Would what I have above work for you? It doesn't work for an application
that tries to manually perform reverse-role-mapping (because the Context
doesn't know about these mappings), but without changes to Jakarta EE
APIs, the application will /never/ be able to do this.
-chris
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org