Granite DS + CDI + Seam 3 Security run with JBoss AS 7.1

157 views
Skip to first unread message

Daniel Farkas

unread,
Jul 29, 2013, 11:09:49 AM7/29/13
to gran...@googlegroups.com
HI,

I have a CDI  project generated by GAS3, however I can not log in by custom autenticator.
The code:


SimpleAuthenticator.java

import javax.inject.Inject;

import org.jboss.seam.security.Authenticator;
import org.jboss.seam.security.BaseAuthenticator;
import org.jboss.seam.security.Credentials;

public class SimpleAuthenticator extends BaseAuthenticator implements Authenticator {

@Inject
private Credentials credentials;
@Override
public void authenticate() {  // the process does not go here
// TODO Auto-generated method stub
System.out.println(credentials.getUsername());
}

}


beans.xml

<?xml version="1.0" encoding="UTF-8"?>

   xmlns:s="urn:java:ee" 
   xmlns:security="urn:java:org.jboss.seam.security"
   
  <interceptors>
  <class>org.jboss.seam.security.extension.SecurityInterceptor</class>  
  </interceptors>

   <security:IdentityImpl>
      <s:modifies/>
       <security:authenticatorClass>org.example.SimpleAuthenticator</security:authenticatorClass>
   </security:IdentityImpl>  
</beans>


StackTrace when login:

11:55:17,606 ERROR [org.jboss.security.authentication.JBossCachedAuthenticationManager] (http-localhost-127.0.0.1-8080-3) Login failure: javax.security.auth.login.FailedLoginException: Password Incorrect/Password Required
at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:270) [picketbox-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.auth.spi.UsersRolesLoginModule.login(UsersRolesLoginModule.java:155) [picketbox-4.0.7.Final.jar:4.0.7.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_21]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_21]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_21]
at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_21]
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:784) [rt.jar:1.7.0_21]
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203) [rt.jar:1.7.0_21]
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698) [rt.jar:1.7.0_21]
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696) [rt.jar:1.7.0_21]
at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.7.0_21]
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:695) [rt.jar:1.7.0_21]
at javax.security.auth.login.LoginContext.login(LoginContext.java:594) [rt.jar:1.7.0_21]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(JBossCachedAuthenticationManager.java:449) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(JBossCachedAuthenticationManager.java:383) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.authenticate(JBossCachedAuthenticationManager.java:371) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(JBossCachedAuthenticationManager.java:160) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.as.web.security.JBossWebRealm.authenticate(JBossWebRealm.java:214) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.granite.messaging.service.security.Tomcat7SecurityService.login(Tomcat7SecurityService.java:78) [granite-core.jar:]
at org.granite.messaging.amf.process.AMF3MessageProcessor.processCommandMessage(AMF3MessageProcessor.java:94) [granite-core.jar:]
at org.granite.messaging.amf.process.AMF3MessageProcessor.process(AMF3MessageProcessor.java:61) [granite-core.jar:]
at org.granite.messaging.amf.process.AMF0MessageProcessor.process(AMF0MessageProcessor.java:78) [granite-core.jar:]
at org.granite.messaging.webapp.AMFMessageServlet.doPost(AMFMessageServlet.java:59) [granite-core.jar:]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.granite.messaging.webapp.AMFMessageFilter.doFilter(AMFMessageFilter.java:117) [granite-core.jar:]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_21]

 Thanks in advance.

wdrai

unread,
Aug 13, 2013, 9:24:22 AM8/13/13
to gran...@googlegroups.com
The error looks 'normal' as you are using the application container security:
org.granite.messaging.service.security.Tomcat7SecurityService

Integrating with Seam 3 Security would require a specific security service, which does not really exist.
We had started a prototype some time ago but never finished because Seam 3 was more or less abandoned:

public class Seam3SecurityService extends AbstractSecurityService {

// private static final Logger log = Logger.getLogger(Seam3SecurityService.class);
@Inject
private CDIServiceContext serviceContext;
@Inject
private Identity identity;
@Inject
private CredentialsImpl seamCredentials;
    public void configure(Map<String, String> params) {
    }

