Announcement Announcement Module
Collapse
No announcement yet.
If our authenticated User is in stored in Session - (and quest in Showcase.) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • If our authenticated User is in stored in Session - (and quest in Showcase.)

    Although I want to take advantage of using Spring Security at some point, we can only refactor so much of our existing application at this point, and I'm working on understanding Spring Social Showcase so I could leverage Spring Social.

    I was stumped for a while on how, within Spring Social Showcase, the "facebook connect" part was working - Couldn't figure out how the ConnectionController was getting access to the logged-in user (userId.) If I'm understanding correctly it's related to the setup in SocialConfig where ConnectController is created from connectionFactoryLocator, connectionRepository so that the connectionRepository is created from the current logged in user of the Request. I'll try to research more on how Spring works there (I'm still somewhat green with Spring) but I thought the default Bean definition was "singleton" so I'm curious how, on different requests from different users using the Spring Social application, the bean ConnectController would end up with the appropriate user connectionRepository - I would have figured just one instance of ConnectionController would exist for the showcase as a singleton? I'm guessing it has something to do with the value="request", proxyMode=ScopedProxyMode.INTERFACES defined for the connectionRepository?)

    My main questions is, since I'm not using a SecurityContextHolder to hold my authentication information, how should I get a handle to the HttpSession in my version of SocialConfig, so that I could pull the user out and be able to use the standard ConnectController when it's created from a ConnectionRepository instance:

    Code:
    @Bean
    @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)	
    public ConnectionRepository connectionRepository() {
        //HttpSession even possible here ?????
        User user = (User)session.getAttribute("user");
        return usersConnectionRepository().createConnectionRepository(user.getUserId()));
    }
    Is there some other way I should handle this if (at least for now) the HttpSession is holding our authenticated User? I could of course create my own ConnectController and pull what I need out in there, but since ConnectionController is part of the core spring social library I figured I should try to leverage it 'as is' first if possible?

    Thanks for any help

  • #2
    What about this idea...

    I create a simple SecurityContext object like the spring-social-quickstart object has. In our custom Authentication filter we are already pulling out the User from the HttpSession on every request to see if it exists... I could set the user on the SecurityContext ThreadLocal at this time? and then have access to it in my connectionRespository() call in my SocialConfig via the SecurityContext object. I think this would work but it seems sort of like a hack and I'm probably missing something very simple.

    Comment


    • #3
      Accessing authenticated user context via a ThreadLocal is a common pattern. Spring Security does this, as does the little example in Spring Social Quickstart. Are you running in a Spring MVC environment? If so, you can also call RequestContextHolder.requestAttributes() to get at a RequestAttributes object that provides access to Http Session attributes. You could also try injecting the HttpServletRequest directly with the @Value tag on a method parameter of a "request" @Scope(ed) bean e.g. @Value("#{request}"). I'd look at the Spring Framework docs for request scope beans for more info on that.

      Keith

      Comment


      • #4
        Thanks Keith!

        Looks like I can leverage all three since it will be in Spring MVC environment (it currently is in one using Spring 3.0.3 - but I plan to try and upgrade things at some point to Spring 3.1 - assuming there aren't a lot of backwards compatibility issues.)

        I only meant at first that the ThreadLocal seemed like hack since I was just using it as a temporary holder for lack of me understanding how to get access to the HttpSession... but the more I think about, I like it overall, since it makes things like Unit testing easier not having to deal with an HttpSession in certain classes. (Plus once we move to Spring Security it moves me closer to the pattern used there.)

        Comment


        • #5
          Hello,

          Picking up on this older thread as I could not find another that is more suitable...

          I need to implement a feature where a (potential) new customer can sign up for a new account on my site with the customer's existing Facebook account. The flow would be something like this:

          1. Existing Facebook user visits my site for the first time
          2. He/she decides to create an account on my site by clicking on the "Create account with my Facebook login" button
          3. The page POSTs to the ConnectController, and successfully retrieves an OAuth2 access token

          After step 3 is where my code crashes. I am using:

          Spring 3.2.1.RELEASE
          Spring Security 3.1.3.RELEASE
          Spring Social 1.1.0.M2

          I have configured the ConnectionRepository like so:

          Code:
          	<bean id="connectionRepository" factory-method="createConnectionRepository" 
          	      factory-bean="usersConnectionRepository" scope="request" lazy-init="true">
          	    <constructor-arg value="#{request.userPrincipal.name}" />
          	    <aop:scoped-proxy proxy-target-class="false" />
          	</bean>
          The error occurred at the point where the "userPrincipal" is anonymous, and do not have a "name" property as the customer has not yet created an account/signed in.

          Does Spring Social have a best practice regarding this usage scenario?

          Thanks in advance!

          -Frank

          Comment


          • #6
            It sounds like you're wanting to use ProviderSignInController, not ConnectController.

            ConnectController's job is to establish a connection between an existing user and their remote profile. If there's not an existing user, ConnectController can't do its job.

            ProviderSignInController's job is to sign in a user based on their remote profile. If the user is an existing user and a connection has previously been established, then it signs them in. But if there is not existing connection, then it goes to an application-defined signup/registration page and some of the user's remote profile data is available to populate the registration form. After registration is complete, your app can then use ProviderSignInUtils to complete the connection with the new user. The Spring Social Showcase example shows how this works.

            The only drawback to this is that there may be data in the user's remote profile you want to capture at registration time that isn't available from ProviderSignInController. Let's say you want to capture the user's birthday as part of the registration. Although that's part of the user's Facebook profile, it's not available in the UserProfile you can fetch from the Connection (which you can get from ProviderSignInUtils...see the SignupController.java in the example to see this in action). In that case, you can still use the Connection to obtain the API binding and from that fetch pretty much anything you want (and have been granted scope for).

            Another approach that's interesting, but very Facebook-specific is to use Facebook's registration plugin (https://developers.facebook.com/docs.../registration/). This puts a Facebook-populated registration form on your page and the user submits their registration to Facebook. Facebook will then call back to your app with a signed request containing the registration data. You just need something on your end to receive that signed request and to decode it. Currently, Spring Social doesn't support FB's registration dialog, but it's the subject of https://jira.springsource.org/browse/SOCIALFB-7 and I'm thinking of getting it into the 1.1.0 release.

            Comment


            • #7
              Thank you very much, Craig! This is extremely helpful.

              BTW, I enjoyed your Spring Social talk at Spring One last year. Thanks for all of the hard work to make it easier for the rest of us!

              -Frank

              Comment


              • #8
                Hi Craig,

                Is there a chance that methods in ProviderSignInUtils can be overloaded with non-Spring arguments? E.g.:

                Code:
                public static Connection<?> getConnection(HttpServletRequest request)
                
                public static void handlePostSignUp(String userId, HttpServletRequest request)
                This will make integration easier with existing frameworks not using Spring.

                Thanks!

                -Frank

                Comment


                • #9
                  Excellent point and something worth looking into.

                  That said, can you describe how you might use this outside of Spring? I can certainly see opportunity to use it outside of Spring MVC, but wouldn't you still want Spring around for other stuff?

                  Comment


                  • #10
                    Spring MVC reference in non-Spring MVC code

                    Hi Craig,

                    Sure thing. I am tasked with integrating social networking into our existing site. Our legacy code uses a different MVC framework, with Spring MVC introduced only recently along with Spring Social. In lieu of a complete rewrite and code migration into Spring MVC, the new social code must play nice with the existing legacy framework.

                    I am using Spring Social to establish the Connections, and making them available in the existing (non-Spring) controllers for use. The only Social imports within the old framework are Connection, UserProfile and ProviderSignInUtils, with ProviderSignInUtils forcing a reference to Spring MVC.

                    It's not that big of a deal, and I have created a wrapper around ProviderSignInUtils to change the API to use the Servlet API classes, but thought it would be cleaner if Spring Social offered the alternatives.

                    Thanks,

                    -Frank

                    Comment

                    Working...
                    X