Picketlink replacement for org.jboss.seam.security.Identity
cmartin Oct 4, 2013 10:52 AMI am trying to migrate a Seam 2.3 application to CDI. I was using Jboss security in order to be able to override the Seam identity class so I can use the JBoss Negotiation package for Kerberos authentication. The class uses the JBoss security packages to retrieve the authenticated user information for authorization. I have found that
picketlink has the following classes:
org.picketlink.idm.api.Identity
org.picketlink.idm.api.Credential
org.picketlink.idm.api.Role
but cannot find a replacement for org.jboss.security.SecurityContextAssociation for access to the javax.security.auth.Subject in order to get access to the Principals. This can be seen in the initialize method below. I have searched the documentation but cannot find anything. Can someone provide some direction as to how to rewrite this. Does picketlink support this ?
package com.session;
import com.common.security.UserPrincipal;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Startup;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.Role;
import org.jboss.security.SecurityContextAssociation;
import javax.security.auth.Subject;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Set;
/**
* Overriding the Seam identity class so we can use the JBoss Negotiation package for Kerberos
* authentication. The class uses the JBoss security packages to retrieve the authenticated user
* information for authorization. The identity assumes that the UserPrinciple class has been
* associated with the JAAS Subject from the Login Module.
*/
@SuppressWarnings("serial")
@Name("org.jboss.seam.security.identity")
@Scope(ScopeType.SESSION)
@Install(precedence = Install.APPLICATION)
@BypassInterceptors
@Startup
public class UserIdentity extends Identity {
// ------------------------------ FIELDS ------------------------------
@Logger
private Log log;
private Subject subject;
private UserPrincipal principal;
private boolean initialized;
// -------------------------- METHODS --------------------------
@Override
public Principal getPrincipal() {
if (principal == null) {
initialize();
}
return principal;
}
/**
* Initialize the subject and principle for the object. There is an assumption that the JBoss
* JAAS authentication has occurred and is stored in the SecurityAssociation object.
* <p/>
* Also the method assumes a UserPrincipal has been created.
*/
private synchronized void initialize() {
if (initialized) {
return;
}
subject = SecurityContextAssociation.getSubject();
if (subject == null) {
return;
}
Set<UserPrincipal> principalSet = subject.getPrincipals(UserPrincipal.class);
if (principalSet == null || principalSet.isEmpty()) {
log.error("ERROR WITH USER AUTHORIZATION. Unable to find the " + UserPrincipal.class + " in the JAAS subject.");
return;
}
principal = (UserPrincipal) principalSet.toArray()[0];
//Set the username and password so the credentials object is consider "valid" to
//the super class. We will use a dummy password since the user has already been
//validate in the JBoss JAAS setup.
Credentials credentials = getCredentials();
credentials.setUsername(principal.getName());
credentials.setPassword("dummy");
//Tell super class that we already have a valid principal
acceptExternallyAuthenticatedPrincipal(principal);
log.debug(credentials.getUsername() + " credentials and principal successfully configured");
initialized = true;
log.debug("Initialization of UserIdentity complete");
}
/**
* Overriding method because we need to use the Subject from JBoss JAAS instead of the one from
* the super class.
*
* @return the Subject from the JBoss JAAS authentication
*/
@Override
public Subject getSubject() {
if (subject == null) {
initialize();
}
return (subject == null) ? new Subject() : subject;
}
/**
* Checks if the authenticated user is a member of the specified role. Overrode method because the
* seam identity tries to login again and since we are using JBoss JAAS the login will not work.
*
* @param role String The name of the role to check
* @return boolean True if the user is a member of the specified role
*/
@Override
public boolean hasRole(String role) {
if (!securityEnabled) {
return true;
}
Set<Group> groups = getSubject().getPrincipals(Group.class);
for (Group group : groups) {
if (ROLES_GROUP.equals(group.getName())) {
return group.isMember(new Role(role));
}
}
return false;
}