Adding Social Sign In to a Spring MVC Web Application: Configuration

In the good old days users logged in by using the combination of username and password. Although nowadays some people still prefer the traditional way, a growing number of users want to sign in by using their social media accounts.

This is a what makes Spring Social (and its sub projects) an useful addition to the Spring project portfolio. However, integrating Spring Social with Spring Security has been a bit cumbersome.

Spring Social 1.1.0 changes all this. It provides seamless integration with Spring Security, and the Java configuration support of Spring Security makes the configuration feel like a walk in the park.

You don't have to take my word for it. Keep on reading and you will learn how this is done.

The requirements of our solution are the following:

  • It must be possible to create an user account by using a normal registration form.
  • It must be possible to create an user account by using a social sign in.
  • It must be possible to login by using username and password.
  • It must be possible to login by using a SaaS API provider.
  • The application must support Facebook and Twitter.
  • The application must use "regular" Spring MVC controllers (no REST).

Let's start by taking a look at the prerequisites of this tutorial.

Prerequisites

This tutorial assumes that you have already created the Facebook and Twitter application used by the example application. You can create these applications by following these links:

If you don't know how to do this, you can check out the following links:

Let’s move on and find out how we can get the required dependencies with Maven.

Getting the Required Dependencies with Maven

The first thing that we have to do is to get the required dependencies with Maven. We can do this by declaring the following dependencies in our POM file:

  • Spring Security (version 3.2.0.RELEASE).
    • The core module contains core authentication and and access control components.
    • The config module contains the code used to parse XML configuration files using the Spring Security XML namespace.
    • The taglibs module contains the Spring Security JPS tag libraries.
    • The web module contains filters and all other code related to web security.
  • Apache HttpClient (version 4.3.2). Apache HttpClient is an optional dependency (but recommended) dependency of Spring Social. If it is present, Spring Social will use it as a HTTP client. If not, Spring social will use the standard Java SE components.
  • Spring Social (version 1.1.0.RELEASE).
    • The config module contains the code used to parse XML configuration files using the Spring Social XML namespace. It also adds support for Java Configuration of Spring Social.
    • The core module contains the connect framework and provides support for OAuth clients.
    • The security module integrates Spring Security with Spring Social. It delegates the authentication concerns typically taken care by Spring Security to service providers by using Spring Social.
    • The web module contains components which handle the authentication handshake between our web application and the service provider.
  • Spring Social Facebook (version 1.1.0.RELEASE) is an extension to Spring Social and it provides Facebook integration.
  • Spring Social Twitter (version 1.1.0.RELEASE) is an extension to Social Social which provides Twitter integration.

The relevant part of the pom.xml file looks as follows:

<!-- Spring Security -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-core</artifactId>
	<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-config</artifactId>
	<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-taglibs</artifactId>
	<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-web</artifactId>
	<version>3.2.0.RELEASE</version>
</dependency>

<!-- Use Apache HttpClient as HTTP Client -->
<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.3.2</version>
</dependency>

<!-- Spring Social -->
<dependency>
	<groupId>org.springframework.social</groupId>
	<artifactId>spring-social-config</artifactId>
	<version>1.1.0.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.social</groupId>
	<artifactId>spring-social-core</artifactId>
	<version>1.1.0.RELEASE</version>
</dependency>
<dependency>     
	<groupId>org.springframework.social</groupId>
	<artifactId>spring-social-security</artifactId>
	<version>1.1.0.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.social</groupId>
	<artifactId>spring-social-web</artifactId>
	<version>1.1.0.RELEASE</version>
</dependency>
 
<!-- Spring Social Facebook -->
<dependency>
	<groupId>org.springframework.social</groupId>
	<artifactId>spring-social-facebook</artifactId>
	<version>1.1.0.RELEASE</version>
</dependency>
 
<!-- Spring Social Twitter -->
<dependency>
	<groupId>org.springframework.social</groupId>
	<artifactId>spring-social-twitter</artifactId>
	<version>1.1.0.RELEASE</version>
</dependency>
Our application has other dependencies as well. For example, it uses Spring Framework 4.0.0.RELEASE, Spring Data JPA 1.4.3, and Hibernate 4.2.4.Final. These dependencies are left out from the dependency listing for the sake of clarity. You can get the full list of dependencies from Github.

You might also want to read the following documents which give you more information about the dependencies of the frameworks discussed in this blog post (Spring Security and Spring Social):

Next we have to create a properties file for the configuration properties of our application. Let’s find out how this is done.

Creating the Properties File

We can create the properties file by following these steps:

  1. Create a file called application.properties and ensure that it is found from the classpath.
  2. Configure the database connection.
  3. Configure Hibernate.
  4. Add the Facebook application id and application secret to the properties file.
  5. Add the Twitter consumer key and consumer secret to the properties file.

The contents of the application.properties file looks as follows:

#Database Configuration
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/socialtwitter
db.username=socialtwitter
db.password=password

#Hibernate Configuration
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.format_sql=true
hibernate.hbm2ddl.auto=validate
hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
hibernate.show_sql=false

#Facebook
facebook.app.id=foo
facebook.app.secret=bar

#Twitter
twitter.consumer.key=foo
twitter.consumer.secret=bar

Before we can configure our application, we have to create a few common components. Let's find out what these components are, and how we can create them.

Creating the Common Components

We have to create three components which are used during the authentication process. These components are:

  • We have create a class which contains the user details of an authenticated user.
  • We have to create a class which implements the UserDetailsService interface. This class is used to load user information when the user uses form login.
  • We have to create a class which implements the SocialUserDetailsService interface. This class is used to load user information when the user uses social sign in.

Let’s move on and find out how we can implement these classes.

Creating the User Details Class

We have to take the following requirements into account when we are creating the class which contains the user details of the authenticated user:

  • The class which stores the user details of a user who uses form login must implement the UserDetails interface.
  • The class which stores the user details of a user who uses social sign in must implement the SocialUserDetails interface.

Spring Social has a SocialUser class which fulfils both of these requirements. However, often we want to add application specific information to our user details class.

We can do this by following these steps:

  1. Create the user details class.
  2. Extend the SocialUser class.
  3. Add application specific fields to the created class. The application specific fields of our example application are: id, firstName, lastName, role, and socialSignInProvider.
  4. Create a constructor which takes the username, password and a collection of granted authorities as parameters. Pass these parameters forward to the constructor of the SocialUser class.
  5. Create getters for application specific fields.
  6. Add an inner builder class which is used to build new ExampleUserDetails objects.

The source code of our user details class looks as follows:

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.social.security.SocialUser;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class ExampleUserDetails extends SocialUser {

    private Long id;

    private String firstName;

    private String lastName;

    private Role role;

    private SocialMediaService socialSignInProvider;

    public ExampleUserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        super(username, password, authorities);
    }

	//Getters are omitted for the sake of clarity.

    public static class Builder {

        private Long id;

        private String username;

        private String firstName;

        private String lastName;

        private String password;

        private Role role;

        private SocialMediaService socialSignInProvider;

        private Set<GrantedAuthority> authorities;

        public Builder() {
            this.authorities = new HashSet<>();
        }

        public Builder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public Builder id(Long id) {
            this.id = id;
            return this;
        }

        public Builder lastName(String lastName) {
            this.lastName = lastName;
            return this;
        }

        public Builder password(String password) {
            if (password == null) {
                password = "SocialUser";
            }

            this.password = password;
            return this;
        }

        public Builder role(Role role) {
            this.role = role;

            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.toString());
            this.authorities.add(authority);

            return this;
        }

        public Builder socialSignInProvider(SocialMediaService socialSignInProvider) {
            this.socialSignInProvider = socialSignInProvider;
            return this;
        }

        public Builder username(String username) {
            this.username = username;
            return this;
        }

        public ExampleUserDetails build() {
            ExampleUserDetails user = new ExampleUserDetails(username, password, authorities);

            user.id = id;
            user.firstName = firstName;
            user.lastName = lastName;
            user.role = role;
            user.socialSignInProvider = socialSignInProvider;

            return user;
        }
    }
}

The Role is a simple enum which specifies the "legal" user roles of our example application. Its source code looks as follows:

public enum Role {
    ROLE_USER
}

The SocialMediaService is an enum which identifies the SaaS API provider which was used when user created an user account to our example application. Its source code looks as follows:

public enum SocialMediaService {
    FACEBOOK,
    TWITTER
}

Implementing the UserDetailsService interface

We can create our own implementation of the UserDetailsService interface by following these steps:

  1. Create a class which implements the UserDetailsService interface.
  2. Add a UserRepository field to created class.
  3. Create a constructor which takes a UserRepository as a constructor argument and annotate the constructor with the @Autowired annotation.
  4. Implement the loadUserByUsername(String username) method of the UserDetailsService interface. The implementation of this method consists of following steps:
    1. Get the user by calling the findByEmail() method of the UserRepository interface. This method returns the user whose email matches with the username given as a method parameter.
    2. If the user is not found, throw a new UsernameNotFoundException.
    3. Create a new ExampleUserDetails object.
    4. Return the created object.

The source code of the RepositoryUserDetailsService class looks as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class RepositoryUserDetailsService implements UserDetailsService {

    private UserRepository repository;

    @Autowired
    public RepositoryUserDetailsService(UserRepository repository) {
        this.repository = repository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = repository.findByEmail(username);

        if (user == null) {
            throw new UsernameNotFoundException("No user found with username: " + username);
        }

        ExampleUserDetails principal = ExampleUserDetails.getBuilder()
                .firstName(user.getFirstName())
                .id(user.getId())
                .lastName(user.getLastName())
                .password(user.getPassword())
                .role(user.getRole())
                .socialSignInProvider(user.getSignInProvider())
                .username(user.getEmail())
                .build();

        return principal;
    }
}

The UserRepository is a simple Spring Data JPA repository, and its source code looks as follows:

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {

    public User findByEmail(String email);
}

The User is the only entity of our example application, and it contains the information of a user who has created user account to our example application. The relevant part of its source code looks as follows:

import javax.persistence.*;

@Entity
@Table(name = "user_accounts")
public class User extends BaseEntity<Long> {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "email", length = 100, nullable = false, unique = true)
    private String email;

    @Column(name = "first_name", length = 100,nullable = false)
    private String firstName;

    @Column(name = "last_name", length = 100, nullable = false)
    private String lastName;

    @Column(name = "password", length = 255)
    private String password;

    @Enumerated(EnumType.STRING)
    @Column(name = "role", length = 20, nullable = false)
    private Role role;

    @Enumerated(EnumType.STRING)
    @Column(name = "sign_in_provider", length = 20)
    private SocialMediaService signInProvider;

    public User() {

    }

	//Getters and other methods are omitted for the sake of clarity.
}

Implementing the SocialUserDetailsService interface

We can implement the SocialUserDetailsService interface by following these steps:

  1. Create a class which implements the SocialUserDetailsService.
  2. Add a UserDetailsService field to the created class.
  3. Create a constructor which takes a UserDetailsService object as a constructor parameter, and annotate the constructor with the @Autowired annotation.
  4. Implement the loadUserByUserId(String userId) method of the SocialUserDetailsInterface.
  5. Get the correct UserDetails object by calling the loadUserByUsername() method and pass the user id as a method parameter. We can do this because our application uses the username of the user as the user id.
  6. Cast the returned object to SocialUserDetails object and return it.

The source code of the SimpleSocialUserDetailsService class looks as follows:

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.social.security.SocialUser;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;


public class SimpleSocialUserDetailsService implements SocialUserDetailsService {

    private UserDetailsService userDetailsService;

    public SimpleSocialUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException, DataAccessException {
        UserDetails userDetails = userDetailsService.loadUserByUsername(userId);
        return (SocialUserDetails) userDetails;
    }
}

That is all. We are now ready to configure the application context of our application. Let's find out how we can do that.

Configuring the Application Context

This section describes how we can configure the application context of our example application by using Java configuration. The application context configuration has been divided into multiple configuration classes by following these guidelines:

  1. Each configuration class contains configuration which is associated with a specific part of our example application. This make it easy to find out the relevant configuration if we have to check something out or change something a few months (or years) after we created the initial configuration.
  2. The configuration has been divided in a way which makes it easy to write unit tests for the web layer by using Spring MVC Test. We will talk more about this in the third part of this tutorial where we will write unit tests for the web layer of our application.
  3. The configuration makes it easy remove dependencies to external resources when we are writing integration tests for our application. We will talk more about this in the fourth part of this tutorial which describes how we can write integration tests for our application.
If you want to use XML configuration, you can take look at the example application of this blog post which has a working XML configuration as well (no web.xml though).

Let's start by configuring the persistence layer of our application.

Configuring the Persistence Layer

The persistence layer of our application stores the user account information and provides a way to access this information. This important for two reasons:

  • We can provide a way to sign in by using username and password.
  • We can store application specific information and link this information to the user who uses social sign in.

Let's find out how we can configure it by using both Java configuration class.

The persistence layer of example application uses Spring Data JPA 1.3.4. I will keep this section as thin as possible. If you want to learn more about Spring Data JPA, you can read my Spring Data JPA tutorial. I have also written a book about Spring Data which should help you to get started in no time.

We can configure our persistence layer by following these steps:

  1. Create the configuration class and annotate the created class with the @Configuration annotation.
  2. Annotate the class with the @EnableJpaRepositories annotation and set the base package of our Spring Data JPA repositories.
  3. Enable the Spring transaction management by annotating the configuration class with the @EnableTransactionManagement annotation.
  4. Add an Environment field to the class and annotate the field with the @Autowired annotation. We don't need to configure the properties file by using the @PropertySource annotation because it is already configured in the "parent" application context configuration class.
  5. Configure the data source bean. This bean provides database connections to the entity manager but it has also another purpose. It is used by Spring Social when it persists connections to the database and loads them from the database.
  6. Configure the transaction manager bean.
  7. Configure the entity manager factory bean.

The source code of the PersistenceContext class looks as follows:

import com.jolbox.bonecp.BoneCPDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableJpaRepositories(basePackages = {
        "net.petrikainulainen.spring.social.signinmvc.user.repository"
})
@EnableTransactionManagement
public class PersistenceContext {

    @Resource
    private Environment env;

    @Bean
    public DataSource dataSource() {
        BoneCPDataSource dataSource = new BoneCPDataSource();

        dataSource.setDriverClass(env.getRequiredProperty("db.driver"));
        dataSource.setJdbcUrl(env.getRequiredProperty("db.url"));
        dataSource.setUsername(env.getRequiredProperty("db.username"));
        dataSource.setPassword(env.getRequiredProperty("db.password"));

        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactoryBean.setPackagesToScan({
	            "net.petrikainulainen.spring.social.signinmvc.common.model",
	            "net.petrikainulainen.spring.social.signinmvc.user.model"
	    });

        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
        jpaProperties.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
        jpaProperties.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto"));
        jpaProperties.put("hibernate.ejb.naming_strategy", env.getRequiredProperty("hibernate.ejb.naming_strategy"));
        jpaProperties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));

        entityManagerFactoryBean.setJpaProperties(jpaProperties);

        return entityManagerFactoryBean;
    }
}

Let's move on and find out how we can create the security configuration for our application.

Configuring Spring Security

