14 June 2011

WebLogic Server: Listing Groups of an Authenticated User

Another question from a colleague today: "for a given authenticated user, how can I see what groups the user belongs to?" 

Yep, good question Pas. Not sure, but worth some time to find out.

Hunting through the WebLogic Security Documentation, I found a good description and diagram of how a Subject is related to a Principal.



A principal is an identity assigned to a user or group as a result of authentication. Both users and groups can be used as principals by application servers such as WebLogic Server. The Java Authentication and Authorization Service (JAAS) requires that subjects be used as containers for authentication information, including principals.

As part of a successful authentication, principals are signed and stored in a subject for future use.  

Any principal that is going to represent a WebLogic Server user or group needs to implement the WLSUser and WLSGroup interfaces, which are available in the weblogic.security.spi package.
Thus presumably, if you can get hold of the Subject, then you should be able to see the Principals associated with the User, of which some should reflect the Group(s) the User belongs to.

But how do you get the Subject?

I kept reading through documentation, but I couldn't see any really obvious description of where/how the Subject could be obtained. 

Then, after almost giving up and resorting to looking through the Javadoc, I found this small reference:
http://download.oracle.com/docs/cd/E17904_01/web.1111/e13711/thin_client.htm#i1030501

In Example 3-3, notice that the JSP is calling an API (request.getRemoteUser()) to get the name of the user that logged in.
A different API, weblogic.security.Security.getCurrentSubject(), could be used instead. To use this API to get the name of the user, use it with the SubjectUtils API as follows:

String username = weblogic.security.SubjectUtils.getUsername(
weblogic.security.Security.getCurrentSubject());
    
Note: In the actual doc, there's a missing opening parenthesis in the supplied code snippet.  I've added it in orange in the above.

Looking at the Javadoc, the weblogic.security.Security class has a static method that returns a javax.security.auth.Security object.

I also found a post from Edward Biemond here: http://blog.whitehorses.nl/2010/01/29/weblogic-web-application-container-security-part-1/ that discusses this area, from a slightly different more practical perspective perhaps.

With the Subject accessible and the description of the WLUser and WLGroup interfaces above, the group(s) an authenticated user belongs to can be readily discovered.
    
    import weblogic.security.Security;
    import weblogic.security.spi.WLSUser;
    import weblogic.security.spi.WLSGroup;
    ...
    private void doSubjectStuff(PrintWriter out, 
      HttpServletRequest request, 
      HttpServletResponse response) {

        Subject subject = Security.getCurrentSubject();
       
        StringBuffer groups = new StringBuffer();
        String user = null;
        boolean first = true;


        for(Principal p: subject.getPrincipals()) {
            if(p instanceof WLSGroup) {
                if(first) {
                    first=false;
                } else {
                    groups.append(", ");
                }
                groups.append(p.getName());
            } else if (p instanceof WLSUser) {
                user = p.getName();
            }
        }
       
        out.printf("<p>RemoteUser: %s, User: %s, belongs to: %s</p>",
                request.getUserPrincipal().getName(),
                user,
                groups);
    }



Calling this from a servlet, deployed within a simple web application that uses BASIC authentication mapped to a couple of WebLogic Server groups, the following output is displayed when the user "steve" logs in:
RemoteUser: steve, User: steve, belongs to: AppTesters, Deployers

Note, as Edmond also points out, the groups that are provided in the Subject are the WebLogic Server groups the user belongs to, and not the logical role-name defined in the web.xml file.
web.xml:

    <security-role>
        <role-name>ADMINS</role-name>
    </security-role>
weblogic.xml:

  <security-role-assignment>
    <role-name>ADMINS</role-name>
    <principal-name>AppTesters</principal-name>
    <principal-name>Administrators</principal-name>
  </security-role-assignment>
The primary new takeaway point I got from this was the use of the weblogic.security.Security class to obtain an instance of the current Subject.

8 comments:

Anonymous said...

This is really helpful, thanks heaps. Was looking for how to do something like this. What jar file do the WLUser and WLSGroup belong in?

DingDingLamLam said...

It really help, thanks.

Venkat Ramisetty said...

very useful, thank you.

Buttso said...

The WLSGroup and WLSUser classes are in the wls-api.jar which is likely to be the best place to reference them from.

-steve-

Raj said...

I was looking for similar one.Very very helpful. Detailed explanation.
Thank you.

Syl said...

hi Buttso, i would like to know what jar file must use to obtain the user using weblogic.security.security.getcurrentsubject... thanks..

Buttso said...

The weblogic.security.Security class is in

$MW_HOME/wlserver/server/lib/wls-api.jar: weblogic.security.Security

Or the wlthint3client client:

$MW_HOME/wlserver/server/lib/wlthint3client.jar: weblogic.security.Security


colo said...

Hello Buttso, I write to ask for your advice

I am not a WL expert and I have to develop a remote app to manage the users/Role/Groups in the WL. This is a bit rare because this app can NOT run inside the WL.
Is there any way to do something like this?, According to you, What would be the best way to do this?. Thanks in advance.