You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Carsten Klein <c....@datagis.com> on 2021/04/08 20:08:07 UTC
Getting additional attributes for logged on users
Hi there,
from a servlet, the logged on user is represented by a Principal
instance, which has a getName() to get the logon name of that user. In
most cases, that is a more or less cryptic name like c.klein or m.scott.
Some of our customers like the name of the currently logged on user be
displayed in the application's GUI. We all know that from many popular
applications.
While relying on the Servlet specs only, we can just show that
non-user-friendly logon name. Our customers prefer seeing the user's
display name. Other attributes of the user, like e-mail address, phone
number, department etc., is often welcome (if not required) information
during an application's lifetime.
It's not too hard to hook into session initialization and get the
required extra information, for example through JDBC or JNDI, if the
user database is actually an Active Directory Server. That information
can then be stored in the user's session attributes map.
However, one has to implement that information retrieval "by hand" for
every application and/or customer. Even worse, typically credentials are
required to access the storage in which that information lives. If it's
in the application's 'standard' database, there's a good chance to have
a Tomcat connection pool. However, in general, you need credentials and
access data to get these additional attributes (credentials and JDBC URL
may be configured in Context or Servlet parameters).
Does anybody know a more general way to get such extra user attributes?
My proposal:
Typically, those desired extra attributes are stored in the user's
record in the user database. That may be a SQL database or may be an
Active Directory Server (or any other directory), which is already used
for authentication and authorization.
Wouldn't it be cool to make the Realm get us that extra information?
Why the realm?
First, in order to perform authentication, the Realm already has access
to the user database. So, access data and credentials must not be
configured twice at different places.
Second, the Realm knows how to query the user database and does that
already for retrieving roles and passwords. Getting some more fields
shouldn't be a big deal.
Third, the Realm actually creates and initializes the Principal instance
so, it should be easy to store these extra user attributes in an
extended version of the TomcatPrincipal class. A simple Map<String,
String> should be sufficient, but for the sake of uniformity, the well
known methods getAttribute, getAttributeNames, removeAttribute and
setAttribute may be a better option.
That's clearly something not all Realms can/shall support. Likely
JAASRealm will not, since it uses custom Principal classes. But
JNDIRealm, JDBCRealm and DataSourceRealm (not yet sure about
UserDatabaseRealm) could easily support that feature.
In its simplest form, these Realms get a new configuration property
'extraAttributes', which takes a comma separated list of field names to
retrieve. Implicitly, for an SQL-based Realm, these fields are queried
from the 'userTable' table. The JNDIRealm tries to find these attributes
from the user's entry in the directory, of course.
More complex configurations are possible (but likely not needed).
I'm curious what you think about it :)
Carsten
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
Re: Getting additional attributes for logged on users
Posted by Carsten Klein <c....@datagis.com>.
Hi there,
are there other comments on that? I'd like to implement this and want to
provide a CR On GitHub, if there is a fair chance, that this enhancement
will make it into Tomcat :)
Trying to summarize what has been discussed so far: (read the other
posts for more information)
The basic idea is to obtain additional user attributes and providing
these to the application through an "attributes" map of the Principal
class (e. g. the user's display name, e-mail address, etc.).
Since such user (-related) data is often available in data stores also
used for authentication, it shall be up to the Realm to query these
extra attributes. (Additionally, the Realm already has access data and
credentials to access that data store and also creates and populates the
Principal instance.)
The provided extra user information is not crucial for the Realm and its
authentication and authorization process.
Olaf Kock was suggesting to agree upon a set of "standard" additional
user attributes, which the Realm should query for by default. However,
for at least these reasons, I believe that this is just not possible:
1. Every application's needs are different
2. Every user data store is different
3. Cultural differences may require different attributes to form names
or addresses, for example
In contrast to that, my initial idea was to specify the desired extra
user attributes as a comma separated list though a new configuration
option of the Realm (called "extraAttributes" or "userAttributes"). This
list is nearly equivalent to a SELECT clause in SQL. However, that
"SELECT clause" shall work as well with Realms not based on SQL.
Not all Realms can/shall support that optional new feature. For example,
JAASRealm, which is merely a wrapper around an arbitrary authentication
and authorization process behind the curtain, likely cannot participate
in this.
The queried attributes shall be provided to the application through a
new "attributes" map of the Principal instance. Accessors to this map
should be declared in either TomcatPrincipal or GenericPrincipal. Still
to discuss, what accessors to implement:
Map<String, Object> getUserAttributesMap() {}
vs.
Object getUserAttribute(String name)
String[] getUserAttributeNames()
void setUserAttribute(String name, Object o)
void removeUserAttribute(String name)
The attribute names specified in the configuration option (SELECT
clause) must be the actual field names of the attribute, of course.
These also form the names/keys of the attributes in the Principal's
attribute map (could/should be prefixed with a namespace or prefix):
Realm-Configuration:
userAttributes="attr1, displayName, dept_no"
Using the attributes:
String s1 = principal.getUserAttribute("attr1")
// with a namespace/prefix (configurable and with a default value?)
String s2 = principal.getUserAttribute("realm.usrattr.displayName")
I believe that implementing the discussed enhancement is not too
difficult, since only (some of) the Realm classes as well as the
Principal implementation must be modified (TomcatPrincipal and/or
GenericPrincipal). Also, I do not see any security related risks.
Carsten
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
Re: Getting additional attributes for logged on users
Posted by Carsten Klein <c....@datagis.com>.
Hi Olaf,
also, I only picked your statements for an answer.
> On 08.04.21 13:53, Olaf Kock wrote:
>
> It would be cool, absolutely.
>
> Even cooler if "the desired extra attributes" could be agreed upon - or
> even what would be desirable in user management (is user + roles enough?
> That requires redeployment any time the system gets more picky with
> permissions.
>
> Personally, I work with Liferay, where roles are runtime-configurable
> and map to permissions. The permissions are what's checked in the
> application code, and the applications couldn't care less about number
> of roles or path through which a permission is assigned to a user.
I'm not sure whether I got you right. For my mind, my idea has nothing
to do with authorization, roles and permissions. Also, I don't think
that the set of desired extra attributes is something that could be
agreed upon. It's rather very specific for a project and/or customer.
The basic idea is just to get some of the user's attributes/properties
for (any/free) usage by the application. Actually this proposal only
(ab)uses the Realm, since it already has configured access to a storage,
that one might call the 'user database'.
However, these attributes are only used by the application. These are
not used for authorization or grant of permissions.
>
> You first state "its simplest form", then state that more complex
> solutions are likely not needed.
>
> I'd argue that the current form is "the simplest form", as it provides
> identifiers that can be used to look up extra information according to
> the application's need.
What can be simpler than a comma separated list of field names? If we
can agree upon the set of desired user attributes (which we can't
surely), no configuration will be required. That's would be simpler but
won't work, since every user database is different and desires are too.
>
> I don't want to tear down your idea - only reflect that "only a little
> bit more" will be barely enough for the next person coming around, and
> end up being a really complex beast. And if you look at all the
> different available attributes for users that make sense in some, but
> not in other countries/cultures, you'll soon be implementing your own
> anyway:
>
> * What makes up the name? First/Last Name? Including middle name (common
> in US, almost nonsensical in Germany)? There are cultures with just a
> single name
> * Gender: How many choices and what will they be named (by law, Germany
> now has 3 genders)
> * Address: I've recently sent out letters to international addresses,
> and boy was it hard to ask for the right information to go to the
> address sticker.
> * Department: Makes sense in a business environment, not at all in a
> community environment
That's why I recommend that the desired attributes must be specified in
a list. That list can be seen as the SELECT clause of an SQL statement
(but this will work with an Active Directory Server and likely
tomcat-users.xml as well).
In one of our projects, we authenticate users against the customer's
Active Directory Server. The sAMAccountName attribute is used as the
user's logon name. That's what the principal returns in its getName()
method. For example, we output that name in the footer of printed
reports. On reports created by me, 'c.klein' is shown.
In the ADS, my user class also has these attributes: (among many others)
displayName: ext. Klein, Carsten
givenName: Carsten
name: ext. Klein, Carsten
sn: Klein
(ext. = I'm an external user)
So, in order to show a more user-friendly name on the reports, I'd
configure the extraAttributes list to contain attribute 'displayName'.
Since our reports are template driven, I could as well retrieve fields
'givenNamen' and 'sn' and build my on report specific display name like
'${givenName} ${sn}' (with the knowledge in mind, that it's a German
customer and names in Germany typically are written that way).
> While you name some samples that sound agreeable on first sight, I don't
> think that they're agreeable enough to impose them on people unless
> provided voluntarily and under arbitrary names. Which ends up with the
> cost of a huge framework in order to potentially save a single database
> request per log in.
I guess, we will never find a bunch of attributes everybody can agree
with in all countries, companies and projects. So, there will likely
never be a mechanism that provides extra user attributes voluntarily.
But that was never announced. Some minimal and simple configuration is
still required.
For the same reason these attributes cannot be provided under arbitrary
names. But we could simply use the configured field names (which must be
the actual field names):
Config:
extraAttributes="displayName, givenName, sn"
Code: (no safe type checks here)
Principal p = ((TomcatPrincipal) request.getUserPrincipal());
out.writeln(p.getAttribute("displayName"));
It's not about saving a single database request per log in (at least not
from a performance point of view, technically, the request must be made
anyway).
But, it's about a simple, safe and reproducible way to get additional
fields from the user's record in the user database by just specifying
field names in a simple list. This can be done (and later changed) by
configuration only. No class has to be written. No extra configuration
for accessing the user database must be provided. No knowledge of SQL or
LDAP queries is required.
That's what this proposal offers: generic configurable retrieval of
extra attributes from the user's record in the user database. Nothing
more and nothing less. There's no room for an Extrawurst. If someone
want's "only a little bit more", he's free to leave the Relam's
attribute 'extraAttributes' empty and run his own mechanism.
Finally, I don't think that implementing this requires too much work (I
don't see the beast in it nor do I see a huge framework). If we stick to
the above offering, it's only about some additions to the Realm classes,
the TomcatPrincipal interface (optionally) and the GenericPrincipal class.
Carsten
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
Re: Getting additional attributes for logged on users
Posted by Olaf Kock <to...@olafkock.de>.
Hi Carsten,
I'll be limiting my answer to the most notable lines and quote only those.
(anybody else reading this without following the mails live: Go to the
archive to see Carsten's full post)
On 08.04.21 22:08, Carsten Klein wrote:
>
> Typically, those desired extra attributes are stored in the user's
> record in the user database. That may be a SQL database or may be an
> Active Directory Server (or any other directory), which is already
> used for authentication and authorization.
>
> Wouldn't it be cool to make the Realm get us that extra information?
It would be cool, absolutely.
Even cooler if "the desired extra attributes" could be agreed upon - or
even what would be desirable in user management (is user + roles enough?
That requires redeployment any time the system gets more picky with
permissions.
Personally, I work with Liferay, where roles are runtime-configurable
and map to permissions. The permissions are what's checked in the
application code, and the applications couldn't care less about number
of roles or path through which a permission is assigned to a user.
> In its simplest form, these Realms get a new configuration property
> 'extraAttributes', which takes a comma separated list of field names
> to retrieve. Implicitly, for an SQL-based Realm, these fields are
> queried from the 'userTable' table. The JNDIRealm tries to find these
> attributes from the user's entry in the directory, of course.
>
> More complex configurations are possible (but likely not needed).
You first state "its simplest form", then state that more complex
solutions are likely not needed.
I'd argue that the current form is "the simplest form", as it provides
identifiers that can be used to look up extra information according to
the application's need.
I don't want to tear down your idea - only reflect that "only a little
bit more" will be barely enough for the next person coming around, and
end up being a really complex beast. And if you look at all the
different available attributes for users that make sense in some, but
not in other countries/cultures, you'll soon be implementing your own
anyway:
* What makes up the name? First/Last Name? Including middle name (common
in US, almost nonsensical in Germany)? There are cultures with just a
single name
* Gender: How many choices and what will they be named (by law, Germany
now has 3 genders)
* Address: I've recently sent out letters to international addresses,
and boy was it hard to ask for the right information to go to the
address sticker.
* Department: Makes sense in a business environment, not at all in a
community environment
While you name some samples that sound agreeable on first sight, I don't
think that they're agreeable enough to impose them on people unless
provided voluntarily and under arbitrary names. Which ends up with the
cost of a huge framework in order to potentially save a single database
request per log in.
E.g.: It would be cool, but I don't see it worth the price.
my 2 (Euro) Cent
Olaf
>
> I'm curious what you think about it :)
>
> Carsten
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org