    public void login(Object credentials) throws SecurityServiceException {
        String[] decoded = decodeBase64Credentials(credentials);
        
        serviceContext.setLogin(true);
        
//        // Unauthenticate if username has changed (otherwise the previous session/principal is reused)
//        if (identity.isLoggedIn() && !decoded[0].equals(identity.getUser().getId())) {
//         try {
//         Method method = identity.getClass().getDeclaredMethod("unAuthenticate");
//         method.setAccessible(true);
//         method.invoke(identity);
//         } catch (Exception e) {
//         log.error(e, "Could not call unAuthenticate method on: %s", identity.getClass());
//         }
//        }

        seamCredentials.setUsername(decoded[0]);
        seamCredentials.setPassword(decoded[1]);
        String ok = identity.login();
        if (ok == null)
            throw SecurityServiceException.newInvalidCredentialsException("User authentication failed");
    }

    public Object authorize(AbstractSecurityContext context) throws Exception {
        startAuthorization(context);
        
        if (context.getDestination().isSecured()) {
            if (!identity.isLoggedIn()) {
                // TODO: Session expiration detection...
                // throw SecurityServiceException.newSessionExpiredException("Session expired");
                throw SecurityServiceException.newNotLoggedInException("User not logged in");
            }

            boolean accessDenied = true;
            for (String role : context.getDestination().getRoles()) {
                if (identity.inGroup(role, "ROLE")) {
                    accessDenied = false;
                    break;
                }
            }
            if (accessDenied)
                throw SecurityServiceException.newAccessDeniedException("User not in required role");
        }

        try {
            return endAuthorization(context);
        } catch (InvocationTargetException e) {
            for (Throwable t = e; t != null; t = t.getCause()) {
                // If destination is not secured...
                if (t instanceof NotLoggedInException)
                    throw SecurityServiceException.newNotLoggedInException("User not logged in");
                // Don't create a dependency to javax.ejb in SecurityService...
                if (t instanceof SecurityException ||
                    t instanceof AuthorizationException ||
                    "javax.ejb.EJBAccessException".equals(t.getClass().getName()))
                    throw SecurityServiceException.newAccessDeniedException(t.getMessage());
            }
            throw e;
        }
    }

    public void logout() throws SecurityServiceException {
    if (identity.isLoggedIn())
    identity.logout();
    }
}

And the corresponding client classes:

