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.

4 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-