Announcement Announcement Module
Collapse
No announcement yet.
Question about anonymousUser authentication Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Question about anonymousUser authentication

    Hi,

    When I authenticate through Twitter in SocialConfig
    PHP Code:
    public ConnectionRepository connectionRepository() {
            
    Authentication authentication SecurityContextHolder.getContext()
                    .
    getAuthentication();
            if (
    authentication == null) {
                throw new 
    IllegalStateException(
                        
    "Unable to get a ConnectionRepository: no user signed in");
            }
            
            return 
    usersConnectionRepository().createConnectionRepository(
                    
    authentication.getName());
        } 
    athentication.getName() returns "anonymousUser". I would have expected the username as per the documentation to be something like twitter123989857:

    "Each connection is uniquely identified by a composite key consisting of a providerId (e.g. 'facebook') and connected providerUserId (e.g. '1255689239'"

    Creating a connectionRepository based on "anonymousUser doesn't seem to make sense. Can someone enlighten me?

    Kind regards,

    Marc

  • #2
    It appears you're using Spring Security to authenticate a local user identity. Spring Security has an optional "anonymous filter" that will authenticate each request as originated from a "anonymous user" if it hasn't been otherwise authenticated. I'm not sure if this is what you want or not. You might want to check your Spring Security configuration and review the Spring Security documentation. My advice would be sure to understand the big picture of how you would like user authentication and authorization to work in your application (where Spring Social plays a part in that, as the handler for social integrations).

    Keith

    Comment


    • #3
      Yeah, thanks for the quick feedback. I will see if I can remove that. I don't think I really need the anonymous user. I do feel that given how close Spring Security and Social are, Social should prevent these anonymous requests from coming in. Because every authentication object is considered "connectionRepository-worthy" and returning a null connectionRepository object is not possible, it's not directly obvious (to me) how to avoid this issue if you do need to use the anonymous user.

      Comment


      • #4
        Hmm, seems I do need it. Any obvious way around this?

        Comment


        • #5
          Well, a ConnectionRepository should generally only be obtained in a request where an actual user has been authenticated. I wouldn't expect it to be obtained in the context of an anonymous user request. In fact, I would suggest that your @Bean method should also throw an IllegalStateException in that case.

          I find it difficult to support you without looking at some real code that demonstrates your issue and the context around it. I find github works really well for such collaboration. You could create a scaled down project on github showing your issue and point folks to it. Then it's a lot easier to make some concrete suggestions rather than speculations.

          Keith
          Last edited by Keith Donald; Jul 13th, 2011, 12:29 PM.

          Comment


          • #6
            ok

            Well, my Github skills are not all that great, so I'll try to give it a go here if that's ok:

            So I think that I may be misunderstanding.

            I think the basic problem is that I do have a default anonymous role

            PHP Code:
            <http entry-point-ref="myAuthenticationProcessingFilterEntryPoint" >
            <
            anonymous granted-authority="ROLE_ANONYMOUS" />
            </
            http
            My SocialConfig is set up like so
            PHP Code:
            @Configuration
            public class SocialConfig {

                @
            Resource(name="socialProperties")
                private 
            Map<StringMap<StringUserAccount>> environment;

                @
            Autowired
                
            private SocialUserDao jpaTemplate;

                @
            Bean
                
            @Scope(value="singleton"proxyMode=ScopedProxyMode.INTERFACES
                public 
            ConnectionFactoryLocator connectionFactoryLocator() {
                    
            ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
                    
            registry.addConnectionFactory(new FacebookConnectionFactory(
                            
            environment.get("myapp").get("facebook").getUserId(),
                            
            environment.get("myapp").get("facebook").getPassword()));
                        
            registry.addConnectionFactory(new TwitterConnectionFactory(
                            
            environment.get("myapp").get("twitter").getUserId(),
                            
            environment.get("myapp").get("twitter").getPassword()));
                    return 
            registry;
                }

                @
            Bean
                
            @Scope(value "singleton"proxyMode ScopedProxyMode.INTERFACES)
                public 
            UsersConnectionRepository usersConnectionRepository() {
                    return new 
            JPAUsersConnectionRepository(jpaTemplate,
                            
            connectionFactoryLocator(), Encryptors.noOpText());
                }

                @
            Bean
                
            @Scope(value "request"proxyMode ScopedProxyMode.INTERFACES)
                public 
            ConnectionRepository connectionRepository() {
                    
            Authentication authentication SecurityContextHolder.getContext()
                            .
            getAuthentication();
                    if (
            authentication == null || !(authentication.getPrincipal() instanceof User)) {
                        throw new 
            IllegalStateException(
                                
            "Unable to get a ConnectionRepository: no user signed in");
                    }
                    
            String id=((Userauthentication.getPrincipal()).getId().toString();

                    return 
            usersConnectionRepository().createConnectionRepository(
                            
            id);
                }

                @
            Bean
                
            @Scope(value "request"proxyMode ScopedProxyMode.INTERFACES)
                public 
            Facebook facebook() {
                    
            Connection<Facebookfacebook connectionRepository()
                            .
            findPrimaryConnection(Facebook.class);
                    return 
            facebook != null facebook.getApi() : new FacebookTemplate();
                }

                @
            Bean
                
            @Scope(value "request"proxyMode ScopedProxyMode.INTERFACES)
                public 
            Twitter twitter() {
                    
            Connection<Twittertwitter connectionRepository()
                            .
            findPrimaryConnection(Twitter.class);
                    return 
            twitter != null twitter.getApi() : new TwitterTemplate();
                }

                @
            Bean
                
            public ConnectController connectController() {
                    
            ConnectController connectController = new ConnectController(
                            
            connectionFactoryLocator(), connectionRepository());
                    return 
            connectController;
                }

                @
            Bean
                
            public ProviderSignInController providerSignInController() {
                    return new 
            ProviderSignInController(connectionFactoryLocator(),
                            
            usersConnectionRepository(), new SimpleSigninAdapter());
                } 
            What seems to be happening is that because of the anonymous principal being passed, public ConnectionRepository connectionRepository() will get called on SocialConfig from

            /connect/twitter

            at

            PHP Code:

            @RequestMapping(value="/{providerId}", method=RequestMethod.GET)
                public String connectionStatus(@PathVariable String providerId, WebRequest request, Model model) {
                    processFlash(request, model);
                    List<Connection<?>> connections = connectionRepository.findConnections(providerId);
            Because there is an anonymous principal: anonymousUser it will try to create a connectionRepository for this user, which I don't want since he is anonymous.

            However, the anonymous principal also seems to be there when I turn the

            <anonymous granted-authority="ROLE_ANONYMOUS" />

            off in security.xml

            So, I guess I don't understand why a connectionRepository is created for an anonymous user. If there shouldn't be a connectionRepository created for an anonymous user, then the question is: how do I filter out anonymousUsers from becoming connectionRepository candidates because they are anonymous principals.

            Kind regards,

            Marc

            Comment


            • #7
              Ok, I have looked at turning anonymous granted-authority off (it's turned on by default). Unfortunately, some key filters in my app depend on the securityFilterChain, so setting filters to "none" doesn't work for me. I do need the anonymous principal. How to deal with the anonymous principal within Spring Social?

              Comment


              • #8
                I would expect your /connect/twitter URL to be a secure URL ... how can you initiate a connect flow if no user has authenticated? The point I'm trying to make is I do not expect a connectionRepository to be used in an anonymous context.

                Comment


                • #9
                  Ok, point taken. This is my novelty to the library that is getting me. Thanks for clearing that up.

                  So, what you are saying is that including the situation where you post to /connect/twitter in order to connect, I need to create a new user for the "to be authenticated" twitter user to be linked to.

                  Ok, my (mis-)understanding was that this new local user would be created on the fly after the twitter authentication completes.

                  Comment


                  • #10
                    Actually, I'm still a little confused. For me, the main object is to allow an anonymous user who may or may not have an account on my site, to login to my site. The primary identifier for a user on my platform is an email address.

                    I thought the connection flow was like this:
                    1. Access a page with login protection
                    2. Click the login with twitter
                    3. Go to Twitter page and login
                    4. Return to site with a registered Twitter user
                    4A. The user does not have a local account with the email of the Twitter user
                    Create new account based on Twitter data (email, nickname etc)
                    Access login protected page
                    4B. The user does have an account with the email of the Twitter user
                    Load local account
                    Access login protected page

                    I'm not sure how to achieve this now. If I need to create a user before redirecting to the Twitter/Facebook site, that user is basically "illegal" for me because there is no uniquely identifying information and there is no guarantee that the user will complete the login flow.
                    Asking for an email before connection is not option. The whole point for me is to allow easy access, huffingtonpost.com style.
                    Any suggestions?

                    Comment


                    • #11
                      The flow you just described is a provider /signin flow, not a /connect flow. Please see all the samples and reference documentation that illustrate and describe provider sign-in. With a provider sign-in attempt, the connection repository is not resolved until a local user account is created. /connect flow usage is for managing connections when updating user settings, and its expected a local user is authenticated.

                      Next time make sure to state what you're trying to do first

                      Keith

                      Comment


                      • #12
                        Hi Keith, yeah I just realized that. I did read all the docs and reviewed the samples. To my defense, the reference docs focus exclusively on the connect controller, which is how I got lost. I didn't realize there was a difference until just now. For now, I'm happy I finally got it. Thanks. I'll be posting a jpaTemplate as soon as I verify it works.

                        Comment


                        • #13
                          There is a whole chapter dedicated to Provider Sign In. Is it not featured prominently enough? Looking forward to seeing the JPA-based ConnectionRepository.

                          Comment


                          • #14
                            I must be blind. I stopped reading at "connecting to service providers". For me that's what is, it;s all connecting to service providers. But it prob is just me.

                            Comment

                            Working...
                            X