package org.jboss.seam.security {

    import flash.events.Event;
    import flash.utils.Dictionary;
    import flash.utils.flash_proxy;
    
    import mx.collections.ArrayCollection;
    import mx.collections.ItemResponder;
    import mx.core.Application;
    import mx.events.PropertyChangeEvent;
    import mx.messaging.events.ChannelFaultEvent;
    import mx.messaging.messages.ErrorMessage;
    import mx.rpc.AsyncToken;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.utils.object_proxy;
    
    import org.granite.events.SecurityEvent;
    import org.granite.tide.BaseContext;
    import org.granite.tide.Component;
    import org.granite.tide.IEntity;
    import org.granite.tide.IIdentity;
    import org.granite.tide.ITideResponder;
    import org.granite.tide.Tide;
    import org.granite.tide.events.TideContextEvent;
    import org.granite.tide.events.TideFaultEvent;
    import org.granite.tide.events.TideResultEvent;
    
    use namespace flash_proxy;
    use namespace object_proxy;
    

    [Bindable]
    /**
     * Implementation of the identity component for Seam services.<br/>
     *  Integrates with the server-side identity component of Seam.<br/>
     *  <br/>
     *  The basic way of using it is by populating username/password and calling login :<br/>
     *  <pre>
     *  identity.username = 'john';
     *  identity.password = 'doe';
     *  identity.login();
     *  </pre>
     * 
     * @author William DRAI
     */
[RemoteClass(alias="org.jboss.seam.security.Identity")]
    public class Identity extends Component implements IIdentity {
        
        public override function meta_init(componentName:String, context:BaseContext):void {
            super.meta_init(componentName, context);
            context.addContextEventListener(Tide.LOGIN, loginSuccessHandler);
        }
        
        public function set context(context:BaseContext):void {
            _context = context;
        }
public function get meta_credentialsClassName():String {
return "org.jboss.seam.security.CredentialsImpl";
}
        
        
        /**
         * Logged in
         */
        public function get loggedIn():Boolean {
            return super.getProperty("loggedIn");
        }
        /**
         * Logged in
         */
        public function set loggedIn(loggedIn:Boolean):void {
            setInternalProperty("loggedIn", loggedIn);
            if (!loggedIn)
_context.meta_logout(this);
        }
        
        
        /**
         * Triggers a remote call to check is user is currently logged in
         *  Can be used at application startup to handle browser refresh cases
         * 
         *  @param resultHandler optional result handler
         *  @param faultHandler optional fault handler 
         */
        public function isLoggedIn(resultHandler:Function = null, faultHandler:Function = null):void {
            var l:Boolean = loggedIn;
            var u:String = _context.byType(Credentials).username;
            
            _context.meta_isLoggedIn(this, resultHandler, faultHandler);
        }
        
        /**
         * Triggers a login request
         * 
         *  @param resultHandler optional result handler
         *  @param faultHandler optional fault handler 
         */  
        public function login(resultHandler:Function = null, faultHandler:Function = null):void {
            var l:Boolean = loggedIn;    // Force evaluation of loggedIn state
            
var credentials:Credentials = _context.byType(Credentials) as Credentials;
credentials.meta_login(this, resultHandler, faultHandler);
        }
        
        private function loginSuccessHandler(event:TideContextEvent):void {
            initSecurityCache();
        }
        
        
        /**
         * Triggers a logout request
         */  
        public function logout():void {
            loggedIn = false;
_context.byType(Credentials).username = null;
            
            clearSecurityCache();
            
            // Must be at the end, because it resets the current identity instance
            // Not necessary, called by loggedIn = false
            // _context.meta_logout(this);
        }
        
        
        private var _groupsCache:Object = new Object();
        
        /**
         * Check role permission for the specified role
         *  
         *  @param roleName role name
         *  @param resultHandler result handler
         *  @param faultHandler fault handler
         *  @return true is role allowed
         */ 
        [Bindable("groupChanged")]
        public function inGroup(groupName:String, resultHandler:Function = null, faultHandler:Function = null):Boolean {
            var has:* = _groupsCache[groupName];
            if (has === undefined) {
                if (loggedIn) {
                    var responder:TideGroupResponder = new TideGroupResponder(groupResultHandler, groupFaultHandler, groupName);
                    responder.addHandlers(resultHandler, faultHandler);
                    _context.meta_callComponent(this, "inGroup", [groupName, "ROLE", responder], false);
                    _groupsCache[groupName] = responder;
                }
                return false;
            }
            if (has is TideGroupResponder) {
            has.addHandlers(resultHandler, faultHandler);
            return false;
            }
            if (resultHandler != null) {
                var event:TideResultEvent = new TideResultEvent(TideResultEvent.RESULT, _context, false, false, null, has);
                resultHandler(event, groupName);
            }
            return (has as Boolean);
        }
        
        private function groupResultHandler(event:TideResultEvent, groupName:String):void {
            _groupsCache[groupName] = event.result as Boolean;
            dispatchEvent(new Event("groupChanged"));
        }
        
        private function groupFaultHandler(event:TideFaultEvent, groupName:String):void {
            delete _groupsCache[groupName];
        }
        
        
        private var _permissionsCache:Dictionary = new Dictionary(true);
        
        /**
         * Check permission for the specified target and action
         *  
         *  @param target target object
         *  @param action requested action
         *  @param resultHandler result handler
         *  @param faultHandler fault handler
         *  @return true is permission granted
         */ 
        [Bindable("permissionChanged")]
        public function hasPermission(target:Object, action:String, resultHandler:Function = null, faultHandler:Function = null):Boolean {
            var cache:Object = _permissionsCache[target];
            if (cache == null || (cache && cache[action] === undefined)) {
                if (loggedIn) {
                    var responder:TidePermissionResponder = new TidePermissionResponder(permissionResultHandler, permissionFaultHandler, target, action);
                    responder.addHandlers(resultHandler, faultHandler);
                    _context.meta_callComponent(this, "hasPermission", [target, action, responder], false);
                    if (cache == null) {
                        cache = new Object();
                        _permissionsCache[target] = cache;
                    }
                    cache[action] = responder;
                }
                return false;
            }
            if (cache[action] is TidePermissionResponder) {
                cache[action].addHandlers(resultHandler, faultHandler);
            return false;
            }
            
            if (resultHandler != null) {
                var event:TideResultEvent = new TideResultEvent(TideResultEvent.RESULT, _context, false, false, null, cache[action]);
                resultHandler(event, target, action);
            }
            return (cache[action] as Boolean);
        }
        
        private function permissionResultHandler(event:TideResultEvent, target:Object, action:String):void {
            _permissionsCache[target][action] = event.result as Boolean;
            dispatchEvent(new Event("permissionChanged"));
        }
        
        private function permissionFaultHandler(event:TideFaultEvent, target:Object, action:String):void {
            delete _permissionsCache[target];
        }
        
        
        private function initSecurityCache():void {
            dispatchEvent(new Event("groupChanged"));
            dispatchEvent(new Event("permissionChanged"));
        }
        
        /**
         * Clear the security cache
         */
        public function clearSecurityCache():void {
            _groupsCache = new Object();
            _permissionsCache = new Dictionary(true);
        }
    }
}


