/** * Authenticate the user by prompting for the SSO Session Identifier assigned by the SSO Gateway * on logon. * * <p>This method obtains from the gateway, using the provided session identifier, the user * associated with such session identifier. Only the NameCallBack is used, since its not a * user/password pair but only one value containing the session identifier. Any other callback * type is ignored. * * @return true in all cases since this LoginModule should not be ignored. * @exception javax.security.auth.login.FailedLoginException if the authentication fails. * @exception javax.security.auth.login.LoginException if this LoginModule is unable to perform * the authentication. */ 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[4]; // Just ask for the session identifier callbacks[0] = new NameCallback("ssoSessionId"); callbacks[1] = new PasswordCallback("password", false); callbacks[2] = new NameCallback("appID"); callbacks[3] = new NameCallback("nodeID"); String ssoSessionId; String ssoSessionId2 = null; try { _callbackHandler.handle(callbacks); ssoSessionId = ((NameCallback) callbacks[0]).getName(); if (((PasswordCallback) callbacks[1]).getPassword() != null) ssoSessionId2 = String.valueOf(((PasswordCallback) callbacks[1]).getPassword()); _requester = ((NameCallback) callbacks[2]).getName(); _nodeId = ((NameCallback) callbacks[3]).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 + "/" + ssoSessionId2); try { if (ssoSessionId2 != null && !ssoSessionId2.equals(ssoSessionId)) ssoSessionId = ssoSessionId2; // 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 = null; SSOAgent agent = Lookup.getInstance().lookupSSOAgent(); SSOIdentityManagerService im = agent.getSSOIdentityManager(); if (_nodeId != null && !"".equals(_nodeId)) { im = agent.getSSOIdentityManager(_nodeId); } ssoUser = im.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()); _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; }
/** * Return the Principal associated with the specified username and credentials, if there is one; * otherwise return null. * * <p>The method was completely rewritten since the overriden operation, on succesfull * authentication, sets as the authenticated Principal a SimplePrincipal instantiated using the * provided username. The problem is that in JOSSO the username is a SSO Session Id, not a * username. So we need to set the SSOUser returned by the Gateway as the authenticatd Principal. * Since the JaasSecurityManager caches the authenticated user using the Principal referring to a * JOSSO Session Id, we will need to map, for example when roles are checked against the realm, a * user Principal back to its JOSSO Session Identifier Principal. This way the the user and its * roles can be retrieved correctly by the JaasSecurityManager. * * @param username Username of the Principal to look up * @param credentials Password or other credentials to use in authenticating this username */ public Principal authenticate(String username, String credentials) { logger.debug("Begin authenticate, username="******"No security context for authenticate(String, String)"); return null; } // Get the JBoss security manager from the ENC context SubjectSecurityManager securityMgr = (SubjectSecurityManager) securityCtx.lookup("securityMgr"); if (!isSSODomain(securityMgr.getSecurityDomain())) { // This is not a SSO Security domain, let JBoss realm handle this ... return super.authenticate(username, credentials); } principal = new SimplePrincipal(username); char[] passwordChars = null; if (credentials != null) passwordChars = credentials.toCharArray(); String requester = ""; // Check for nulls ? SSOAgentRequest request = AbstractSSOAgent._currentRequest.get(); if (request == null) logger.error( "No SSO Agent request found in thread local variable, can't identify requester!"); SSOAgent agent = Lookup.getInstance().lookupSSOAgent(); SSOIdentityManagerService im = request.getConfig(agent).getIdentityManagerService(); if (im == null) im = agent.getSSOIdentityManager(); requester = request.getRequester(); ssoUser = im.findUserInSession(requester, username); if (ssoUser != null) { logger.debug("User: "******" is authenticated"); Subject subject = new Subject(); subject.getPrincipals().add(ssoUser); logger.warn("WARN Cannot identify requester!"); SSORole[] ssoRolePrincipals = im.findRolesBySSOSessionId(requester, username); Group targetGrp = new BaseRoleImpl("Roles"); for (int i = 0; i < ssoRolePrincipals.length; i++) { subject.getPrincipals().add(ssoRolePrincipals[i]); targetGrp.addMember(ssoRolePrincipals[i]); // Add user role to "Roles" group } // Add the "Roles" group to the Subject so that JBoss can fetch user roles. subject.getPrincipals().add(targetGrp); logger.debug("Authenticated Subject: " + subject); // Make the cache aware of the user-session association so that // it can handle correctly cache entry lookups. // _cachePolicy.attachSessionToUser(principal, ssoUser); // Instead of associating the Principal used for authenticating (which is a // session id), sets the authenticated principal to the SSOUser part of the // Subject returned by the Gateway. JBossSecurityAssociationActions.setPrincipalInfo(ssoUser, passwordChars, subject); // Get the CallerPrincipal mapping RealmMapping rm = (RealmMapping) securityCtx.lookup("realmMapping"); Principal oldPrincipal = ssoUser; principal = rm.getPrincipal(oldPrincipal); logger.debug("Mapped from input principal: " + oldPrincipal + " to: " + principal); if (!principal.equals(oldPrincipal)) { _userPrincipalMap.put(principal, oldPrincipal); } } else { principal = null; logger.debug("User: "******" is NOT authenticated"); } } catch (NamingException e) { principal = null; logger.error("Error during authenticate", e); } catch (SSOIdentityException e) { // Ignore this ... (user does not exist for this session) if (logger.isDebugEnabled()) { logger.debug(e.getMessage()); } principal = null; } catch (Exception e) { logger.error("Session authentication failed : " + username, e); throw new RuntimeException("Fatal error authenticating session : " + e); } logger.debug("End authenticate, principal=" + ssoUser); return ssoUser; }