Spring Security provides authentication mechanism for users who uses either form login or social sign in, and it is also responsible of authorization.

We can configure Spring Security by following these steps:

  1. Create the configuration class and annotate the created class with the @Configuration annotation.
  2. Annotate the class with the @EnableWebSecurity annotation. This makes it possible to configure Spring Security by implementing the WebSecurityConfigurer interface.
  3. Ensure that our configuration class extends the WebSecurityConfigurerAdapter class which is a base class for creating WebSecurityConfigurer instances. After we have done this, we can customize the security configuration by overriding methods.
  4. Add an UserRepository field to the configuration and annotate the field with the @Autowired annotation.
  5. Override the configure(WebSecurity web) method of the WebSecurityConfigurerAdapter class. Ensure that Spring Security ignores requests made to static resources such as CSS and Javascript files.
  6. Override the configure(HttpSecurity http) method of the WebSecurityConfigurerAdapter class and implement it by following these steps:
    1. Configure form login by following these steps:
      1. Set the login page url to '/login'.
      2. Set the url which processes login form submissions to '/login/authenticate'.
      3. Set the login failure url to '/login?error=bad_credentials'.
    2. Configure the logout function by following these steps:
      1. Ensure that a cookie called JSESSIONID is deleted after logout.
      2. Set the logout url to '/logout'.
      3. Set the logout success url to '/login'.
    3. Configure url based authorization. The main point of this phase is to ensure that anonymous users can access all urls which are related to the sign in / registration process, and protect the rest of our application from anonymous users.
    4. Add the SocialAuthenticationFilter to the Spring Security filter chain. We can do this by creating a new SpringSocialConfigurer object and ensuring that this object is used when Spring Security is configured.
  7. Configure the PasswordEncoder bean which is used to hash the password of the user (if the user uses form registration and login). We can do this by creating a new BCryptPasswordEncoder object and returning the created object.
  8. Configure the UserDetailsService bean. We can do this by creating a new RepositoryUserDetailsService object and passing the UserRepository as a constructor argument.
  9. Override the configure(AuthenticationManagerBuilder auth) method of the WebSecurityConfigurerAdapter class. We use this method for configuring authentication requests if the user uses form login. Implement this method by following these steps:
    1. Pass the UserDetailsService bean to the AuthenticationManagerBuilder object given as a method parameter.
    2. Pass the PasswordEncoder bean to the AuthenticationManagerBuilder object given as a method parameter.
  10. Configure the SocialUserDetailsService bean. We can do this by creating a new SimpleSocialUserDetailsService object and passing the UserDetailsService bean as a constructor argument. This bean loads the user specific data when social sign in is used.

The source code of our application context configuration class looks as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.social.security.SpringSocialConfigurer;

@Configuration
@EnableWebSecurity
public class SecurityContext extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserRepository userRepository;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web
                //Spring Security ignores request to static resources such as CSS or JS files.
                .ignoring()
                    .antMatchers("/static/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //Configures form login
                .formLogin()
                    .loginPage("/login")
                    .loginProcessingUrl("/login/authenticate")
                    .failureUrl("/login?error=bad_credentials")
                //Configures the logout function
                .and()
                    .logout()
                        .deleteCookies("JSESSIONID")
                        .logoutUrl("/logout")
                        .logoutSuccessUrl("/login")
                //Configures url based authorization
                .and()
                    .authorizeRequests()
                        //Anyone can access the urls
                        .antMatchers(
                                "/auth/**",
                                "/login",
                                "/signup/**",
                                "/user/register/**"
                        ).permitAll()
                        //The rest of the our application is protected.
                        .antMatchers("/**").hasRole("USER")
                //Adds the SocialAuthenticationFilter to Spring Security's filter chain.
                .and()
                    .apply(new SpringSocialConfigurer());
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService())
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(10);
    }

    @Bean
    public SocialUserDetailsService socialUserDetailsService() {
        return new SimpleSocialUserDetailsService(userDetailsService());
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new RepositoryUserDetailsService(userRepository);
    }
}

Let's move on and find out how we can configure Spring Social.

Configuring Spring Social

Spring Social provides integrations with SaaS API providers such as Facebook and Twitter. We can configure Spring Social by following these steps:

  1. Create the application context configuration class which implements the SocialConfigurer interface and annotate the created class with the @Configuration annotation. The SocialConfigurer interface declares callback methods which can be used to configure Spring Social.
  2. Annotate the class with the @EnableSocial annotation. This enables Spring Social and imports the SocialConfiguration configuration class.
  3. Add a DataSource field to the configuration class and annotate the field with the @Autowired annotation.
  4. Add the addConnectionFactories() method of the SocialConfigurer interface to the created configuration class. This method takes two method parameters which are described in the following:
    1. The first parameter is a ConnectionFactoryConfigurer object which can be used to register connection factories.
    2. The second parameter is an Environment object which represents the environment in which our example application is running.
  5. Implement the addConnectionFactories() method by following these steps:
    1. Create a new TwitterConnectionFactory object, and pass the consumer key and the consumer secret as constructor arguments.
    2. Register the created TwitterConnectionFactory object by calling the addConnectionFactory() method of the ConnectionFactoryConfigurer interface. Pass the created TwitterConnectionFactory object as a method parameter.
    3. Create a new FacebookConnectionFactory object, and pass the application id and the application secret as constructor arguments.
    4. Register the created FacebookConnectionFactory object by calling the addConnectionFactory method of the ConnectionFactoryConfigurer interface. Pass the created FacebookConnectionFactory object as a method parameter.
  6. Add the getUserIdSource() method of the SocialConfigurer interface to the created class. The UserIdSource object returned by this method is responsible of determining the correct account id of the user. Because our example application uses the username of the user as an account id, we have to implement this method by returning a new AuthenticationNameUserIdSource object.
  7. Add the getUsersConnectionRepository() method of the SocialConfigurer interface to the created class. This method takes a ConnectionFactoryLocator object as a method parameter and returns a UsersConnectionRepository object.
  8. Implement the getUsersConnectionRepository() method by following these steps:
    1. Create a new JdbcUsersConnectionRepository object and pass the following objects as constructor arguments:
      1. The first argument is a DataSource object. We pass the value of the dataSource field as the first method parameter.
      2. The second argument is a ConnectionFactoryLocator object. We pass the value of the connectionFactoryLocator method parameter as the second method parameter.
      3. The third parameter is a TextEncryptor object which encrypts the authorization details of the connection established between a SaaS API provider and our application. We create this object by calling the noOpText() method of the Encryptors class. This means that our example application stores these details as plaintext. This is handy during the development phase but we should not use it in production.
    2. Return the created object.
  9. Configure the ConnectController bean. The method which configures this bean has two parameters. The first parameter is the ConnectionFactoryLocator bean. The second parameter is the used ConnectionRepository bean. Pass these parameters as constructor arguments when you are creating a new ConnectController object.

The source code of our configuration class looks as follows:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurer;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;
import org.springframework.social.connect.web.ConnectController;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.security.AuthenticationNameUserIdSource;
import org.springframework.social.twitter.connect.TwitterConnectionFactory;

import javax.sql.DataSource;

@Configuration
@EnableSocial
public class SocialContext implements SocialConfigurer {

    @Autowired
    private DataSource dataSource;

    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
        cfConfig.addConnectionFactory(new TwitterConnectionFactory(
                env.getProperty("twitter.consumer.key"),
                env.getProperty("twitter.consumer.secret")
        ));
        cfConfig.addConnectionFactory(new FacebookConnectionFactory(
                env.getProperty("facebook.app.id"),
                env.getProperty("facebook.app.secret")
        ));
    }

    @Override
    public UserIdSource getUserIdSource() {
        return new AuthenticationNameUserIdSource();
    }

    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        return new JdbcUsersConnectionRepository(
                dataSource,
                connectionFactoryLocator,
                Encryptors.noOpText()
        );
    }

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

Our next step is to configure the web layer of our application. Let's get to work.

Configuring the Web Layer

We can configure the web layer of our application by following these steps:

  1. Create the configuration class by following these steps:
    1. Extend the WebMvcConfigurerAdapter class.
    2. Annotate the created class with the @Configuration annotation.
  2. Ensure that all controller classes are found by annotating the class with the @ComponentScan annotation and setting the base packages of our controllers.
  3. Enable the annotation driven web mvc by annotating the class with the @EnableWebMvc annotation.
  4. Ensure that static resources are served by container’s default servlet.
    1. Configure the static resources by overriding the addResourceHandlers() method of the WebMvcConfigurerAdapter class.
    2. Ensure that requests made to static resources are delegated forward to the container's default servlet. This is done by overriding the configureDefaultServletHandling() method of the WebMvcConfigurerAdapter class.
  5. Configure the exception resolver bean.
  6. Configure the ViewResolver bean.

The source code of the WebAppContext class looks as follows:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import java.util.Properties;

@Configuration
@ComponentScan(basePackages = {
        "net.petrikainulainen.spring.social.signinmvc.common.controller",
        "net.petrikainulainen.spring.social.signinmvc.security.controller",
        "net.petrikainulainen.spring.social.signinmvc.user.controller"
})
@EnableWebMvc
public class WebAppContext extends WebMvcConfigurerAdapter {

	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public SimpleMappingExceptionResolver exceptionResolver() {
        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();

        Properties exceptionMappings = new Properties();

        exceptionMappings.put("java.lang.Exception", "error/error");
        exceptionMappings.put("java.lang.RuntimeException", "error/error");

        exceptionResolver.setExceptionMappings(exceptionMappings);

        Properties statusCodes = new Properties();

        statusCodes.put("error/404", "404");
        statusCodes.put("error/error", "500");

        exceptionResolver.setStatusCodes(statusCodes);

        return exceptionResolver;
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }
}

Let's find out how we can tie this all together and create a "parent" application context configuration class for our application.

Tieing It All Together

The last application context configuration class has three responsibilities:

  1. It configures general components used throughout our example application.
  2. It ensures that the service classes of our application are found during the classpath scan.
  3. It is the root application context configuration class of our application.

We can create this configuration class by following these steps:

  1. Create the configuration class and annotate the created class with the @Configuration annotation.
  2. Ensure that our service classes are found during the component scan by annotating the class with @ComponentScan annotation and setting the base package of our services.
  3. Import the other application context configuration classes by annotating the class with the @Import annotation.
  4. Annotate the class with the @PropertySource annotation, and configure it to look for a properties file called application.properties from the classpath. This ensures that the configuration properties can be accessed in the imported application context configuration classes.
  5. Configure the MessageSource bean.
  6. Configure the PropertySourcesPlaceholderConfigurer bean.

The source code the ExampleApplicationContext class looks as follows:

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
@ComponentScan(basePackages = {
        "net.petrikainulainen.spring.social.signinmvc.user.service"
})
@Import({WebAppContext.class, PersistenceContext.class, SecurityContext.class, SocialContext.class})
@PropertySource("classpath:application.properties")
public class ExampleApplicationContext {

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

        messageSource.setBasename("i18n/messages");
        messageSource.setUseCodeAsDefaultMessage(true);

        return messageSource;
    }

    @Bean
    public PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

We have now configured the application context of our example application. However, we still have to configure our web application. Let's see how we can do this by using Java configuration.

Configuring the Web Application

Our last step is to configure our example application. We can do this without web.xml as long as our application is deployed to a servlet 3.0 compliant container.

We can configure the web application by following these steps:

  1. Create a class which implements the WebApplicationInitializer interface.
  2. Configure our application by overriding the onStartup() method of the WebApplicationInitializer interface. We can implement this method by following these steps:
    1. Create the root context of the application and register the ExampleApplicationContext class to the created root context.
    2. Configure the dispatcher servlet.
    3. Configure character encoding filter.
    4. Configure the Spring Security filter chain.
    5. Configure Sitemesh.
    6. Add the context loader listener to the servlet context.

The source code of the ExampleApplicationConfig class looks as follows:

import org.sitemesh.config.ConfigurableSiteMeshFilter;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.*;
import java.util.EnumSet;

public class ExampleApplicationConfig implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ExampleApplicationContext.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");

        EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);

        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);

        FilterRegistration.Dynamic characterEncoding = servletContext.addFilter("characterEncoding", characterEncodingFilter);
        characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");

        FilterRegistration.Dynamic security = servletContext.addFilter("springSecurityFilterChain", new DelegatingFilterProxy());
        security.addMappingForUrlPatterns(dispatcherTypes, true, "/*");

        FilterRegistration.Dynamic sitemesh = servletContext.addFilter("sitemesh", new ConfigurableSiteMeshFilter());
        sitemesh.addMappingForUrlPatterns(dispatcherTypes, true, "*.jsp");

        servletContext.addListener(new ContextLoaderListener(rootContext));
    }
}

What is Next?

We have now successfully configured our example application by using Java configuration. This tutorial has taught us two things:

  • We learned how we can implement the components required by Spring Security and Spring Social.
  • We learned to integrate Spring Security and Spring Social by using Java configuration.

The next part of this tutorial describes how we can add registration and login functions to our example application.

As always, the example application of this blog post is available at Github.