import flash.utils.Dictionary;
import org.granite.tide.ITideResponder;
import org.granite.tide.events.TideResultEvent;
import org.granite.tide.events.TideFaultEvent;


class TideGroupResponder implements ITideResponder {
    
    private var _resultHandlers:Array = new Array();
    private var _faultHandlers:Array = new Array();
    private var _groupName:String;
    
    
    public function TideGroupResponder(resultHandler:Function, faultHandler:Function, groupName:String):void {
        if (resultHandler != null)
            _resultHandlers.push(resultHandler);
        if (faultHandler != null)
            _faultHandlers.push(faultHandler);  
_groupName = groupName;
    }
    
    public function addHandlers(resultHandler:Function = null, faultHandler:Function = null):void {
        if (resultHandler != null)
            _resultHandlers.push(resultHandler);
        if (faultHandler != null)
            _faultHandlers.push(faultHandler);
    }
    
    
    public function result(event:TideResultEvent):void {
        for each (var resultHandler:Function in _resultHandlers) 
            resultHandler(event, _groupName);
    }
    
    public function fault(event:TideFaultEvent):void {
        for each (var faultHandler:Function in _faultHandlers)
            faultHandler(event, _groupName);
    } 
}


class TidePermissionResponder implements ITideResponder {
    
    private var _resultHandlers:Array = new Array();
    private var _faultHandlers:Array = new Array();
    private var _target:Object;
    private var _action:String;
    
    
    public function TidePermissionResponder(resultHandler:Function, faultHandler:Function, target:Object, action:String):void {
        if (resultHandler != null)
            _resultHandlers.push(resultHandler);
        if (faultHandler != null)
            _faultHandlers.push(faultHandler);
        _target = target;
        _action = action;
    }
    
    public function addHandlers(resultHandler:Function = null, faultHandler:Function = null):void {
        if (resultHandler != null)
            _resultHandlers.push(resultHandler);
        if (faultHandler != null)
            _faultHandlers.push(faultHandler);
    }
    
    
    public function result(event:TideResultEvent):void {
        for each (var resultHandler:Function in _resultHandlers) 
            resultHandler(event, _target, _action);
    }
    
    public function fault(event:TideFaultEvent):void {
        for each (var faultHandler:Function in _faultHandlers)
            faultHandler(event, _target, _action);
    } 
}

and

package org.jboss.seam.security {

    import flash.utils.flash_proxy;
    
    import mx.utils.object_proxy;
    
    import org.granite.tide.Component;
use namespace flash_proxy;
use namespace object_proxy;
    

    [Bindable]
    /**
     * Implementation of the identity component for Seam services.<br/>
     *  Integrates with the server-side identity component of Seam.<br/>
     *  <br/>
     *  The basic way of using it is by populating username/password and calling login :<br/>
     *  <pre>
     *  identity.username = 'john';
     *  identity.password = 'doe';
     *  identity.login();
     *  </pre>
     * 
     * @author William DRAI
     */
[RemoteClass(alias="org.jboss.seam.security.CredentialsImpl")]
    public class Credentials extends Component {
        
        /**
         * User name
         */
        public function get username():String {
            return super.getProperty("username") as String;
        }
        /**
         * User name
         */
        public function set username(username:String):void {
            super.setProperty("username", username);
        }
        
        /**
         * Password
         */
        public function set password(password:String):void {
            super.setProperty("password", password);
        }
public function meta_login(identity:Identity, resultHandler:Function, faultHandler:Function):void {
_context.meta_login(identity, username, super.getProperty("password"), resultHandler, faultHandler);
}
    }
}

Don't hesitate to send a pull request if you can make it work.
Reply all
Reply to author
Forward
0 new messages