Questions:
Is there a concept of user & role that is general to Servlet Containers?
If so, is there a container agnostic way to access those users and roles?
If not, is there a way to access Tomcat Realm users & roles?
Background:
I would like to either get all users and their roles from the Java webapp context (Servlet Container) or, better yet, query the users and their roles directly.
I see that there are projects like Apache Directory which let you do this for LDAP if you know the connection string. However, I want to be agnostic to the technology serving up the users and roles.
Specifically, I'm on Tomcat and in the simplest scenario want to access the users & roles in a) tomcat-users.xml b) any other configured Realm in the context. However, I am really looking for a solution which isn't specific to Tomcat and it's Realms.
In tomcat(or any other conytainer) (using std. Servlet API), directly accessing of user roles is not possible (without using tomcat/third party specific mechanisms). the getUserPrincipal & isUSerInRole are the two methods, access to the role list is not directly possible.
Since the API does not provision for such an access, I guess you will have to rely on other mechanisms which is container or technology specific.
As you pointed out, if the realm configured is a JNDI realm and the realm store is implemented over an LDAP, it is possible to write a servlet filter and get the roles from the LDAP and set them on session or on a thread local.
Related
I have two realms in Keycloak "internal" and "external".
As a user (not Admin!) from "internal" realm I would like to get list of users from "external" realm.
There is default Role "view_users" but I guess it's only for the users from the same realm right ?
is it possible as not admin user to access to another realm ?
how it would look like in java Spring Boot ?
This is not possible in Keycloak by design, realms are isolated from each other. The exception to this rule is the master realm. A user that is in the master and has the global admin role is allowed to do everything in all realms.
In addition, there are (automatically generated) management clients for all realms in the master realm, in your case named internal-realm and external-realm. These clients, in turn, have a list of client-roles that allow the user that is in those roles, to perform specific actions. You can read more about this in the Keycloak documentation here.
I need to create an application with authentication and authorization using Java EE 6 (Glassfish Server). I read a lot about Java EE 6 security and just wanted to ask if my concept is correct:
Every user in the company has an account according to "X123456". I want to use this for LDAP Authentication:
Application ---> LDAP
So, I can use the company's infrastructure to authorize the user.
However I want to be in control of the roles in my application. So, I want to define my own roles using JACC. Therefore I will create a database with a user-to-role mapping,
Example: "X123456 -> ADMIN".
The benefits would be:
I don't need to store any password
I can create a kind of admin panel in my application where I can set the existing roles to users dynamically
Do you think this would be technically possible and good practice?
Alternative: Would it be possible to define the roles (Admin, User) in Active Directory and query it via LDAP? So I could outsource my user-to-role mapping into active directory.
Update:
For authentication I currently use a LDAP-Realm (user, password).
For authorization I want to use a database (rolename, user). However I don't know how to tell my application to use the database for authorization. If I would use a JDBC-Realm, I could specify the Group/Role table and column. Is there a way to tell my application to just use the JDBC-Realm for authorization?
I have web-app on Tomcat. I need to limit access to all its resources only for authenticated users. User logins and credentials are located in some DB table with according columns. What's the easiest way to implement this in the case database schema is not to be modified.
I found some options:
Extend tomcat JDBCRealm. It requires additional table for roles (that's why extending instead of using standard), but i have simplified case of just one role.
Implement JAAS LoginModule based on DB. If there is existing opensource solutions with license for usage in proprietary software let me know about it.
After successful login put an user in session attribute. Then implement servlet filter that checks for presence of that attribute in the session.
Probably there are simpler options. So it will be interesting to see them.
Is there any way to extend the authentication operation which connects a client application to an EJB, using standard JAAS/container-based security? I'm looking for a way to use more than just a username to authenticate the user (in this case a domain name is also needed). Ideally I'd like to be able to use the SessionContext.getCallerPrincipal() to get access to both the username and the domain name in the EJB.
I'm using Glassfish, if that influences the answer at all. Do I need to create a custom login module/custom realm and what should it do?
Adding authentication mechanisms to an EJB Container is usually a vendor specific task. I don't believe there is a standard way to do it. For Glassfish though, I believe this article will help you set up a SAM (Serve Auth Module) that can handle the authentication in any way you need. http://blogs.oracle.com/enterprisetechtips/entry/adding_authentication_mechanisms_to_the
Keep in mind this is Glassfish specific.
I'm working on an existing j2ee app and am required to remove some vendor specific method calls from the code.
The daos behind a session facade make calls into the ejb container to get the user's id and password - in order to connect to the database. The user id and password part of the initialContext used to connect to the server.
I am able to get the userid using sessionContext.getCallerPrincipal()
Is there anyway to get to the SECURITY_CREDENTIALS used on the server connection or, is there a way to pass information from the server connection into the ejbs (they are all stateless session beans).
This is a large app with both a rich-client and web front end, and in a perfect world I'd be happy to go back and re-architect the entire solution to use J2EE security etc - but unfortunately, that is not realistic.
I can't give you a generic solution, but this is what has worked for us. We have the app server connect to LDAP as a specific user that has the ability to request credentials for other users. Then we have some generic security code that we can use to request a users credentials from inside the session beans, based on the users identity from their initial login (just as you are doing it via getCallerPrincipal()).
We also place the users identity in a thread local variable, so that classes down the call chain from the EJB do not have to be "container aware". They simply access the identity from the thread local and use the security classes to look up user profile information. This also makes it easy to change the implementation for testing, or even something other than LDAP lookups.
Other conveniences we created were a JDBCServiceLocator that retrieves connections with user/password for the current user. So the developer does not have to explicitly code the security lookups at all.
Normally the Java EE security model will not allow the retrieval of the user password, for security reasons. But it depends on the implementation. Some vendors provide methods to retrieve this kind of information, but if you rely on such implementations, be aware that the portability of the application will be compromised.
One common approach is to write a servlet filter to intercept the login request and save a copy of the credentials, to be used later. If your application doesn't use the Java EE security infrastructure, this could be easily implemented. That's because some vendors prevent you from filtering an authentication servlet.
Robin,
Sounds like what I was planning. I figured I'd make a call right after a successful server connection to load the credentials into a threadLocal variable on my connection class. I was hoping there was an easier way - but I guess not.