If you want to learn how to use Spring Social, you should read my Spring Social tutorial.
256 comments… add one
  • jay.cz Oct 4, 2013 @ 20:32

    Looking forward to second part of tutorial...

    • Petri Oct 4, 2013 @ 21:28

      I start writing it tomorrow. I think that I can publish it next week.

  • Caio Oct 5, 2013 @ 23:28

    great post, helped me very much. I'm waiting for the next.

    obrigado

    • Petri Oct 8, 2013 @ 17:25

      I am happy to hear that I could help you out.

  • Alexey Zvolinskiy Oct 6, 2013 @ 10:56

    Petri, I have made a pause in a Spring article writing, but you inspired me to return to this =)

    • Petri Oct 8, 2013 @ 17:27

      Hi Alexey,

      It is good to hear from you! Also, continue writing Spring articles. :)

  • Caio Oct 6, 2013 @ 18:06

    Great, I'm from Brazil and this post helped to understand spring's configuration.

    congratulations

    • Petri Oct 8, 2013 @ 17:26

      Thank you! I appreciate your kind words.

  • sam Nov 17, 2013 @ 17:47

    Hi Petri,

    nice detail articular. i am struggling to get this working, appreciate you help.

    1. i could not working, hence i configured below in xml then, at deployment it failed with below error

    exception
    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'socialAuthenticationFilter' defined in ServletContext resource [/WEB-INF/spring/LBSWeb/security-config.xml]: Unsatisfied dependency expressed through constructor argument with index 2 of type [org.springframework.social.connect.UsersConnectionRepository]: Could not convert constructor argume
    nt value of type [com.sun.proxy.$Proxy198] to required type [org.springframework.social.connect.UsersConnectionRepository]: Failed to convert value of type 'com.sun.proxy.$Proxy198 implementing org.springframework.social.connect.ConnectionRepository,java.io.Serializable,org.springframework.
    aop.scope.ScopedObject,org.springframework.aop.framework.AopInfrastructureBean,
    org.springframework.aop.Spring
    Proxy,org.springframework.aop.framework.Advised' to required type 'org.springframework.social.connect.UsersConnectionRepository'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.sun.proxy.$Proxy198 implementing org.springframework.social.connect.ConnectionRepository,java.io.Serializable,
    org.springframework.aop.scope.ScopedObject,org.springframework.aop.framework.
    AopInfrastructureBean,
    org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [org.springframework.social.connect.UsersConnectionRepository]: no matching editors or conversion strategy found
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray
    (ConstructorResolver.java:702)

    hope you can help me out.

    • Petri Nov 17, 2013 @ 18:10

      Hi Sam,

      It seems that Wordpress ate your XML configuration. However, it seems that Spring cannot convert the constructor argument with index 2 to required type (UsersConnectionRepository). It is kind of hard to figure out what could be wrong without seeing the XML configuration file. Can you paste it to Pastebin?

      Also, have you compared the XML configuration of the example application to your application context configuration?

      The configuration files which are relevant to you are: exampleApplicationContext-social.xml and exampleApplicationContext-security.xml.

  • sam Nov 17, 2013 @ 18:44

    Thank you for the quick revert.

    i posted the xml on Pastebin ' SamJay - spring social xml configuration issue'. i am using spring.social.version>1.1.0.M4

    actually i tried to make the configuration work as give by you. but for some reason social:jdbc-connection-repository did not work or recongnized, it failed to compiler with nodefine bean expectation for usersConnectionRepository, that's why i switched to xml configuration at first place.

    i understand there are 2 place where usersConnectionRepository has being used (socialAuthenticationFilter and socialAuthenticationProvider ), i get the exception with socialAuthenticationProvider .

    thank you.

    • Petri Nov 17, 2013 @ 19:05

      For some reason I cannot find the XML from Pastebin by using the search term: 'SamJay – spring social xml configuration issue'. Could you provide a direct link to it?

      By the way, this example assumes that you use Spring Social version 1.1.0.BUILD-SNAPHOT. The reason for this is that some classes which makes the configuration a lot simpler are not available in the version 1.1.0.M4.

  • sam Nov 17, 2013 @ 19:11

    here is the link Petri.
    http://pastebin.com/uu9K2tJH

    i did try with the as is configuration given by you but it still does not pick the social:jdbc-connection-repository so its failed at deployment to JBoss.

    thanks.

    • Petri Nov 17, 2013 @ 19:30

      The reason why you cannot use Java configuration if you deploy to JBoss is that JBoss doesn't support Spring Java configuration yet. Have you tried to deploy the application to Tomcat 7? It could be useful because this way you could figure out if this is a JBoss related problem.

      I noticed that you don't set the value of the index attribute when you use the constructor-arg element. Have you tried to set it?

      Also, some of your configuration files use the old Spring versions (3.1). You should probably update them to the latest versions.

      Have you tried to update your Spring Social version to 1.1.0.BUILD-SNAPSHOT? If you would do that, you should be able to use my versions of the XML configuration files. This would make your application context configuration files easier to read and less brittle.

  • sam Nov 17, 2013 @ 20:16

    thanks,
    i am not using Java configuration at all only old faction xml, and adding constructor-arg element also made no difference.

    i will deploy the app to the tomcat to eliminate the server.

    below has simile issue being discussed, but could not really help.
    http://forum.spring.io/forum/spring-projects/web/social/118162-exception-faced-while-migrating-social-s-java-based-configuration-style-to-xml-based

    thanks
    will write to you with update.

    • Petri Nov 17, 2013 @ 20:47

      After I read that discussion, I realized that is probably an AOP related issue. I noticed a small difference between your XML configuration file and a file mentioned in that thread. Have you tried to declare the JdbcUsersConnectionRepository bean as follows:

      
      <bean id="jdbcConnectionRepository"
      	class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository" 
      	primary="true" 
      	scope="singleton" >
      	<constructor-arg ref="dataSource" />
      	<constructor-arg ref="connectionFactoryLocator" />
      	<constructor-arg ref="textEncryptor" />
      	<aop:scoped-proxy proxy-target-class="false" />
      </bean>
      
      
  • sam Nov 18, 2013 @ 10:03

    thanks, i tried that, but still get the same error,

    one other think i tried to get the Spring Social version 1.1.0.BUILD-SNAPHOT from.
    http://projects.spring.io/spring-social/core.html, but it also failed downloading the jar's.

    dependencies>

    org.springframework.social
    spring-social
    1.1.0.BUILD-SNAPSHOT

    spring-snapshots
    Spring Snapshots
    http://repo.spring.io/snapshot

    true

    • Petri Nov 18, 2013 @ 13:44

      Hi,

      You can get the correct dependencies from the Spring snapshot repository by following these steps:

      1. Add the snapshot repository to your POM file (I assume that you did this).
      2. Use the groupId org.springframework.social (This was also right).
      3. Add the following modules to your POM: spring-social-core, spring-social-security, and spring-social-web.
      4. Add the required client modules to your POM.

      Check the POM file of the example application for more details about this.

      Also, It seems that the required modules are found from the snapshot repository. Perhaps the download failed because of a network issue or something.

  • sam Nov 18, 2013 @ 12:29

    Hi Petri,
    deployment failed on tomcat 7 as well with same exception.

    • Petri Nov 18, 2013 @ 13:54

      I was expecting that. The problem is related to Spring AOP and not to the used server. I noticed that you answered to this thread.

      Let's hope that you get an answer soon (I want to hear what the problem was)!

  • sam Nov 20, 2013 @ 1:43

    Will keep you posted as soon as i get a answer.

    on a different note can you please enplane the below please.

    with the ConnectController, called back (redirect) into your app: GET /connect/facebook?code=xxx, which ends up with page not found.

    how should i capture the call back here and seamlessly integrate with the app

  • sam Nov 20, 2013 @ 14:20

    Hi

    do u know the reason for this error please

    [ServerImpl] JBoss (Microcontainer) [5.0.1.GA (build: SVNTag=JBoss_5_0_1_GA date=200902231221)] Started in 1m:27s:96ms
    [STDOUT] WARN : org.springframework.social.connect.web.ConnectController - Exception while handling OAuth2 callback (The OAuth2 'state' parameter doesn't match.). Redirecting to facebook connection status page.

  • sai Dec 6, 2013 @ 5:08

    Hi Petri,

    I have added /web-inf/jsp/js/app.js and web-inf/jsp/js/controller.js and updated
    layout.jsp with below includes.

    <script type="text/javascript" src="">

    getting below errors in javascript console

    Refused to execute script from 'http://localhost:8080/springsocialsignin/js/app.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled. login:1
    Refused to execute script from 'http://localhost:8080/springsocialsignin/js/controller.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled. login:1

    do i need to update webapp? any pointers??

    sridhar

    • Petri Dec 6, 2013 @ 12:04

      Hi Sai,

      The problem is that tou put your Javascript files to WEB-INF/jsp/js/ directory, and servlet containers do not serve any content put to the WEB-INF directory.

      You can solve this by moving your Javascript files to the src/main/webapp directory. If you use the same approach which I used in the example application, you should move the app.js and controller.js files to the src/main/webapp/static/js/app directory and add the following code to the layout.jsp file:

      
      <script type="text/javascript" 
        src="${pageContext.request.contextPath}/static/js/app/app.js"></script>
      <script type="text/javascript" 
        src="${pageContext.request.contextPath}/static/js/app/controller.js"></script>
      
      

      I hope that this answered to your question.

  • RetRo Dec 14, 2013 @ 7:58

    I think there is a dependency missing: spring-social-config

    • Petri Dec 14, 2013 @ 11:11

      You are right! Thanks for pointing this out. It seems that the spring-social-config module is a transitive dependency but I agree that it might be better to explicitly specify it (at least in this case). I will update the blog post and the example application.

  • RetRo Dec 14, 2013 @ 7:59

    oops, forgot to say first, awesome article, thanks a lot for sharing :)

    • Petri Dec 14, 2013 @ 11:25

      Thanks! I appreciate your kind words.

  • Davi Dec 16, 2013 @ 8:55

    Hi petri, i'am newbie in spring. How to add your example source to my project in eclipse?
    Thank you

    • Petri Dec 16, 2013 @ 9:49

      Hi Davi,

      I haven't been using Eclipse for several years but let's see if I can help you out. Which Eclipse version are you using?

      • danang Dec 15, 2014 @ 8:58

        hi Petri, What are you using for this project?

        • Petri Dec 15, 2014 @ 9:46

          I use IntelliJ Idea, but the example application uses Maven. In other words, you can compile / package / run it without using an IDE. All you have to do is to clone it from the Github repository and you are ready to go (if you have installed JDK + Maven).

  • Davi Dec 16, 2013 @ 14:01

    Thank you for your reply. I'm using eclipse kepler.

    • Petri Dec 16, 2013 @ 14:16

      It seems that you should be able to do this by navigating to:

      File -> Import -> Browse to general -> Maven Projects

      This wiki page has more information about this (including screenshots).

      I hope that this solved your problem.

  • Davi Dec 16, 2013 @ 16:10

    Great, thank you. Great tutorial petri.

  • Phuong Dang Jan 13, 2014 @ 9:38

    uhmm. It's should not be this complicated.

    • Petri Jan 13, 2014 @ 20:11

      I agree. It will be interesting to see if Spring Boot will be integrated with Spring Social.

  • Kumar Jan 14, 2014 @ 21:55

    New to this , I am getting the following error when I import the code to the eclipse
    Error loading property file '/Users/akumar/Documents/development/tracks/git/spring-social-examples/sign-in/spring-mvc-normal/profiles/dev/socialConfig.properties' (org.apache.maven.plugins:maven-resources-plugin:2.6:testResources:default-testResources:process-test-resources)

    • Petri Jan 14, 2014 @ 22:22

      You need to create the socialConfig.properties file yourself. This file contains the configuration of your Facebook and Twitter applications. See the README of the example application for more details about this.

  • Daniel Jan 19, 2014 @ 18:24

    Hello, im having huge problems adopting new facebook api to our application. Before i knew ill have to add it, i've created normal spring security besed User management. But now i have to add facebook. With new Social Security have been added XML based configuration with UserIdSource etc. But i've no idea how to use it. Could you be so nice and also create tutorial for XML based configuration that can be adopted to already existing spring security projects :( ?
    Huge thx for all help.

    • Petri Jan 19, 2014 @ 19:46

      Hi,

      Have you checked out the XML configuration of the example application? It should help you get started if you want to configure your application by using XML.

      I was planning to describe it in this blog post as well but I noticed that the blog post would probably be too long. That is why I decided to skip it and provided a link to the XML configuration instead.

      If you cannot solve problem by reading the configuration files, let me know and I will write a brief description about the required steps.

  • sam Feb 1, 2014 @ 4:56

    Hi Petri,

    I have managed to get the FB logging to work. Now i see that data are being populated to ‘userconnection’ table through ConnectController and when i disconnected from the service, the data from the table get deleted as well (hope the expected behavior).
    My query is:
    I have a table called ‘user’ which maintains the application form logging users information’s and authenticates via spring-security.
    What i want to figure out is, i would like to sync userconnection data which maintains FB user data with ‘user’ table which maintain the form application local user accounts. So in a situation where a client logging with a FB, i should be able to create an account in the site as well and pass that information (ex: a passwrod) via a mail. So that user has the ability to either use FB or site account.
    Can you please help me to understand am i thinking on the right direction? And what are the steps that i should do to achieve this.

    Thanks
    Sam

    • Petri Feb 1, 2014 @ 22:28

      Hi Sam,

      If your application uses email as username and you get the email address of the user from Facebook, you can create a row to the user table when a user signs in by using Facebook.

      The way I see this, you have two options:

      1. Modify the example application to create a new user account automatically (without rendering the registration form) when user signs in by using social sign in. However, I wouldn't create the password automatically and send it to the given email address because email isn't a secure way to transfer this kind of information. I would implement a password reset function which would allow the user to set his password. Read Troy Hunt's blog post titled Everything you ever wanted to know about building a secure password reset feature for more details about this (it is not Spring specific). Also, if you have to support other social sign in providers, you might run into problems because all social sign providers do not return the email address.
      2. Modify the example application of this blog post to ask (and process) the password information even if the user is using social sign in.

      The first option provides a better user experience. The problem is that you cannot use it if your application has to support social sign in providers which don't return the email address of the user or if you don't use email address as the username.

      The second option is easier to implement but it can be annoying because often users expect that they don't have to enter password information if they use social sign in.

      I hope that this answered to your question. If you need more advice about this, don't hesitate to ask additional questions.

      • sam Feb 2, 2014 @ 2:48

        HiPetri,

        Thank you very much for the detail explanation & ill go through the links you provided and get back to you on the outcome. I do want to support FB, Twitter, Googal+, hence need to check whether email is being returned by those services. but my current implementation does not use email as the username, yet i am able to get the username with below.

        Regarding the second point:
        i am not clear on this, what do you mean is; at the end of authentication success, inject a page to capture a password, is it?

        another query that i came across is,

        once the FB authentication is successful, default behaviors is, the flow returns to the facebookConnected.jsp. what is the configuration (bean) to allow the flow to be continued to the application since the user is now authenticated ?

        Thanks
        Saranga

        • Petri Feb 4, 2014 @ 21:47

          Hi Sam,

          First, I am not sure if you have tried the example application of this blog post but its registration flow goes like this:

          1. If the user is creating user account by using social sign in, the registration form has first name, last name, and email address fields.
          2. If the user is creating user account by using "normal registration", the registration form has first name, last name, email address, password, and password verification fields.

          What I meant was that you could ask the password information from users who are using social sign in. If you want to know more about the registration flow of the example application, you should read my blog post titled Adding Social Sign In to a Spring MVC Web Application: Registration and Login.

          Second, have you integrated Spring Social with Spring Security or are you using only Spring Social?

          If you have integrated Spring Social with Spring Security, you can configure the AuthenticationSuccessHandler bean. If you are using Java configuration, you should take a look at this StackOverflow question.

          On the other hand, if you are using only Spring Social, you could try to set the url by calling the setPostSignInUrl() method of the ProviderSignInController class. I haven't tested this though so I am not sure if this is the right way to handle this.

          • sam Feb 5, 2014 @ 22:06

            Hi Petri,

            i am using the Spring Social with Spring Security and i have gone though your example which user xml, configuration.

            i have posted my 2 xml file here for your reference. http://pastebin.com/P6u6cpyv (social-security xmls). hope it will make sense.

            i am going through the clinks that you are given. i am stuck on what to do with when the authentication call back return to facebookConnected.jsp. i guess, i want to capture the callback and take the control to spring-security and let the application work flow proceed.
            as you can see, i have used default spring provided controller, i guess i need to overwrite this and configure a way to let the flow run through the application flow.

            thank you very much for your help.

            thanks
            saranga

          • Petri Feb 5, 2014 @ 23:57

            Hi Sam,

            I just realized something. Do you use the url /auth/[provider] (in other words, for Facebook this url would be /auth/facebook) to start the social sign in flow or do you use the url /connect/[provider]?

            If you only want to authenticate the user, you should use the first url (/auth/[provider]) because requests send to that url are processed by the SocialAuthenticationFilter.

            I took a very quick look at your configuration files and they seemed to be fine.

  • Moussi Feb 6, 2014 @ 21:29

    I want to make a full example integrating spring social and spring security using MongoDB , i need some examples , links or tuorials that help me to achieve that. i don't know the needed changes to make in order to use mongodb instead of mysql because the problem that i faced is that Spring Social project already provides a jdbc based connection repository implementation to persist user connection data into a relational database. i don't know if this is only used by relational databases :(

    • Petri Feb 8, 2014 @ 10:44

      Hi Moussi,

      The JdbcUsersConnectionRepository class persist connection information to a relational database. If you want to save this information to MongoDB, you have implement the UsersConnectionRepository interface.

      I have never done this but I found a blog post titled Customize Spring Social Connect Framework For MongoDB (unfortunately this blog post has been removed). It explains how you can persist connection information to MongoDB. You can get the example application of this blog post from Github.

      I hope this helps you to achieve your goal!

  • Yves Tanas Feb 14, 2014 @ 22:40

    I am looking forward on using this solution for testing in my environment.
    As i have had no contact yet with sitemesh, here's my question.
    How would i do sth. like this:
    https://groups.google.com/forum/#!topic/sitemesh3-users/KjxbrtC0fFI
    I think this work should be done in ExampleApplicationConfig, but i am stuck with this.
    Is there some easy solution to add things like ?

  • Yves Tanas Feb 15, 2014 @ 2:51

    Hi there, forget about my last post.
    I made a small change in "ExampleApplicationConfig" on setting up the sitemesh

    FilterRegistration.Dynamic sitemesh = servletContext.addFilter("sitemesh", new TagBundlerFilterForSite());
    sitemesh.addMappingForUrlPatterns(dispatcherTypes, true, "*.jsp");

    While adding the new Class to the same package:
    public class TagBundlerFilterForSite extends ConfigurableSiteMeshFilter {
    public TagBundlerFilterForSite(){
    this.applyCustomConfiguration(new SiteMeshFilterBuilder());
    }
    @Override
    protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
    builder.addTagRuleBundle (new DivExtractingTagRuleBundle ());
    }
    }

    I can now do this:

    Template:

    JSP-Page:Some more data

    for me this really helps to use my template well, maybe u or others can use that.
    I know the setup on the constructor is a bad thing, but as i really tried to get this working, i was happy for now. If there is a better solution, let me know ! :)

    • Petri Feb 17, 2014 @ 19:18

      It is great to hear that you were able to solve your problem!

      Also, thanks for coming back and posting your solution to my blog. Now I know where to look if I need similar functionality (I have never needed it yet).

  • Twinkle Mar 4, 2014 @ 5:29

    Heh,
    This is really an awesome post.This will help me a lot.
    Can you please mail me the zip file of the complete code? I tried to copy the code and and run, but it's not working. Am trying to remove errors since last 3 days, but not able to do so.
    Please help me out.
    Mail me as soon as possible.

  • Nandhana Mar 11, 2014 @ 8:46

    Hi petri,
    I have one doubt.How to set the anonymous user for authentication without xml configuration?

    • Petri Mar 11, 2014 @ 20:50

      Hi,

      If you are talking about the anonymous authentication support of Spring Security, it should be enabled by default. The default role of the anonymous user is ROLE_ANONYMOUS, and you can use this role when you specify the authorization rules of your application.

      Unfortunately I don't how you can customize the anonymous authentication support without using XML configuration. :(

  • Roman Mar 14, 2014 @ 5:50

    Hello! I'm trying to follow this tutorial, but I have a problem downloading the dependencies.
    Can you help me out?

    Thanks

    The following artifacts could not be resolved: org.springframework.social:spring-social-config:jar:1.1.0.BUILD-SNAPSHOT, org.springframework.social:spring-social-core:jar:1.1.0.BUILD-SNAPSHOT, org.springframework.social:spring-social-security:jar:1.1.0.BUILD-SNAPSHOT, org.springframework.social:spring-social-web:jar:1.1.0.BUILD-SNAPSHOT, org.springframework.social:spring-social-facebook:jar:1.1.0.BUILD-SNAPSHOT: Failure to find org.springframework.social:spring-social-config:jar:1.1.0.BUILD-SNAPSHOT in http://repo.springsource.org/libs-milestone was cached in the local repository, resolution will not be reattempted until the update interval of spring-milestone has elapsed or updates are forced

  • Christopher Smith Mar 18, 2014 @ 1:04

    Please let me know if I'm misunderstanding, but it appears that this application permits a user to associate exactly one social-media account--of any type--with their application account, so that a user can't associate both Facebook and Twitter accounts simultaneously. It appears that the SocialUserDetails interface has a massive flaw in that its getUserId() method takes no parameter specifying *which* social service for which we're looking up the user's identity. Did I overlook some out-of-band information to the persistence layer about which social network is being talked about (such as an injectable thread-local holder), or does is this entire setup limited to a single social-media association per user?

    • Petri Mar 18, 2014 @ 20:40

      You are right. If a user creates a user account by using Facebook, he cannot sign in by using Twitter (or associate a Twitter account with his local user account). However, it is possible to support multiple social sign in providers as well.

      I haven't done this myself but I think that you can do this by following these steps:

      1. Modify the User entity and add support for multiple social sign in providers (this is required only if you want to store this information).
      2. Implement the UserIdSource interface and create a userId which contains the information required to identify the local user and the used social sign in provider.
      3. Implement the SocialUserDetailsService interface and ensure that it can handle the "new" userId (you have to parse the local username from userId and load the correct user).
      4. Use the "new" userId when you persist the connection between the user and the social sign in provider (See the javadoc ProviderSignInUtils class.

      If you have any further questions, don't hesitate to ask them.

  • JSSAggie Apr 14, 2014 @ 7:13

    Petri,

    I was looking around on the web to find out how to change the scope when doing a Facebook login authorization. I was looking to make the change in the configuration rather having to send a post with a hidden variable on the social login button.

    I see in SocialContext that we are adding the Facebook connection factory and it has a method to set the scope. I changed the scope and it does not change the scope on the authorization. Do you know how to change this at the configuration level?

    There is an "Authorization scope" section that explains how it is done but not at the configuration level.
    http://docs.spring.io/spring-social/docs/1.0.3.RELEASE/reference/html/connecting.html

    Have you done this before?

    • Petri Apr 14, 2014 @ 21:23

      I was able to verify that setting the scope by calling the setScope(String scope) method of the OAuth2ConnectionFactory class (FacebookConnectionFactory extends this class) doesn't seem to do anything.

      Unfortunately I cannot provide an answer right away, but I promise that I will take a closer look at this because the Javadoc of that method suggests that it should work. I will let you know if I find a solution.

      • JSSAggie Apr 15, 2014 @ 6:34

        I looked around tonight and did not find a way to set the scope but I did find that OAuth2AuthenticationService.defaultScope is really what is being used when it adds the scope to the URL. If you don't pass a scope as a hidden variable it will use the defaultScope.

        Thanks again for always being so helpful.

        • JSSAggie May 3, 2014 @ 0:46

          Petri,

          Have you found a work around for this? I have not. I tried looking through the source code and kept getting a little lost and did not find a path to set the scope.

          • Petri May 3, 2014 @ 12:16

            Hi,

            Actually I did found something from the web:

            It seems that if you want to set the default scope, you have to use the FacebookAuthenticationService class.

            The SecurityEnabledConnectionFactoryConfigurer object given as a method parameter to the addConnectionFactories() method of the SocialConfigurerinterface creates the required authentication service objects BUT it doesn't set the default scope.

            I assume that if you want to set the default scope, you have remove the @EnableSocial annotation from the SocialContext class and create all required beans manually.

            I can take a closer look at this tomorrow.

          • Petri May 4, 2014 @ 11:44

            I checked this out and I noticed one problem:

            I should create a ConnectionRepository bean but I am unable to do it because the ConnectionRepository class is package-private (and I don't want to move the SocialContext class to the same package).

            You could of course configure Spring Social by using XML configuration but if you don't want to do that, you should create a new issue to the Spring Social project.

          • JSSAggie May 6, 2014 @ 6:05

            Petri,

            Thanks again. I created a ticket. With your help I hope they have enough information to find the bug. I am a little lost.

            https://jira.spring.io/browse/SOCIAL-436

          • Petri May 6, 2014 @ 17:55

            You are welcome! Let's hope that the Spring Social team can solve this soon.

  • iMedia Designs Apr 18, 2014 @ 14:45

    great post, helped me very much.

    • Petri May 3, 2014 @ 12:19

      I am happy to hear that.

  • Ademir Constantino May 7, 2014 @ 22:29

    Hi Petri,
    I'm trying to implement spring-social-facebook in my application, however I'm stuck in the JdbcUsersConnectionRepository part. I would like to have my own UsersConnectionRepository using Hibernate but without JPA.

    Thanks much in advance

    • Petri May 7, 2014 @ 22:57

      The JdbcUsersConnectionRepository class uses the JDBC API. In other words, you can use it in an application which uses the "native" Hibernate API.

      You can of course create your own implementation by implementing the UsersConnectionRepository interface but I am not sure if it is worth the effort.

      Did you mean that you want to create a custom UserDetailsService which uses Hibernate instead of Spring Data JPA?

  • RCB Jun 1, 2014 @ 19:46

    HI Petri

    At the end of this tutorial I have an error with the servletContext.addServlet, servletContext.addFilter and servletContext.addListener ... I´m workinh with Eclipse and the message that appear is "The method addListener(ContextLoaderListener) is undefined for the type ServletContext".
    The solution tath Eclipse suggest me is "Add Cast to servletContext"

    What can I do?
    Thanks much in advance

  • PR Jun 14, 2014 @ 3:09

    Hi Petri,

    Thank you very much for the detailed tutorials!
    I have a question that is similar to the one from Ademir. I would like to integrate spring social into my project however I don't need any of the spring social persistence stuff and just seems to conflict with my application. All I really need is Spring Social's Facebook methods. Is this possible to simplify the setup in this way?
    Any help would be greatly appreciated!

    • Petri Jun 15, 2014 @ 11:46

      Hi,

      Do you want that your application is able to read information from Facebook and write information to Facebook (and that is it)? If that is the case, you should read a tutorial titled Accessing Facebook Data. It should help you to get started.

      If that guide doesn't solve your problem, let me know!

  • farziny Jun 24, 2014 @ 19:07

    hello my friend,
    i have a trouble to run this sample, in "" class on line 68 we have
    .apply(new SpringSocialConfigurer())
    but i get can't resolve method ! i'm sure that i provide all maven dependencies correctly,
    then i tried to upgrade the "spring.security.version" to 3.2.4.RELEASE but the problem remains.
    whats the problem ?
    thanks.

    • Petri Jun 24, 2014 @ 22:18

      Are you getting a compilation error or a runtime error? Also, if you get a runtime error, it would be useful to see the stacktrace.

      • farziny Jun 25, 2014 @ 6:57

        hello again,
        when i start packaging app by using maven directly, i get rid of my first question, because that was just an IDE wrong alert.
        but now i have another problem after returning from facebook auth, the page redirected into
        http://localhost:8080/signin#_=_
        and i an error 404 will raise.
        of course i can't find any controller matching /signin url
        why!?
        whats the problem you think ?
        thank you

        • farziny Jun 25, 2014 @ 11:06

          Hi, Petri
          can you help me on my question ?
          thanks

        • Petri Jun 25, 2014 @ 11:11

          Hi,

          Yes, I was wondering if your previous problem was an IDE alert because I used to see a similar alert in IntelliJ Idea. However, it disappeared after I updated it to a newer version.

          I assume that your problem occurs when a registered user tries to log in to your application (because of the url). If this isn't the case, let me know.

          Anyway, you can configure the url in which the user is redirected after a successful login by following the instructions which I gave in this comment.

          Let me know if this doesn't solve your problem.

          • farziny Jun 25, 2014 @ 13:12

            here is my changes

            
            protected void configure(HttpSecurity http) throws Exception {
               SpringSocialConfigurer springSocialConfigurer = new SpringSocialConfigurer();
               springSocialConfigurer.postLoginUrl("/myurl");
               ...
            }
            
            

            in http:/localhost:8080/login i click on Sign in With facebook then i redirected to
            facebook and have a successful login but it still redirected to
            http:/localhost:8080/signin#_=_

            here is statcktrace
            DEBUG - LoginController - Rendering login page.
            DEBUG - RequestAddCookies - CookieSpec selected: best-match
            DEBUG - RequestAuthCache - Auth cache not set in the context
            DEBUG - ttpClientConnectionManager - Connection request: [route: {s}->https:/graph.facebook.com:443][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]
            DEBUG - ttpClientConnectionManager - Connection leased: [id: 0][route: {s}->https:/graph.facebook.com:443][total kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 10]
            DEBUG - MainClientExec - Opening connection {s}->https:/graph.facebook.com:443
            DEBUG - ttpClientConnectionManager - Connecting to graph.facebook.com/173.252.112.23:443
            DEBUG - anagedHttpClientConnection - http-outgoing-0: Shutdown connection
            DEBUG - MainClientExec - Connection discarded
            DEBUG - anagedHttpClientConnection - http-outgoing-0: Close connection
            DEBUG - ttpClientConnectionManager - Connection released: [id: 0][route: {s}->https:/graph.facebook.com:443][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]

          • farziny Jun 25, 2014 @ 15:53

            sorry Petri,
            can i ask what url you expected to called after return from facebook ?
            which controller must catch the request and how can i get auth_token to get all friends of logged in user ?
            i have so many quastions, but at first i need to run application properly,
            i googling so much for some other examples but yours is best article ever.
            thanks again.

          • Petri Jun 25, 2014 @ 18:10

            No problem. I happy to help but I am on summer holiday at the moment so my response time might be a bit longer than in a normal situation.

            Anyway, if you implement the registration and login functions as described in this blog post, the only urls you should care about are:

            • The sign up url. A user is redirected to this url when Facebook login is suggesful but a user account isn't found from the database. The default value of the sign up url is '/signup'. You can override this by using XML configuration. At the moment it isn't possible to override this url if you use Java configuration.
            • The post login url. A user is redirected to this url when Facebook login is successful and a user account is found from the database. You can change this url by following the instruction given in my last comment.

            I have never experienced a situation where the user would have been redirected to the '/signin' url, so I am not sure how you can solve this problem (The log you added to your comment doesn't reveal anything unusual).

            I think that the easiest to way to solve this problem is to compare the configuration of your application with the configuration of my example application. Unfortunately it is impossible to figure out the root cause without seeing the source code of your application.

            About your second question: I have never used Spring Social Facebook for accessing user's Facebook data (such as list of friends), so I don't know how you can do it. I think that your best bet is to read this guide which explains how you can create a simple web application that reads data from Facebook.

          • farziny Jun 26, 2014 @ 16:24

            excuse me Petri,
            i found that my server doesn't have an access to graph.facebook.com:443
            this make's the problem, after i resolve this issue now have a null pointer exception at
            org.springframework.social.security.SocialAuthenticationFilter.doAuthentication(SocialAuthenticationFilter.java:301)

            Authentication success = getAuthenticationManager().authenticate(token);
            and getAuthenticationManager(). return null value !
            do you have any suggestion ?
            thanks you for your replies,

          • Petri Jun 26, 2014 @ 16:45

            Have you configured the AuthenticationManager bean?

            You can do this by overriding the protected void configure(AuthenticationManagerBuilder auth) method of the WebSecurityConfigurerAdapter in the SecurityContext class (assuming that your configuration is similar than mine).

          • farziny Jun 26, 2014 @ 17:43

            finally, all thing worked together successfully.
            thanks for all of your advises.
            have a good holidays.

          • Petri Jun 26, 2014 @ 18:15

            Thanks! It is good to hear that you were able to solve your problem.

  • Coder Jun 25, 2014 @ 9:51

    Hi in RepositoryUserDetailService I am getting error "The method getBuilder() is undefined for the type ExampleUserDetails"...Please Help anyone..

  • FANA Jun 28, 2014 @ 11:26

    hello Peter.. thank your for this article.. can u create a video tutorial for this article..?

    • Petri Jun 28, 2014 @ 12:09

      Hi,

      That is a great idea. I will add this to my Trello board, and I will record the video tutorial in the future.

  • daniel Jun 28, 2014 @ 16:05

    I'm using your example and my question is where the method is implemented
    public User findByEmail(String email);?? i dont see (interface UserRepository.class)

    • Petri Jun 28, 2014 @ 16:21

      The findByEmail(String email) is a custom query method which is found from the UserRepository interface. This has been explained in the section titled 'Implementing the UserDetailsService interface'. You can also get the source code of the UserRepository interface from Github.

      • daniel Jun 28, 2014 @ 16:26

        yes, but I do not see where is the implementation of the method, see the calling but where is the implementation?

      • daniel Jun 28, 2014 @ 16:33

        I really doubt that userRepository class implements the interface for the method to work findByEmail

        sorry for my English

        thanks!!

        • Petri Jun 28, 2014 @ 16:55

          The example application uses Spring Data JPA which provides a proxy implementations for each interface which extends the Repository interface. That is why there is no need to implement the UserRepository interface.

  • sam Jun 30, 2014 @ 17:41

    Hi Petri,

    I in the process of implemented Spring Security & Spring Social for the website and also would like to allow for the iOS and Android apps to connect via the social as well. Idea i had in mind is to have the centralised api expose in web end and let it handle the social signup/sing in process where mobile end only connect to this api.

    Can you please help me on modelling such and how should i go on about this.

    Thanks

    • Petri Jul 2, 2014 @ 11:15

      Hi Sam,

      I have never done this myself (surprising but it is the truth).

      However, I found an answer to StackOverflow question titled 'Integrate app with spring social website' which looks quite promising. The idea is that you have to first implement the social sign in by using the native APIs (Android, iOS) and then provide the required credentials to your backend and log the user in.

      I am planning to extend my Spring Social tutorial to cover REST APIs in the future. I will probably take a closer look at this when I do that.

      • sam Jul 6, 2014 @ 16:58

        Thanks Petri. Look forward to it.

        • Armen Jun 30, 2015 @ 23:01

          Hi Petri,

          Did you have a chance to add REST API support in this example?

          • Petri Jun 30, 2015 @ 23:49

            Hi Armen,

            No. I will update my Spring Data JPA and Spring MVC Test tutorials before I will update this tutorial. If everything goes as planned, I will do it at November or most likely at December.

            Actually I asked this from the creator of Spring Social because one of my readers asked the same question, and he said that at the moment the best way to do this is to do a normal GET request and let the backend handle the authentication dance.

  • Amit Jul 9, 2014 @ 13:25

    Hi Petri,
    Thank you for your quick response. I tried working with maven but facing below issue. Can you please help me to look into this issue.

    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 4.906 s
    [INFO] Finished at: 2014-07-09T15:47:17+05:30
    [INFO] Final Memory: 13M/154M
    [INFO] ------------------------------------------------------------------------
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:2.6:resources (defau
    lt-resources) on project spring-mvc-normal: Error loading property file 'F:\workspace\login\profile
    s\dev\socialConfig.properties' -> [Help 1]
    [ERROR]

    • Petri Jul 9, 2014 @ 14:43

      Hi Amit,

      the Maven build is a bit different than the setup described in this blog post. It expects to find socialConfig.properties file from the profiles/dev/ directory. This properties file contains the configuration of your Facebook and Twitter application (app id and app secret).

      Also, the example application doesn't contain this file. This means that you have to create it yourself.The README of the example application explains how you can set up the example application before you can run it.

      I hope this answered to your question. If not, feel free to ask more questions!

  • Amit Kumar Singh Jul 15, 2014 @ 10:02

    I deployed the project but not able to access registration page and also authentication page is not available. can you please provide me complete setup of this project to learn more.

    • Petri Jul 15, 2014 @ 10:35

      Did you follow the steps described in the README of the example application?

      If you did follow them, could you check the log and paste the relevant part of it here (also, if you see any stack traces, add them here as well)?

      • Amit Jul 15, 2014 @ 10:56

        I followed the steps as you have mentioned and getting the login page. But when i tried to login my url is this "http://localhost:8080/spring-social-normal-mvc/login" and after submitting the URL it redirects to "http://localhost:8080/login". So, I feel the problem is redirecting the URL. It's not redirecting properly. Also, After login with facebook the url redirects to "http://localhost:8080/spring-social-normal-mvc/signin#_=_" and it shows 404 error. Please let me know if i have to update anything more in configuration.

        • Petri Jul 15, 2014 @ 11:25

          I followed the steps as you have mentioned and getting the login page. But when i tried to login my url is this “http://localhost:8080/spring-social-normal-mvc/login” and after submitting the URL it redirects to “http://localhost:8080/login”.

          The reason for this is that the action attribute of the login form ignores the context path. You can fix this by replacing the form tag with this one:

          
          <form action="${pageContext.request.contextPath}/login/authenticate" 
                method="POST" 
                role="form">
          
          

          I made the fix to the example application. Thank you for reporting this bug.

          Also, After login with facebook the url redirects to “http://localhost:8080/spring-social-normal-mvc/signin#_=_” and it shows 404 error.

          Another reader had the same problem, and the reason for this behavior was that his server didn't have access to the Facebook Graph API.

          • Amit Jul 15, 2014 @ 11:56

            Thank you Petri. It works.... cheers :)

          • Amit Jul 15, 2014 @ 12:45

            I tried as mentioned above but still it redirects to same url. I pasted my console log. Please have a look and help me to fix this issue.

            DEBUG - ttpClientConnectionManager - Connection leased: [id: 0][route: {s}->https:/
            /graph.facebook.com:443][total kept alive: 0; route allocated: 1 of 5; total alloca
            ted: 1 of 10]
            DEBUG - MainClientExec - Opening connection {s}->https:/graph.facebook
            .com:443
            DEBUG - ttpClientConnectionManager - Connecting to graph.facebook.com/31.13.74.128:
            443
            DEBUG - anagedHttpClientConnection - http-outgoing-0: Shutdown connection
            DEBUG - MainClientExec - Connection discarded
            DEBUG - anagedHttpClientConnection - http-outgoing-0: Close connection
            DEBUG - ttpClientConnectionManager - Connection released: [id: 0][route: {s}->https
            :/graph.facebook.com:443][total kept alive: 0; route allocated: 0 of 5; total allo
            cated: 0 of 10]
            DEBUG - LoginController - Rendering login page.
            DEBUG - RequestAddCookies - CookieSpec selected: best-match
            DEBUG - RequestAuthCache - Auth cache not set in the context
            DEBUG - ttpClientConnectionManager - Connection request: [route: {s}->https:/graph
            .facebook.com:443][total kept alive: 0; route allocated: 0 of 5; total allocated: 0
            of 10]
            DEBUG - ttpClientConnectionManager - Connection leased: [id: 1][route: {s}->https:/
            graph.facebook.com:443][total kept alive: 0; route allocated: 1 of 5; total alloca
            ted: 1 of 10]
            DEBUG - MainClientExec - Opening connection {s}->https:/graph.facebook
            .com:443
            DEBUG - ttpClientConnectionManager - Connecting to graph.facebook.com/31.13.74.128:
            443
            DEBUG - anagedHttpClientConnection - http-outgoing-1: Shutdown connection
            DEBUG - MainClientExec - Connection discarded
            DEBUG - anagedHttpClientConnection - http-outgoing-1: Close connection
            DEBUG - ttpClientConnectionManager - Connection released: [id: 1][route: {s}->https
            :/graph.facebook.com:443][total kept alive: 0; route allocated: 0 of 5; total allo
            cated: 0 of 10]

          • Petri Jul 15, 2014 @ 20:24

            Your log file looks pretty similar than farziny's log.

            His problem was that his server could not access the Facebook Graph API. I am not exactly sure what he meant by that, but I assumed that either his FB application was not configured properly, or the app secret and app key were not correct.

            When you created the FB Application for your web application, did you enable the Facebook login?

          • Amit Jul 16, 2014 @ 11:22

            Hi Petri,

            As, you said its blocking the facebook graph api, you were correct. I fixed the problem and working fine everything. You rocks dude...
            Trying to implement to get the post feed of user and friend list also. May be your help required in future again. So, thanks a lot in advance.

          • Raghavendra Rao Mar 22, 2015 @ 20:27

            Hi Amit, Petri,
            Even I am getting the same error you specified earlier. After the Facebook login, the control is not returning back to login page/signUp page. Do you know how to resolve this/ Enable the Facebook graph API on the server?

            DEBUG - headers - http-outgoing-1 << Access-Control-Allow-Origin: *
            DEBUG - headers - http-outgoing-1 << X-FB-Rev: 1653508
            DEBUG - headers - http-outgoing-1 << ETag: "02e90b73697f1bf84bb1c08a06c30817978e2ff1"
            DEBUG - headers - http-outgoing-1 << Pragma: no-cache
            DEBUG - headers - http-outgoing-1 << Cache-Control: private, no-cache, no-store, must-revalidate
            DEBUG - headers - http-outgoing-1 << Facebook-API-Version: v2.0
            DEBUG - headers - http-outgoing-1 << Expires: Sat, 01 Jan 2000 00:00:00 GMT
            DEBUG - headers - http-outgoing-1 << X-FB-Debug: KntgReJ8rZbpdGdWOho0pLPgYBPEpFQei1a+jQNDJJBs+qoE6Sx9pBiHGMk0MsA5NEv6oa0uEv5ABrrVqMwgJg==
            DEBUG - headers - http-outgoing-1 << Date: Sun, 22 Mar 2015 18:07:53 GMT
            DEBUG - headers - http-outgoing-1 << Connection: keep-alive
            DEBUG - headers - http-outgoing-1 <https://graph.facebook.com:443%5D can be kept alive indefinitely
            DEBUG - ttpClientConnectionManager - Connection released: [id: 1][route: {s}->https://graph.facebook.com:443%5D%5Btotal kept alive: 1; route allocated: 1 of 5; total allocated: 1 of 10]

          • Raghavendra Rao Mar 22, 2015 @ 21:09

            Hi Petri,
            I am facing a problem where the Facebook sign-in happens but after that the control is not returning to my applicaiton. It is simply waiting for localhost.
            I am simply running this code as is without any modification( except creating a new socialConfig.properties )
            what basically happens after the facebook login? Does it check for the user existance? I am asking this because I havent configured the Database.

          • Petri Mar 22, 2015 @ 22:26

            Hi,

            The registration and login process is explained in the second part of my Spring Social tutorial. Does your problem occur when the user tries to create a user account by using social sign in (i.e. he clicks the social sign in link for the first time)?

  • Pradeep Jul 18, 2014 @ 13:43

    Hi Petri,
    Nice article!!
    I have followed exactly the same steps as described here and can go to facebook login page from my apps login page (by clicking on facebook link).After fb login , the app lands back to the apps login page with the url appended with '#_=_' e.g. 'http://localhost:8080/MyApp/#_=_'.

    Actually I expected the registration page will be displayed instead.SocialUserService::loadUserByUserId() is not getting called as I put some sop there.

    Any hints?

    Best regards,
    Pradeep

    • Pradeep Jul 19, 2014 @ 12:15

      my own mistake, forgot adding /usr/register twith permitAll() in security context.
      Can see the register form now.

      • Petri Jul 20, 2014 @ 0:05

        It is good to hear that you were able to solve your problem!

        • Pradeep Jul 21, 2014 @ 17:21

          Well the user registers now,I mean registration screen comes and user details are saved to my Candidate table but UserConnection table has no entries of this new user.So looks like some configuration error still there regarding SocialUserService since it's loadUserByUserId() is still not called.

          My securitycontext.xml is:

          and social.xml is

          My databasecontext.xml has the rest:

          3 ? request.getRequestURI().split('/')[3] : 'guest'}" />

          Any hints for this problem?

          • Petri Jul 21, 2014 @ 18:24

            Wordpress ate your XML configuration but I happen to have an idea what might be the problem. You have to persist the user's connection to the UserConnection table after the registration has been successful (and the user uses social sign in). You can do this by following the instructions given in the second part of this tutorial.

            However, please note that the static handlePostSignUp method of the ProviderSignInUtils class has been deprecated. You should use the doPostSignUp() method instead.

            I hope that this solves your problem.

          • Pradeep Jul 23, 2014 @ 16:38

            That was a perfect hint!!
            Actually I have commented the call to ProviderSignInUtils.handlePostSignUp() thinking its not useful in my case.
            Thanks a lot :)

          • Petri Jul 23, 2014 @ 17:31

            You are welcome. It is good to hear that you were able to solve your problem.

  • Sanjay Jul 26, 2014 @ 8:07

    This article is not simple. It's difficult to understand so please make simple example

    • Petri Jul 26, 2014 @ 10:52

      Unfortunately I have no idea how I could create a simpler example application since I think that the example application is already pretty simple.

      However, if you let me know which parts of this blog post were hard to understand, I can try to make them easier to understand.

  • Naitik Jul 28, 2014 @ 13:37

    HI Petri,

    Logout is not working for facebook. It just redirecting to login page. How can I do logout in facebook.
    And for twitter I'm getting this error.

    org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable
    org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)

    • Petri Jul 28, 2014 @ 13:48

      Do you mean that log out function of my example application is not working, or are you trying to follow the instructions given in this blog post and cannot get the log out to work in your application?

      Also, do you mean that after the user clicks the log out link, the user is still logged in to the application and can access protected resources (such as the front page of my example application)?

      • Naitik Jul 28, 2014 @ 15:02

        yes,
        when I do click on logout button it's redirecting to login page. but when I try to open facebook.com it's directly shows me home page.(It's not asking me use name and password again) That means logut is not working properly.

        • Petri Jul 28, 2014 @ 15:27

          As far as I know, Spring Social doesn't support this. However, there are a couple of workarounds which are described in the following forum discussions:

          I hope that this answered to your question. Also, remember that you have to use similar workarounds for other social sign in providers as well.

          • Anonymous Jul 28, 2014 @ 15:48

            Thanks Petri,
            There is one more issue in my application. when I do click on signin with twitter, I am getting following error. Am I missing something??

            org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable
            org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)

          • Naitik Jul 29, 2014 @ 7:56

            Thanks Petri,
            There is one more issue in my application. when I do click on signin with twitter, I am getting following error. Am I missing something??

            org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable
            org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)

          • Naitik Jul 29, 2014 @ 9:17

            Hi Petri,

            Find the solution. I was not setting callback URL in twitter that was the problem. But when I do login in twitter and when it's successful it's redirecting me to registration form. Why is so? do I need to change my callback URL?

          • Petri Jul 29, 2014 @ 9:51

            Great! It is good to hear that you were able to solve your problem.

            The user is redirected to the registration page because either the user account or the persisted connection is not found from the database. This can be a bit confusing so I will explain it here:

            When a user "returns" to the example application after clicking a social sign button, Spring social tries to find the persisted connection from the UserConnection table.
            If the connection is not found, the user is forwarded to the registration page because the application assumes that the user doesn't have a user account yet.

            On the other hand, if the connection is found, Spring Social tries to find the correct user account by using the value of the userId column (the example application uses email address as user id). If the user is not found, the user is forwarded to the registration page.

            I hope that this answered to your question.

            By the way, if you want to get more information about the social sign in flow, you should read the second part of this tutorial.

          • Naitik Jul 29, 2014 @ 14:46

            Thanks Petri.

            Thank you for help. Project is now working properly. :)

          • Petri Jul 29, 2014 @ 22:05

            You are welcome. :)

  • Yeloon Aug 26, 2014 @ 10:58

    Hello,
    I have a problem with facebook when I turn on HTTPS for /**. When user is redirected back from Facebook site after successful login, and after granting permissions for my app. It goes back to my SocialAuthenticationFilter and attemptAuthentication method. Everythink is ok for http, but with https this method is called one more time, and the user is already authenticated (in attemptAuthService()) so it tries to addConnection but token.principal is null so entire method returns null. In the end the AuthenticationServiceException("authentication failed") is thrown and user is redirected to defaultFailureUrl. I use XML version of your config.

    I tried to force http for /auth/** and it WORKS, but i don't think it's safe to transfer tokens on unsecured channel.

    Don't know what to do :(

    • Petri Aug 26, 2014 @ 19:12

      When the user is redirected back to your web application, is the user redirected by using HTTP or HTTPS? The reason why I ask this is that I am using Spring Social in a web application that is served by using HTTPS, and the Facebook login is working correctly.

      I checked the Facebook application configuration of that web application and I noticed that I had entered the website url by using HTTPS (e.g. https://www.example.com instead of http://www.example.com). If I would be you, I would check the website url setting found from the Facebook application configuration and ensure that the website url setting has the 'https' prefix instead of 'http'.

      Let me know if this solves your problem.

    • Yeloon Aug 26, 2014 @ 20:53

      Aww... I have finally figured it out. The problem was in my social configuration. I have added authenticationSuccessHandler (SavedRequestAwareAuthenticationSuccessHandler) with useReferer=true to my socialAuthenticationFilter.

      I have done that because I have bootstrap modal dialog with login form on every page and I wanted to redirect user to the same page after authentication. I had totally forgot about that.

      • Petri Aug 26, 2014 @ 21:17

        It is good to hear that you were able to solve your problem!

  • Michael Ettlinger Aug 27, 2014 @ 21:22

    Everytime a sql-query is placed it results in a 404 Error. For example I can load the main page without problems. But if I put

    User test = userRepository.findByEmail("test")
    somewhere in the code i get the 404 Error again. Also everytime I try to do something like login -> 404. From the logs i see the sql query which works fine if I copy it into phpmyadmin. Except for this logging I se nothing.

    If I place a logging before and after the query I only see the first one. I guess the query somehow crashes and produces a 404.

    I know 404 means not found but this does not make any sense.

    What can I do? Is there a way to turn up more loggings?

    I use Glassfish with the source provided from github.

    • Petri Aug 27, 2014 @ 21:43

      I have never tried to run this with Glassfish but I can try to figure out what is going on. Which version of Glassfish are you using?

  • Ricardo Sep 5, 2014 @ 13:09

    Is it possible to override the /auth/{providerId} path?

    I need to do this because I have multiple security chains and in one of them the social login is meant to do something a bit different and also direct you to somewhere a bit different to.

    • Petri Sep 5, 2014 @ 20:50

      Hi Ricardo,

      There is a way to override the url that is processed by the social authentication filter, but you have to make your own copies of the SpringSocialConfigurer and SocialAuthenticationFilter classes. I know that this is an ugly solution but unfortunately it seems that there is no other way to do this (yet?).

      The source code of the CustomSocialAuthenticationFilter class looks as follows (check the comments for more details):

      
      public class CustomSocialAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
      	
      	//Removed irrelevant code
      	
      	public CustomSocialAuthenticationFilter(AuthenticationManager authManager, 
      								UserIdSource userIdSource, 
      								UsersConnectionRepository usersConnectionRepository, 
      								SocialAuthenticationServiceLocator authServiceLocator) {
      		//Set the url that is processed by this filter
      		super("/newurl");
      		//Removed irrelevant code
      	}
      	
      	//Removed irrelevant code
      }
      

      The source code of the CustomSpringSocialConfigurer class looks as follows:

      
      public class CustomSpringSocialConfigurer extends SecurityConfigurerAdapter {
      
      	//Removed irrelevant fields.
      	
      	public SpringSocialConfigurer() {
      	}
      	
      	@Override
      	public void configure(HttpSecurity http) throws Exception {		
      		ApplicationContext appContext = http.getSharedObject(ApplicationContext.class);
      		UsersConnectionRepository usersConnectionRepository = getDependency(
      													appContext, 
      													UsersConnectionRepository.class
      		);
      		SocialAuthenticationServiceLocator authServiceLocator = getDependency(
      													applicationContext, 
      													SocialAuthenticationServiceLocator.class
      		);
      		
      		//Removed irrelevant code
      		
      		//Create your custom filter object
      		CustomSocialAuthenticationFilter filter = new CustomSocialAuthenticationFilter(
      				http.getSharedObject(AuthenticationManager.class), 
      				userIdSource != null ? userIdSource : new AuthenticationNameUserIdSource(), 
      				usersConnectionRepository, 
      				authServiceLocator);
      				
      		//Removed irrelevant code
      	}
      
              //Removed irrelevant code
      }
      
      

      After you have created these classes, you need configure your application to use them (modify either the exampleApplicationContext-security.xml file or the SecurityContext class).

      I haven't compiled these classes yet but you probably get the idea anyway. Also, I remember that I removed some irrelevant code to make the code sample more clear. This code must be present in your CustomSocialAuthenticationFilter and CustomSpringSocialConfigurer classes.

      I hope that this answered to your question.

  • Naitik Sep 8, 2014 @ 9:59

    Hi Petri,

    I am using your demo. I have rename one table named "userconnection" to "mg_userconnection" . I have changed table named in script. But when I am redirecting to register page after social login it's throws error like this. "bad SQL grammar [select userId from UserConnection where providerId = ? and providerUserId = ?]; nested exception". My question is how can I rename that table name?

    Thanks.

    • Petri Sep 8, 2014 @ 10:36

      Hi Naitik,

      You can configure the table prefix by using setTablePrefix() method of the JdbcUsersConnectionRepository class.

      The SocialContext class implements the getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) method of the SocialConfigurer class. You can make the required modifications to this method. After you are done, the getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) method looks as follows:

      
      @Override
      public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator cfl) {
      	JdbcUsersConnectionRepository repo = new JdbcUsersConnectionRepository(
      			dataSource,
       			cfl,
       			Encryptors.noOpText()
      	);
      	repo.setTablePrefix("mg_");
      	return repo;
      }
      
      

      Now Spring Social is using the table mg_UserConnection instead of the UserConnection table. At the moment it is not possible to configure the "whole" name of this database table. In other words, if your database uses case sensitive table names, you cannot transform the name of created database table into lowercase.

  • Tiziano Sep 8, 2014 @ 15:14

    Hi Petri,
    with a little bit of customization I've this scenario:

    when a new user registered (not social) displays the phrase "You cannot create an user account because you are already logged in.". but if I try to go to the home (index.jsp) I get an internal server error, maybe because the context is wrong.

    here the code of home button: <a href="">home</a>

    but if I use different path (/upload for example) all works fine (I've a controller)

    all works fine if I logout and login again whit the login form... the problem is for new registration only.

    can you help me?

    • Petri Sep 8, 2014 @ 21:13

      Hi Tiziano,

      I tested this out by following these steps:

      1. Log in as a user that is registered by using the "normal" registration.
      2. Navigate to the registration page.
      3. I see the error message "You cannot create an user account because you are already logged in", and click the 'Home' link found from the header.

      The result is that I can see the home page in my browser. My home link looks as follows:

      
      <a href="/">
      	Home
      </a>
      
      

      However, this assumes that the application uses context path '/'. If you want to use another context path, you should create your link by using the following code:

      
      <a href="${pageContext.request.contextPath}/">
      	Home
      </a>
      
      

      Did I miss something? If so, let me know :)

      • Tiziano Sep 9, 2014 @ 11:13

        Thanks Petri,
        I forgot to tell you that I already use the contextPath tag. sorry...

        I obtain a generic error (500 error). with debug I see that creation time in Object principal (cast to UserDetails) is null inside database until I logout and login again.

        something miss in registration process?

        • Petri Sep 9, 2014 @ 20:12

          Did you remember to log the user in after the registration is completed? You should take a look at the controller method that processes the request created when the user's submits the registration form.

          If you are logging the user in after registration, could you add the stacktrace found from the log file here? It is kind of hard to say what is going on without seeing any code or a log.

  • Rituraj Sep 23, 2014 @ 6:43

    Hi Petri,

    Thanks for posting this tutorial this is really good. I used your xml configuration with web.xml . it is unable to locate the bean of userConnectionRepository and connectionFactoryLocator. Below are the error what i am getting

    Cannot resolve reference to bean 'usersConnectionRepository' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'usersConnectionRepository' is defined.

    • Petri Sep 23, 2014 @ 12:44

      Thank you for pointing this problem out. I just noticed that the XML configuration is still using Spring profiles (I removed these profiles from the Java config). If you want to use the XML configuration, you should either

      1. Remove the <beans profile="application"> element and leave the other elements intact.
      2. Set the active Spring profile to 'application'.

      I will remove the Spring profiles from the XML configuration when I have got time to do it. Again, thank you for pointing this out!

      • Anonymous Sep 28, 2014 @ 22:26

        thanks Petri for your great tutorial and quick response. I have one clarification that how user/provider is binded with registeration. i want to just persist the data and allow the user what should i do. More clear I dont want the registeration form in the case of social sign in.

        • Petri Sep 29, 2014 @ 10:04

          Hi,

          The second part of this tutorial explains how you can create a registration form that supports "normal" registration and registration via social sign in. If you have any other questions about the registration process, leave a comment to that blog post.

  • macleo Sep 26, 2014 @ 9:03

    thanks ,very usefully

    • Petri Sep 26, 2014 @ 9:37

      You are welcome! I am happy to hear that this blog post was useful to you.

  • Sona Oct 15, 2014 @ 21:40

    Hi,
    I cloned the repo from https://github.com/pkainulainen/spring-social-examples/tree/master/sign-in/spring-mvc-normal and executed the below command:
    mvn clean install
    It failed by giving the below error:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:2.6:resources (default-resources) on project spring
    -mvc-normal: Error loading property file 'D:\Personal\BACKUP\Non-Cloud\Projects\workspace\petrikainulainen-spring-social-examples-
    master\sign-in\spring-mvc-normal\profiles\dev\socialConfig.properties' -> [Help 1]
    [ERROR]

    Can you help? Thanks.

    • Petri Oct 15, 2014 @ 21:46

      Hi,

      you need to create a Facebook and a Twitter application before you can run the example application. Also, you need to create the socialConfig.properties file and configure the used social sign in providers in that file. The README of the example application provides more details about these steps.

      • Sona Oct 22, 2014 @ 10:48

        Hi Petri,

        Thanks for your prompt response. I finished first two parts of this tutorial and sincerely thank you for all your efforts in creating a top-quality example app. I am new to Java & Spring development and learned a lot by going through these two articles and the source code.

        I am able to run the app by "mvn jetty:run -P dev" now after reading the README file but facing few issues in which I need your help. I plan to create a tomcat-deployable WAR file so I did: mvn war:war -P dev, and came up with a WAR. Now things don't work as they were working earlier:

        1. Once I Log in using my FB account, the app shows me a Welcome page. When I press the Logout button on that page, it takes me to http://localhost:8080/logout instead of the logout success URL: http://localhost:8080/login.

        2. Also, if I type http://localhost:8080/spring-mvc-normal/ again after logging out, I am able to see the Welcome page. That means user is still logged in my app as well as in FB.

        3. Both problems 1 & 2 are there when I create a new normal user (without FB etc).

        4. Create user account also doesn't work now. It comes to http://localhost:8080/user/register and displays a blank page.

        I believe either the WAR is not getting created properly or Tomcat is not getting configured. Can you suggest what could the problem here? I found this link "http://maciejwalkowiak.pl/blog/2012/03/27/spring-3-1-profiles-and-tomcat-configuration/" but not sure whether it is relevant to my problem.

        Thanks once again for writing such a wonderful tutorial.

        • Petri Oct 22, 2014 @ 20:54

          I think that these problems are caused by the fact that the application assumes that it is run by using context path '/'. It seems that you are running it by using the context path '/spring-mvc-normal/'. Am I right?

          I thought that I already fixed this, but it seems that I didn't fix it after all. Thank you for pointing this out!

          I will fix the JSP pages and commit my changes to Github.

          Update: I fixed the JSP pages. You can get the working example application from Github.

          • Anonymous Oct 23, 2014 @ 8:35

            Thanks Petri, you nailed down the problem. After pulling your last commit, I was able to run the app perfectly fine from Tomcat.
            BTW, I want to know whether there was a mistake in my running the app. Is it not the right way to launch when one would deploy the app in production environment?

          • Petri Oct 23, 2014 @ 9:29

            You are welcome.

            The problem was that I didn't think that it should be possible to run this application by using other context paths than '/'. In other words, it was a bug in the application (my mistake, not yours).

  • Sona Oct 28, 2014 @ 15:13

    Hi Petri,

    I am facing one strange problem now. When I try to login / register for the first time, I don't see the "Create user account" link at the top right corner of the page. Once I log in successfully, I don't see the log out button anymore.

    I re-used your JSP pages as they are in my test app. But looks like something is missing. What do I need to effectively use "sec:authorize" in my JSP pages?

    Thanks for your help.

    • Petri Oct 29, 2014 @ 19:49

      Hi,

      The reference manual of Spring Security states that:

      This tag is used to determine whether its contents should be evaluated or not. In Spring Security 3.0, it can be used in two ways [23]. The first approach uses a web-security expression, specified in the access attribute of the tag. The expression evaluation will be delegated to the SecurityExpressionHandler<FilterInvocation> defined in the application context (you should have web expressions enabled in your <http> namespace configuration to make sure this service is available).

      Do you configure your application by using XML configuration or Java configuration?

      If you use Java configuration, you should check the source code of the SecurityContext class.

      If you use XML configuration, you should check the exampleApplicationContext-security.xml file.

      • Sona Oct 31, 2014 @ 19:39

        Hi Petri,

        I have matched the XML and JSP files many times but there is no change except the package names which are as per my application.

        During my debugging, what I realized is that none of the spring security tags present in the layout.jsp file is working. I put many debug prints in layout.jsp but nothing came up on the screen. If I do the same in other JSP files,they all show up.

        Does this ring any bell? Where have I screwed up? Sorry but since I am on the learning path, hence troubling you too much.

        Thanks.

        • Petri Oct 31, 2014 @ 20:36

          Hi Sona,

          Have you declared the Spring Security taglib in every JSP file that uses it?

          Sorry but since I am on the learning path, hence troubling you too much.

          Don't worry about this. I am happy to help.

          • Sona Dec 11, 2014 @ 20:36

            Hi Petri,

            Finally, months after reporting this issue, I found the root cause and believe me, it is one of most silly solutions I have found for my issues.

            Problem is in the filter ordering in my web.xml file. I wasn't aware that ordering plays a critical role and here sitemesh and spring security were not in order. Following thread from SO helped me in identifying this:

            http://stackoverflow.com/questions/4370629/spring-security-tags-in-sitemesh-decorator

            Thanks for all your support in debugging this :)

          • Petri Dec 11, 2014 @ 23:48

            Hi Sona,

            You are are welcome (although I think that was not able to provide you a lot of help on this matter). In any case, it is great to hear that you finally found the reason for your problem and were able solve it!

  • NewSpringLearner Oct 30, 2014 @ 9:34

    Hi Petri,
    I am very new to spring security at all and I have implemented spring security with openID authentication(Login through gmail) now I am trying spring facebook integration. For this, I have written custom class which is generic for all i.e. simple security,openId Auth and spring facebook as follows:-

    public class UserAuthenticationFilter implements UserDetailsService,AuthenticationUserDetailsService,SocialUserDetailsService {
    public UserDetails loadUserByUsername(String username)
    throws UsernameNotFoundException, DataAccessException {
    }
    public UserDetails loadUserDetails(OpenidAuthenticationToken token)
    throws UsernameNotFoundException, DataAccessException {
    }

    public SocialUserDetails loadUserByUserId(String username)
    throws UsernameNotFoundException, DataAccessException {
    }

    in this way, in above filter, I have overridden the required methods.But I am not able to execute the loadIUserByUserId method at all. I have added following code in security.xml:-

    and in jsp code is as follows
    <a href=""> Login with facebook

    Is it necessary to create the facebook app? Can u plz tell that Is It a correct way to implement this. plz give me the solution to get success on spring facebook login and plz suggest what implemtation is remaining . I am stuck on this.

    Thanks in advance

    • Petri Oct 30, 2014 @ 20:07

      Hi,

      Is it necessary to create the facebook app?

      Yes. You cannot implement a Facebook login without it because you need a valid app id and app secret. If you haven't created a Facebook application for your application, this is the reason why you your Facebook login is not working.

      Unfortunately Wordpress "ate" your XML configuration so I cannot say if there is something wrong with it. However, you can take a look at the exampleApplicationContext-security.xml file, and compare it to your security.xml file.

      I hope that this answered to your question.

      • Anonymous Oct 31, 2014 @ 14:50

        Hi Petri,
        Thanks for reply, Actually I have same xml configuaration as ur exampleApplicationContext-security.xml and exampleApplicationContext-social.xml. And I have already done data source and transactionManger like configuration in application context.xml.
        But I have some doubts and issues as follows:-
        1)I am getting this error in exampleApplicationContext-security.xml
        Line 77 in XML document from ServletContext resource [/WEB-INF/application-security.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 77; columnNumber: 65; cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'constructor-arg'
        2) We don't have created any object then why are we using the "usersConnectionRepository" this value as ref in security.xml
        plz help me to make this integration working. I am not getting clicked anyway here.

        Thanks a lot petri......

        • Petri Oct 31, 2014 @ 20:12

          Hi,

          it seems that the problem is that you haven't configured the UsersConnectionRepository bean. This bean is required because Spring Social persists the user's connection to a social service provider.

          My example application uses the JdbcUsersConnectionRepository class that persists connection data to a relational database.

          The section 2.3. Persisting Connections of the Spring Social reference manual provides more information about this.

          • NewSpringLearner Nov 5, 2014 @ 15:27

            Hi Petri,
            Can u plz tell me that how to integrate facebook login with localhost application.
            Plz help me. I am using gwt with spring and hibernate. My generated local URL is http://127.0.0.1:8888/demo

            What is the correct way to implement this? Thanks

            Thanks in advance

          • Petri Nov 5, 2014 @ 20:15

            Hi,

            I have never used GWT (Google Web Toolkit?), and unfortunately I have no idea if it is possible to integrate Spring Social with it. :(

            If you want to use Spring Social, you should use Spring MVC and follow the instructions given in my Spring Social tutorial.

  • horatius Nov 10, 2014 @ 4:45

    Excellent post for Spring MVC.

    How can we make it work for Spring MVC without ViewModel, but plain REST services that return JSON? In that case, the user probably uses some javascript based SPA that already authenticates with the SocialSignInProvider outside the MVC application and already has a token.

    • Petri Nov 10, 2014 @ 21:34

      Thank you for your kind words. I really appreciate them.

      Unfortunately I have never added social sign in to a Spring powered REST API. In other words, I don't know how you can use it with Spring MVC if your application provides only a REST API.

      I have been planning to write a separate tutorial about this for a long time. I guess now is a good time to actually do it.

  • Aniket Kulkarni Nov 11, 2014 @ 13:27

    Petri,
    One of the finest tutorial available on the internet.
    I searched a lot for spring social sign in with Google+. Your example also implements facebook and twitter
    Could you please guide or leave comment on how can I implement Google+ sign in using spring MVC?
    Again many thanks.

    • Petri Nov 12, 2014 @ 19:20

      Thank you for your kind words. I really appreciate them.

      Could you please guide or leave comment on how can I implement Google+ sign in using spring MVC?

      Unfortunately I have never done this myself :( However, I am going to update my Spring Social tutorial when I have got some free time (I don't know the exact schedule). I will add the Google sign in to my example application and add a new part to my Spring Social tutorial.

      • Anonymous Dec 3, 2014 @ 20:22

        Great tutorial ! I was able to integrate Facebook, LinkedIn and Google+ Sign-In and was able to post link on Facebook & LinkedIn. But wondering which API of google to use for the same. Any help please ?

        Also I noticed, when logging out, data from UserConnection is not getting deleted. Is it right behavior or I missed something in configuration?

        I noticed , record gets deleted when used POST /connect/facebook with delete hidden parameter like below

        <form action="" method="post">

        Spring Social Showcase is connected to your Facebook account.
        Click the button if you wish to disconnect.

        Disconnect

        • Petri Dec 3, 2014 @ 21:17

          Thank you for your kind words. I really appreciate them!

          But wondering which API of google to use for the same. Any help please ?

          There is a community project called Spring Social Google, but I haven't tried it out yet. If you want to give it a shot, you can get started by readings its reference manual.

          Also I noticed, when logging out, data from UserConnection is not getting deleted. Is it right behavior or I missed something in configuration?

          This is normal. The data found from the UserConnection table links the information received from the social sign in provider with the local user account. If you delete this link, the application cannot log you in (unless you create a new user account).

  • NewSpringlearner Nov 12, 2014 @ 15:03

    Hi Petri,
    I have implemented spring social.When I clicked on the"login with facebook" button then it is get redirected to the facebook login page successfully but now after login the facebook ,its get redirected to signup url means it is not finding the user in database.

    1) I have registered the user in my application and able to login alsoby using simple username and password without using the facebook login.

    2)But when I login through the facebook with the same user then why it is no finding that user and it is get redirected to signup url.

    First it was giving the errror as "userconnection table not exit" now I have created the userconnection table in my database.

    I have the following xml configuration :-

    --------- xml configuration------

    ----- End of xml configuration-----

    In jsp page, I have used the code like:-

    These are my all changes. Apart from this,I couldnt have implemented anything else. So please, what should I do here for the proper working of the applicaiton, my facebook login user should redirect properly to my application and data should be inserted by connect controller in "userconnection" table. I am stuck over here please highligh what should I implement now at this stage.

    Many Many thanks in advance...

    • Petri Nov 12, 2014 @ 20:24

      The reason for this is that the user who tries to log in by using a social sign in provider is not the "same" user than the user who created a user account by using the "normal" registration.

      Because the user created a user account by using the "normal" registration, he/she cannot sign in by using a social sign in provider and expect the application to identify his/her existing user account. The application cannot do this because the UserConnection table is empty.

      Also, you cannot just insert a row to this table (unless the user is creating a user account by using social sign in) because you need the information returned by the social sign in provider.

      If you need to support only Facebook, you can try to fix this by making the following changes to the controller method that renders the sign up view:

      1. Check if there already is a user account that is using the email address returned by the social sign in provider.
      2. If the user account is found, update it (if necessary), add a new row to the UserConnection table, and log the user in.
      3. If no user account is found, render the sign up view.

      Also, you have to configure Spring Social to request the user's email address when the user starts the social sign in flow by using Facebook.

      This approach has two limitations:

      • If the user isn't using the same email address on Facebook and on your application, there is no way to identify the user account.
      • If you need to support other social sign in providers, you might not be able to use this approach because all of them don't return the user's email address.

      I hope that this answered to your question.

      • NewSpringLearner Nov 13, 2014 @ 15:18

        Thank u so much Petri.
        As u suggested I tried a lot to create user connection but not work. Is there any url(signup url) through which user connection is created automatically.
        Thanks..

  • Victor Feb 3, 2015 @ 13:41

    Hi Petri,

    I tried to use the example of Maven but appeared this error in building:

    Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.16:test (default-test) on project spring-mvc-normal: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.16:test failed: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?

    Command wascmd.exe /X /C ""C:\Program Files\Java\jdk1.8.0_05\jre\bin\java" -javaagent:C:\Users\Victor\.m2\repository\org\jacoco\org.jacoco.agent.6.3.201306030806\org.jacoco.agent-0.6.3.201306030806-runtime.jar=destfile=C:\Users\Victor\Documents\spring-social-examples\sign-in\spring-mvc-normal\target\coverage-reports\jacoco-ut.exec -jar C:\Users\Victor\Documents\spring-social-examples\sign-in\spring-mvc-normal\target\surefire\surefirebooter5500528348155860158.jar C:\Users\Victor\Documents\spring-social-examples\sign-in\spring-mvc-normal\target\surefire\surefire5217935832005982224tmp C:\Users\Victor\Documents\spring-social-examples\sign-in\spring-mvc-normal\target\surefire\surefire_07294595199859845725tmp"
    -> [Help 1]

    Can you help me? Thanks

    I removed a few lines from this comment since they were irrelevant - Petri

    • Petri Feb 3, 2015 @ 17:34

      Hi,

      I noticed that you are using Java 8. I assume that the JaCoCo Maven plugin 0.6.3.201306030806 is not compatible with Java 8.

      If you don't need to code coverage reports, you can simply remove the plugin configuration. If you want to generate the code coverage reports, you should update its version to 0.7.2.201409121644.

      Let me know if this solved your problem.

  • SLP Mar 1, 2015 @ 6:34

    Hi Petri,

    Good morning !!!

    I made a small application going through your fantastic tutorials and tried hosting it using Apache & Tomcat on a professional Hosting Server. However, I am not able to access the site without having the app name in the URL. I always have to do: http://www.mydomainname.com/my-spring-app-name.

    I followed many SO posts and tutorials but no where I could find some one who is having the same environment. So finally thought of asking you as how it should be done. Details of what I have tried are captured here: http://stackoverflow.com/questions/28670450/apache-with-proxypass-and-spring-security

    Please see if you can help.

    Thanks once again for all your help.

    • Petri Mar 1, 2015 @ 18:29

      Hi,

      The easiest way to solve to solve your problem is to change the name of deployed war file to ROOT.war. When you deploy a war file called ROOT.war to Tomcat, the context path of that application is '/'. This means that you can access your application by using the url http://www.mydomainname.com.

      • SLP Mar 16, 2015 @ 9:52

        Hi Petri,

        Thanks for the suggestion. I tried that and it worked like a charm for my localhost but not for the production app running at my hosting machine. When I tried mydomainname.com, it gave me:

        Index of /

        [ICO] Name Last modified Size Description
        [IMG] favicon.ico 2015-02-26 15:54 822
        [TXT] index.html.backup 2014-12-20 10:49 603

        I checked both tomcat server.xml files and didn't find any difference. Is there something else which I am missing?

        • Petri Mar 17, 2015 @ 20:38

          It's kind of hard to say what could be wrong, but the first thing that came my mind was that your Apache might not be configured properly (it seems that is not "forwarding" requests to Tomcat). Are you using an AJP connector?

  • Onur Mar 26, 2015 @ 17:47

    Hi,

    My project run well based on Spring + Spring Security + JSF + WebFlow . Can I integrate Spring Social to my project without Spring Controler.

    Thanks in advance

  • Shashi Apr 16, 2015 @ 18:15

    Hi Petri,
    You have the best example on spring social. am trying to add 'login with facebook' on my website where form based login is already implemented. You have merged both form based and social login into one and made confusing. Is there a way you can create an example with 'login with facebook' only based on xml configuraiton?

    • Petri Apr 16, 2015 @ 20:08

      Hi Shashi,

      You have merged both form based and social login into one and made confusing

      Actually the login functions are not merged. The form login is processed by Spring Security and the social login is processed by Spring Social. However, if a user tries to sign in by using a social sign in provider and he doesn't have an user account, he has to register one by using the registration form. This process is explained in the next part of this tutorial.

      You can of course skip the registration phase and create a new user account if the user account isn't found from the database. If you want to do this, you need to modify the SignUpController class. You need to read the user's information from the request and use this information to create a new user account.

      Is there a way you can create an example with ‘login with facebook’ only based on xml configuraiton?

      The example application has XML configuration files as well.

      By the way, I will update my Spring Social tutorial later this year. I will address your concerns when I do that. For example, I plan to make this tutorial less confusing :) Thank you for the feedback!

  • 85noob May 23, 2015 @ 7:48

    Thanks for a wonder post on this! It helped me understand how spring social works quicker than the official spring social post. :)
    I wanted to add spring social feature to an Appfuse app (uses spring security) that I had been playing with. Following your 2 posts, I was trying to integrate step by step and trying to see the effect of each step.

    But I ran into a problem right immediately :

    WARN [qtp937612-50] PageNotFound.noHandlerFound(1118) | No mapping found for HTTP request with URI [/app/auth/facebook] in DispatcherServlet with name 'dispatcher'

    Can you help explain where is the "/auth/facebook" request mapped? Is this done by simply declaring a connectController bean in your SocialContext class (which I have copied)?

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

  • wojciech Jun 12, 2015 @ 18:21

    Thanks for this project, it is very good to understand social core.I only have question, there is any possibility to adapt this project in mobile or rest api ? I have problem with redirecting in process /signup for REST &( angularApp and mobileApp) ?

    • Petri Jun 12, 2015 @ 20:33

      I have never done this myself, but I think that it is doable. I tried to find information from Google, but I couldn't find anything interesting. My next step was to ask help from my Twitter followers. I hope that someone can shed some light on this problem.

      Update: It seems that your only option is to do a normal GET request and let the backend handle the authentication dance.

      • wojciech Jun 23, 2015 @ 12:29

        And how to send response to android or rest api after this dance ?

        • Mova Jan 19, 2016 @ 2:29

          Hi Wojciech and Petri, did you fix this problem i have the same many thanks!

          • Petri Jan 20, 2016 @ 21:34

            Hi Mova,

            Unfortunately your best option is to do a normal GET request and let the backend handle the authentication dance. However, that doesn't solve your problem because you still need to respond to the client after the dance is complete. I have one idea that might help you to do this:

            The easiest way to solve this to create two controller methods which handle failed sign in attempt and successful sign in. Implement these controller methods by setting the preferred HTTP response code to the HTTP response. After you have implemented these controller methods, you have to configure Spring Social to redirect the request to the correct url.

            If you use Java configuration, you can do this by setting the values of the postLoginUrl and postFailureUrl fields of the SpringSocialConfigurer class.

            If you use XML configuration, you can do this by setting the values of the postLoginUrl and postFailureUrl fields of the SocialAuthenticationFilter filter class. If you don't have any idea how to do this, check out the XML configuration file of my example application. It should help you to get started.

            Did this answer to your comment?

  • shashwat Jul 9, 2015 @ 0:16

    hi petri,

    I tried the first part of this tutorial using xml configurations, however i am getting the following error..

    No qualifying bean of type [com.project.service.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

    could you please help me out in this, it seems to be an autowiring or dependency injection issue also is there any implementation of UserRepository that we have to write.

    thanks,
    shashwat

    Update: I removed the stack trace since the error message gave enough information about the problem - Petri

    • Petri Jul 9, 2015 @ 0:34

      Hi Shashwat,

      The example application uses Spring Data JPA, and the UserRepository is the repository that is used to manage user information.

      It seems that you have changed the package hierarchy of the project because old package of the UserRepository interface was: net.petrikainulainen.spring.social.signinmvc.user.repository. This is why Spring Data JPA cannot create the UserRepository bean.

      You can solve this problem by configuring Spring Data JPA to use the correct package. You can do this by changing the value of the jpa:repositories element's base-package attribute. You can find the persistence layer configuration from the exampleApplicationContext-persistence.xml file.

      Also, if you are not familiar with Spring Data JPA, you should take a look at my Spring Data JPA tutorial.

      If have any further questions, don't hesitate to ask them.

      • Anonymous Jul 9, 2015 @ 9:43

        Hey Petri,
        thanks for a quick revert. So I get the issue, you are using jpa repository. But the main problem i m facing is that i am using hibernate in my whole application and it would be difficult to migrate the whole app to spring data jpa to just implement a login functionality. Could you please help me with the changes that i will have to do in case i have to implement it in hibernate.

        I m attaching below my dao setup below which uses a jndi resource. Any help would be appreciated.

        com.myproject.pojo.*

        org.hibernate.dialect.MySQL5InnoDBDialect
        false
        false
        true
        true
        true
        false
        false
        org.joda.time.contrib.hibernate.PersistentDateTime

        java:comp/env/jdbc/myproject

        regards,
        shashwat

        • Petri Jul 9, 2015 @ 10:21

          Hi,

          It is actually quite easy to get rid of Spring Data JPA. You need to create a Hibernate repository class that is used to handle user information (or you can use an existing repository) and ensure that the repository implements these methods:

          • The User findByEmail(String email) method returns the user whose email address is given as a method parameter. If no use is found, it returns null. This method is invoked when the user logs in to the system or creates a new user account.
          • The User save(User saved) method saves the information of the User object given as a method parameter and returns the saved object. This method is invoked when a user creates a new user account.

          If you have any other questions, feel free to ask them.

          • shashwat Jul 9, 2015 @ 11:52

            thanks petri,
            got it working, will be moving to part 2 of this tutorial, will let you know if i get stuck anywhere.

          • Petri Jul 9, 2015 @ 12:01

            Hi Shashwat,

            You are welcome! It is nice to hear that you were able to solve your problem.

  • Viral Jul 13, 2015 @ 15:23

    Hi Petri,
    I have integrated spring security with spring social using your example code , configuration is same as you provided in your github code.However after calling /auth/twitter it goes to twitter sigin page and after that it authenticates and redirects back to my login page.What can be the reason for this?
    I am using the latest version of spring, spring-security and spring-social.

    • Petri Jul 13, 2015 @ 17:05

      Hi Viral,

      I have a couple of ideas:

      First, check that the callback url of your Twitter application is correct.

      Second, Does this happen when the user clicks the "Sign in With Twitter" link for the first time? If so, one possible reason for this is that Spring Social cannot find the persisted connection from the UserConnection table. When this happens, it will redirect user to the sign up page (see this discussion). Also, if the user account is not found the database, the user is redirected to the sign up page.

      Do you use your login page as the sign up page?

      • Viral Jul 14, 2015 @ 11:37

        Hi Petri ,
        Thanks for Your help.
        It worked ,I was Sign in With Twitter for the first time .Also I had changed the spring social version to 1.1.2 Release ,ProviderSignInUtils class is getting error in 1.1.2 .It is working fine in 1.1.0 Release .

        • Petri Jul 14, 2015 @ 11:47

          It seems that the Spring Social team did some major changes to the ProviderSignInUtils class between Spring Social 1.1.0 and 1.1.2. Anyway, another reader had the same problem, and I posted the solution here.

  • Protazy Sep 23, 2015 @ 20:45

    Are you planning to update the tutorial to version 2.0.x of spring.social.facebook? There are big changes there, for example, there is no default constructor for ProviderSignInUtils. I am currently struggling with updating my code to version 2.0.x.

    • Petri Sep 25, 2015 @ 12:07

      I would love to do it right now, but I am afraid that I won't be able to do it until next year because I need to update two older tutorials before I can move on to this one.

      I took a quick look at the Javadoc of the ProviderSignInUtils class and noticed that it has a constructor which takes ConnectionFactoryLocator and UsersConnectionRepository objects as constructor arguments. You could simply inject these beans to the component that uses the ProviderSignInUtils class and pass them as constructor arguments when you create a new ProviderSignInUtils object.

      If you have any other questions, don't hesitate to ask them!

  • Vinodh Dec 2, 2015 @ 13:06

    Hi Petri Kainulainen,
    How can I workout with mongoDB having this set of example, please help me out..

  • Laxman Dec 31, 2015 @ 12:35

    hi Petri,

    I am getting error in POM.xml when I import your project in Eclipse Mars IDE:
    Plugin execution not covered by lifecycle configuration: org.jacoco:jacoco-maven-plugin:0.6.3.201306030806:prepare-
    agent (execution: pre-unit-test, phase: initialise)
    regards,
    Laxman

    • Petri Dec 31, 2015 @ 21:58

      Hi,

      You can fix this by removing the JaCoCo Maven Plugin from the pom.xml file.

  • SLi Mar 20, 2016 @ 6:20

    for those who is also struggle about the Auth setScope issue mentioned at http://www.petrikainulainen.net/programming/spring-framework/adding-social-sign-in-to-a-spring-mvc-web-application-configuration/#comment-453154

    Pls update spring-social-config to later version (1.1.2.REALEASE), you should be fine.

    • Petri Mar 21, 2016 @ 9:45

      Hi,

      Thank you for sharing! This is a quite common use case, and that is why it is great to find out how I can solve this problem.

  • Jay Apr 2, 2016 @ 18:36

    Hi Petri,

    I have few questions regarding this tutorial. I am trying to have only 'login with facebook' as the way users can signIn to the application.

    Questions:
    1. When would user get a session Id, if user tries to login with facebook?
    2. Spring Social document says to have a schema for UserConnections table. So when does Spring adds a particular entry (user) to this table ?

    • Petri Apr 3, 2016 @ 15:13

      Hi Jay,

      1. When would user get a session Id, if user tries to login with facebook?

      The user gets a session id when he/she opens the first page of your application. Spring Security can create a new session for him/her after login if you have specified it to do so.

      2. Spring Social document says to have a schema for UserConnections table. So when does Spring adds a particular entry (user) to this table ?

      You need to insert a new row into this table by using the ProviderSignInUtils class.

      If you want get more information about this, check out the next part of my Spring Social tutorial.

  • Prabhu Apr 4, 2016 @ 16:50

    Hi Petri,
    I have deployed the project into amazon aws but it is not working fine. sometimes not able to get repsonse from auth/facebook. getting exception "Page has too many redirection" but all the functionalities are working fine in local tomcat.

    Need suggestion..

    • Petri Apr 18, 2016 @ 18:35

      I think that this is an AWS specific problem. Unfortunately I don't know what the problem is :(

  • Morteza Apr 18, 2016 @ 9:39

    Dear my friends,

    I need sample project that use spring MVC framework + restful and use OAuth 2 and use MYSQL database if some body can help me please email to me,thank you in advance.

  • Anonymous Apr 20, 2016 @ 13:02

    Dear Petri,

    when i want to run this project with wildfly i have this error can you help me.

    org.springframework.social.config.annotation.SocialConfiguration.connectionFactoryLocator()] threw exception; nested exception is java.lang.IllegalArgumentException: Circular placeholder reference 'twitter.consumer.key' in property definitions

    Update: I removed the irrelevant part of the stack trace - Petri

    • Petri Apr 20, 2016 @ 21:57

      Hi,

      How did you create the war file? The reason why I ask this is that Maven should replace the property placeholders found from the properties file with the values found from the profile specific configuration file. However, the error message of the thrown IllegalArgumentException states that this did not happen.

  • Morteza Apr 23, 2016 @ 8:29

    Dear Petri,

    How should i create the war file i run it in Intellij Idea and make the artifact and configure it but this error happened when i select each of AuthServer and RestServer.

    • Morteza Apr 23, 2016 @ 9:52

      ERROR [org.springframework.web.servlet.DispatcherServlet] (MSC service thread 1-3) Context initialization failed: java.lang.IllegalArgumentException
      at org.springframework.asm.ClassReader.(Unknown Source) [spring-core-3.2.1.RELEASE.jar:3.2.1.RELEASE]
      at org.springframework.asm.ClassReader.(Unknown Source) [spring-core-3.2.1.RELEASE.jar:3.2.1.RELEASE]
      at org.springframework.asm.ClassReader.(Unknown Source) [spring-core-3.2.1.RELEASE.jar:3.2.1.RELEASE]

    • Morteza Apr 23, 2016 @ 14:33

      Dear Petri,

      Can you tell me how to run this project in Intellij Idea and with wildfly application server with screen shot,thank you in advance.

      • Petri Apr 26, 2016 @ 20:28

        I don't know how you can run this application with IntelliJ Idea and Wildfly because I have never used Wildfly. However, you should be able to run it as long as you have:

        1. Created Facebook and Twitter applications for this application (Check README).
        2. Configured the application correctly (check README).
        3. Initialized the MySQL database (check README).

        Also, keep in mind that you have to create the deployed .war file by running the package Maven goal by using the dev Maven profile. You can configure IntelliJ Idea to invoke a Maven goal before it starts the application server.

  • Morteza Apr 26, 2016 @ 15:34

    Hi Petri,

    Can you tell me this project how to work with Twitter and Facebook.

    • Morteza Apr 26, 2016 @ 15:47

      and i want work this with linkedin and google too.

    • Petri Apr 26, 2016 @ 20:31

      Hi Morteza,

      The example application should work with Facebook and Twitter as long as you have configured it properly (check my previous comment).

      These projects provide support for Google and LinkedIn:

      The example application doesn't support them at the moment. This means that you have to make some minor configuration changes to the application. These changes are explained in the reference manuals of these projects. Also, you need to add the sign in links to the login page and add the new providers to the SocialMediaService enum.

      • Morteza Apr 30, 2016 @ 7:54

        Dear Petri,

        I have this error when click the link of facebook (Invalid App ID: foo) and this error when i click the link of twitter

        org.springframework.web.client.HttpClientErrorException: 401 Authorization Required
        org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
        org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:576)
        org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:532)
        org.springframework.web.client.RestTemplate.execute(RestTemplate.java:504)
        org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:449)
        org.springframework.social.oauth1.OAuth1Template.exchangeForToken(OAuth1Template.java:187)
        org.springframework.social.oauth1.OAuth1Template.fetchRequestToken(OAuth1Template.java:115)

        what i have to do and i configure the Twitter as you said.

        • Petri May 4, 2016 @ 22:17

          Did you create your own Facebook and Twitter applications? The error messages suggest that the configuration file (socialConfig.properties) which should contain the real API credentials provided by Facebook and Twitter contains my placeholders (foo and bar).

          • Morteza May 7, 2016 @ 10:13

            Yes,I create my own Twitter applications and above error has happened.

          • Petri May 17, 2016 @ 19:29

            Did you configure the domains that are allowed to access the application?

          • Morteza May 23, 2016 @ 11:38

            how to configure domainds?

          • Petri May 23, 2016 @ 18:36

            Hi,

            Unfortunately I don't remember the details anymore, but if I remember correctly, you should be able to configure the domains in the settings of your Twitter and Facebook applications.

  • Hi May 27, 2016 @ 14:31

    Hi,
    I am P V REDDY.I am Senior Software Engineer.What I have to in our Project is I need authenticate Either Email Id or Phone Number with OTP or 3 Questions and Answers before Login into the Web application in Spring MVC .
    I need some reference and also I need some api's

  • Morteza May 30, 2016 @ 11:43

    Dear Petri,

    When i use Google+ and configure with this application and click the button of Google+ redirect me to the page with this error:

    400. That’s an error.

    Error: invalid_request

    Missing required parameter: scope

    Learn more

    Request Details
    That’s all we know.

    • Petri May 30, 2016 @ 22:53

      Hi,

      It seems that you need to specify the value of the scope parameter. Take a look at this StackOverflow answer. It explains how you can the add the scope parameter in your sign in form.

  • Swapnil Sep 26, 2016 @ 8:02

    Hi Petri,
    I am trying to use social login in my current Spring project. I have added the dependencies, but when I build the project, I am not able to see the /connect url mapped logs in the console.

    • Petri Sep 27, 2016 @ 18:12

      Unfortunately it's impossible to say what is going on without running your code. Do have a sample project that reproduces this problem?

  • Sujit Feb 5, 2017 @ 18:14

    Superb Post. Thanks a lot

    • Petri Feb 7, 2017 @ 17:12

      You are welcome.

  • Akshay May 9, 2017 @ 14:07

    Hi

    I imported the code from Github. And i had maven clean install. But when i run the code using this path url in the browser...
    http://localhost:8080/spring-mvc-normal/login
    I get 404 Error like this ........ What is the reason ?
    HTTP ERROR 404
    Problem accessing /spring-mvc-normal/login. Reason:
    NOT_FOUND

    • Petri May 9, 2017 @ 18:44

      The 404 error means that the page is not found. Are you running the web application by using Jetty Maven plugin or do you use some other servlet container?

      • Akshay May 11, 2017 @ 10:21

        Yes , I am running the web application using Jetty server

        • Petri May 19, 2017 @ 18:37

          Hmm. I have to admit that I don't know what is wrong :( By the way, are you using Java 8? If I remember correctly, the example application doesn't work with Java 8 because it uses a Spring version that doesn't support Java 8.

Leave a Reply