package org.josso.applet.agent.jaas;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.josso.gateway.WebserviceGatewayServiceLocator;
import org.josso.gateway.identity.SSORole;
import org.josso.gateway.identity.SSOUser;
import org.josso.gateway.identity.exceptions.SSOIdentityException;
import org.josso.gateway.identity.service.SSOIdentityManagerService;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import java.util.Map;
public class JOSSOClaimsLoginModule implements LoginModule {
private static final Log logger = LogFactory.getLog(JOSSOClaimsLoginModule.class);
// initial state
private Subject _subject;
private CallbackHandler _callbackHandler;
// the authentication status
protected boolean _succeeded;
protected boolean commitSucceeded;
// the logged user and his roles.
protected String _currentSSOSessionId;
protected String _requester;
protected SSOUser _ssoUserPrincipal;
protected SSORole[] _ssoRolePrincipals;
protected SSOIdentityManagerService _im;
protected String _endpoint;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
this._subject = subject;
this._callbackHandler = callbackHandler;
}
public boolean login() throws LoginException {
if (_callbackHandler == null)
throw new LoginException("Error: no CallbackHandler available " +
"to garner authentication information from the user");
Callback[] callbacks = new Callback[3];
// Just ask for the session identifier
callbacks[0] = new NameCallback("ssoSessionId");
callbacks[1] = new NameCallback("appID");
callbacks[2] = new NameCallback("endpoint");
String ssoSessionId;
try {
_callbackHandler.handle(callbacks);
ssoSessionId = ((NameCallback) callbacks[0]).getName();
_requester = ((NameCallback) callbacks[1]).getName();
_endpoint = ((NameCallback) callbacks[2]).getName();
} catch (java.io.IOException ioe) {
throw new LoginException(ioe.toString());
} catch (UnsupportedCallbackException uce) {
throw new LoginException("Error: " + uce.getCallback().toString() +
" not available to garner authentication information " +
"from the user");
}
logger.debug("Requested authentication to gateway by " + _requester + " using sso session " + ssoSessionId);
try {
// If no session is found, ignore this module.
if (ssoSessionId == null) {
logger.debug("Session authentication failed : " + ssoSessionId);
_succeeded = false;
return false;
}
_currentSSOSessionId = ssoSessionId;
SSOUser ssoUser = getSSOIdentityManager().findUserInSession(_requester, ssoSessionId);
logger.debug("Session authentication succeeded : " + ssoSessionId);
_ssoUserPrincipal = ssoUser;
_succeeded = true;
} catch (SSOIdentityException e) {
// Ignore this ... (user does not exist for this session)
if (logger.isDebugEnabled())
logger.debug(e.getMessage(), e);
_succeeded = false;
return false;
} catch (Exception e) {
logger.error("Session authentication failed : " + ssoSessionId, e);
_succeeded = false;
clearCredentials();
throw new FailedLoginException("Fatal error authenticating session : " + e);
}
return true;
}
public boolean commit() throws LoginException {
if (_succeeded == false) {
return false;
} else {
try {
// Add the SSOUser as a Principal
if (!_subject.getPrincipals().contains(_ssoUserPrincipal)) {
_subject.getPrincipals().add(_ssoUserPrincipal);
}
logger.debug("Added SSOUser Principal to the Subject : " + _ssoUserPrincipal);
_ssoRolePrincipals = getRoleSets(_requester);
// Add to the Subject the SSORoles associated with the SSOUser .
for (int i=0; i < _ssoRolePrincipals .length; i++) {
if (_subject.getPrincipals().contains(_ssoRolePrincipals [i]))
continue;
_subject.getPrincipals().add(_ssoRolePrincipals [i]);
logger.debug("Added SSORole Principal to the Subject : " + _ssoRolePrincipals [i]);
}
commitSucceeded = true;
return true;
} catch (Exception e) {
logger.error("Session login failed for Principal : " + _ssoUserPrincipal, e);
throw new LoginException("Session login failed for Principal : " + _ssoUserPrincipal);
} finally {
// in any case, clean out state
clearCredentials();
}
}
}
public boolean abort() throws LoginException {
if (_succeeded == false) {
return false;
} else if (_succeeded == true && commitSucceeded == false) {
// login _succeeded but overall authentication failed
_succeeded = false;
clearCredentials();
} else {
// overall authentication _succeeded and commit _succeeded,
// but someone else's commit failed
logout();
}
return true;
}
public boolean logout() throws LoginException {
_subject.getPrincipals().remove(_ssoUserPrincipal);
logger.debug("Removed SSOUser Principal from Subject : " + _ssoUserPrincipal);
// Remove all the SSORole Principals from the Subject.
for (int i=0; i < _ssoRolePrincipals.length; i++) {
_subject.getPrincipals().remove(_ssoRolePrincipals[i]);
logger.debug("Removed SSORole Principal from Subject : " + _ssoRolePrincipals[i]);
}
_succeeded = commitSucceeded;
clearCredentials();
return true;
}
/**
* Reset the login module state.
*/
private void clearCredentials() {
_ssoUserPrincipal = null;
_ssoRolePrincipals = null;
_currentSSOSessionId = null;
}
/**
* Retreives the list of roles associated to current principal
*/
protected SSORole[] getRoleSets(String requester) throws LoginException {
try {
// obtain user roles principals and add it to the subject
return getSSOIdentityManager().findRolesBySSOSessionId(requester, _currentSSOSessionId);
} catch(Exception e) {
logger.error("Session login failed for Principal : " + _ssoUserPrincipal, e);
throw new LoginException("Session login failed for Principal : " + _ssoUserPrincipal);
}
}
protected SSOIdentityManagerService getSSOIdentityManager() {
if (_im == null) {
try {
WebserviceGatewayServiceLocator wsLocator = new WebserviceGatewayServiceLocator();
wsLocator.setEndpoint(_endpoint);
_im = wsLocator.getSSOIdentityManager();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
return _im;
}
}