How can I check Spring Security for user authentication and get roles from Flex?

17,325

Solution 1

If you use Spring Blazeds integration , you can implement getUserDetails method using org.springframework.flex.security.AuthenticationResultUtils.

public Map<String, Object> getUserDetails() {  
 return AuthenticationResultUtils.getAuthenticationResult();
}

Solution 2

I would write a secured Spring service method that returns the current user's roles information. Let the Flex app invoke that when the application starts up. If you receive a FaultEvent due to a security error, then prompt the user to authenticate and use ChannelSet.login().

Share:
17,325
Buns of Aluminum
Author by

Buns of Aluminum

I'm a Senior Software Engineer with Unanet A/E in Forest, VA. I'm married and have four sons. I love writing apps for the web and mobile!

Updated on June 04, 2022

Comments

  • Buns of Aluminum
    Buns of Aluminum almost 2 years

    I'm using Spring, Spring Security, BlazeDS, Flex and spring-flex.

    I know that I can call channelSet.login() and channelSet.logout() to hook into Spring Security for authentication. channelSet.authenticated apparently only knows about the current Flex session, as it always starts off as false, until you call channelSet.login().

    What I want to do:

    1. Check from Flex to know if a user is already in a session.
    2. If so, I want their username and roles.

    UPDATE
    I just thought I'd add details of the solution I used from brd6644's answer below, so that this might be easier for someone else who looks this up. I used this StackOverflow answer to make the SecurityContext injectable. I won't be rewriting the code from that answer in this one, so go look at it for the SecurityContextFacade.

    securityServiceImpl.java

    public class SecurityServiceImpl implements SecurityService {
        private SecurityContextFacade securityContextFacade;
    
        @Secured({"ROLE_PEON"})
        public Map<String, Object> getUserDetails() {
            Map<String,Object> userSessionDetails = new HashMap<String, Object>();
    
            SecurityContext context = securityContextFacade.getContext();
            Authentication auth = context.getAuthentication();
            UserDetails userDetails = (UserDetails) auth.getPrincipal();
    
            ArrayList roles = new ArrayList();
            GrantedAuthority[] grantedRoles = userDetails.getAuthorities();
            for (int i = 0; i < grantedRoles.length; i++) {
                roles.add(grantedRoles[i].getAuthority());
            }
    
            userSessionDetails.put("username", userDetails.getUsername());
            userSessionDetails.put("roles", roles);
            return userSessionDetails;
        }
    }
    


    securityContext.xml

    <security:http auto-config="true">
        <!-- Don't authenticate Flex app -->
        <security:intercept-url pattern="/flexAppDir/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <!-- Don't authenticate remote calls -->
        <security:intercept-url pattern="/messagebroker/amfsecure" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    </security:http>
    
    <security:global-method-security secured-annotations="enabled" />
    
    <bean id="securityService" class="ext.domain.project.service.SecurityServiceImpl">
        <property name="securityContextFacade" ref="securityContextFacade" />
    </bean>
    <bean id="securityContextFacade" class="ext.domain.spring.security.SecurityContextHolderFacade" />
    


    flexContext.xml

    <flex:message-broker>
        <flex:secured />
    </flex:message-broker>
    
    <flex:remoting-destination ref="securityService" />
    <security:http auto-config="true" session-fixation-protection="none"/>
    


    FlexSecurityTest.mxml

    <mx:Application ... creationComplete="init()">
    
        <mx:Script><![CDATA[
            [Bindable]
            private var userDetails:UserDetails; // custom VO to hold user details
    
            private function init():void {
                security.getUserDetails();
            }
    
            private function showFault(e:FaultEvent):void {
                if (e.fault.faultCode == "Client.Authorization") {
                    Alert.show("You need to log in.");
                    // show the login form
                } else {
                    // submit a ticket
                }
            }
            private function showResult(e:ResultEvent):void {
                userDetails = new UserDetails();
                userDetails.username = e.result.username;
                userDetails.roles = e.result.roles;
                // show user the application
            }
        ]]></mx:Script>
    
        <mx:RemoteObject id="security" destination="securityService">
            <mx:method name="getUserDetails" fault="showFault(event)" result="showResult(event)" />
        </mx:RemoteObject>
    
        ...
    </mx:Application>
    
  • Buns of Aluminum
    Buns of Aluminum almost 15 years
    The people commenting on his blog posts seem to be having the same problems that I was; mainly that logging in and out was easy from Flex, but noticing an existing session wasn't. brd6644's solution worked perfectly for this.
  • JARC
    JARC almost 15 years
    Nice idea, will def try this.
  • Buns of Aluminum
    Buns of Aluminum almost 14 years
    This was MUCH better than what I had going on. It worked very well and saved a lot of code.