Integrate Spring Security with Facebook Login

13,299

Solution 1

I don't think you should deal with Facebook manually. You can a really easy library: https://github.com/pac4j/spring-security-pac4j to authenticate for OAuth (Facebook, Twitter, Google...), CAS, SAML, OpenID (Connect) and GAE. See the demo: https://github.com/pac4j/spring-security-pac4j-demo

Solution 2

Daniel could you please elaborate where are you getting stuck. I used the same stack for integrating facebook login. But I did not use Spring Social. I believe it's not required.

Steps to integrate facebook login with the existing login.

  1. Use the facebook javascript plugin in your jsp for facebook login.
  2. Once the user approves your app. OAuth generates an auth token, using that fetch the email id of the client using graph API.
  3. Send the email id to the server using Ajax.
  4. Compare the email id sent to the server side with the email id in the database.
  5. If the email id is same login the user.

Authentication token is temporary so I find it pointless sending it to the server side or saving in db. It is saved locally on the client side. And the fb javascript plugin takes care of it. This way it saves you the hassle of implementing spring social facebook.

I see you are using the controller for facebook login, it's not required, trust me using the fb javascript plugin is really simple & easy.

Share:
13,299
Daniel Robertus
Author by

Daniel Robertus

Updated on June 04, 2022

Comments

  • Daniel Robertus
    Daniel Robertus almost 2 years

    I use Spring MVC and Spring Security for my project.. This using my own user data for authentication. But now i trying to integrate with Facebook. i have created app on Facebook means i got Client ID and client Secret.. I also read some questions in SO and some documents but still stuck...

    i create controller to Login with Facebook :

    import java.util.List;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("/login/")
    public class LoginController {
    
        String fb_app_id="my_client_id";
        String redirect_url="localhost:8888";
        String state="public_profile,email,user_friends";
        String key="my_client_secret";
    
        @RequestMapping("/facebook")
        public String login( ModelMap model) {
    
            String url="https://www.facebook.com/dialog/oauth/?"
                       + "client_id=" + fb_app_id
                       + "&redirect_uri=" + redirect_url
                       + "&scope=email,publish_stream,user_about_me,friends_about_me"
                       + "&state=" + key
                       + "&display=page"
                       + "&response_type=code";
            return "redirect:"+url;
    
        }
    
    }
    

    i think it works because when i try to connect, i can show my name with Javascript below:

    function testAPI() {
      console.log('Welcome!  Fetching your information.... ');
      FB.api('/me', function(response) {
        console.log('Good to see you, ' + response.name + '.');
        document.getElementById('status').innerHTML = 'Good to see you, ' +
          response.name;
      });
    }
    

    But i still confuse how to integrate it with Spring Security. If anyone have any examples i will appreciate...

    This is my spring-security.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
               http://www.springframework.org/schema/security
               http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    
        <http pattern="/common/*" security="none" />
    
        <http auto-config="true">
            <intercept-url pattern="/maintenance/*" access="ROLE_USER" />
            <intercept-url pattern="/_ah/*" access="ROLE_USER" />
            <intercept-url pattern="/predict/*" access="ROLE_USER" />
    
            <form-login login-page='/' default-target-url='/predict/list'
                login-processing-url="/login_check" authentication-failure-url="/index?login_error=2"
                always-use-default-target="true" />
            <logout logout-url="/logout" logout-success-url="/index" />
        <!--    <custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" /> -->
        <!--    <custom-filter before="FORM_LOGIN_FILTER"
                ref="facebookAuthenticationFilter" /> -->
        </http>
    
        <authentication-manager>
            <authentication-provider ref="gaeAuthenticationProvider" />
        <!--    <authentication-provider ref="authenticationProviderFacebook"> 
            </authentication-provider>-->
        </authentication-manager>
    
        <beans:bean id="gaeAuthenticationProvider"
            class="com.games.predictor.security.AuthenticationProvider" />
    
    </beans:beans>  
    

    i have my own class to Authenticate to userdata with JPA...

    package com.games.predictor.security;
    
    import java.util.List;
    
    import org.springframework.security.authentication.BadCredentialsException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    
    import com.games.predictor.UserDAO;
    
    
    public class AuthenticationProvider extends AbstractUserDetailsAuthenticationProvider
    {
        //private SecurityDao securityDao; 
    
        @Override
        protected UserDetails retrieveUser(String username,
                UsernamePasswordAuthenticationToken authentication)
                throws AuthenticationException
        {
            final String password = authentication.getCredentials().toString();
            System.out.println(username+"===="+password);
            //This line for validating user with database
            boolean isValidUser = UserDAO.INSTANCE.isValidUser(username, password);
            if (isValidUser)
            {
                final List<SimpleGrantedAuthority> authorities = UserDAO.INSTANCE.getAuthoritiesByUser(username);
                //User u=new User(username,password,);
                return new User(username, password, true, true, true, true, authorities);
            }
            else
            {
                authentication.setAuthenticated(false);
                throw new BadCredentialsException("Username/Password does not match for " 
                    + authentication.getPrincipal());
            }
    
        }
    
        @Override
        protected void additionalAuthenticationChecks(UserDetails arg0,
                UsernamePasswordAuthenticationToken arg1)
                throws AuthenticationException {
            // TODO Auto-generated method stub
    
        }
    }
    

    I did some research in last few days but still stuck.

    My Project Stack : Java, Spring MVC, Spring Security, Google App Engine, Google Data Store, JPA. (Spring Social Core and Spring Social Facebook Added)

  • Daniel Robertus
    Daniel Robertus almost 10 years
    Hi, Thanks for your answer.. My problem is when integrating Facebook Login with Spring Security Session. I see some people use it with spring social and spring security. But i have problem when trying implementing one of that sample.
  • 2low.samurai
    2low.samurai over 9 years
    Underdog misses this-you should not fetch email id of the client that was generated on the client side, because that could be easily modified by some other email and thus person that should not have entrance can get entrance. Once auth user token is returned, you should send that token to the server side, where you need to check that this token is still the token that was generated , as recomended by facebook here developers.facebook.com/docs/facebook-login/login-flow-for-w‌​eb/… . Once you confirm this, you can login this facebook user as one of your user it the user exists.