Develop a Facebook-App with Spring-Social – Part IV: Signing In Users

In this series of Mini-How-Tow’s I will describe how to develop a facebook app with the help of Spring-Social

In the last part of this series, we tried to teach Spring Social how to remember our signed in users and learned, that we have to sign in a user first.

In this part, I will show you, how you sign (and automatically sign up) users, that are authenticated via the Graph-API.

The Source is With You

You can find the source-code on http://juplo.de/git/examples/facebook-app/ and browse it via gitweb. Check out part-04 to get the source for this part of the series.

In Or Up? Up And In!

In the last part of our series we ran in the problem, that we wanted to connect several (new) users to our application. We tried to achieve that, by extending our initial configuration. But the mistake was, that we tried to connect new users. In the world of Spring Social we can only connect a known user to a new social service.

To know a user, Spring Social requires us to sign in that user. But again, if you try to sign in a new user, Spring Social requires us to sign up that user first. Because of that, we had already implemented a ConnectionSignUp and configured Spring Social to call it, whenever it does not know a user, that was authenticated by Facebook. If you forget that (or if you remove the according configuration, that tells Spring Social to use our ConnectionSignUp), Spring Social will redirect you to the URL /signup — a Sign-Up page you have to implement — after a successfull authentication of a user, that Spring Social does not know yet.

The confusion — or, to be honest, my confusion — about sign in and sign up arises from the fact, that we are developing a Facebook-Application. We do not care about signing up users. Each user, that is known to Facebook — that is, who has signed up to Facebook — should be able to use our application. An explicit sign-up to our application is not needed and not wanted. So, in our use-case, we have to implement the automatically sign-up of new users. But Spring Social is designed for a much wider range of use cases. Hence, it has to distinguish between sign-in and sign-up.

Implementation Of The Sign-In

Spring Social provides the interface SignInAdapter, that it calls every time, it has authenticated a user against a social service. This enables us, to be aware of that event and remember the user for subsequent calls. Our implementation stores the user in our SecurityContext to sign him in and creates a cookie to remember him for subsequent calls:

public class UserCookieSignInAdapter implements SignInAdapter
{
  private final static Logger LOG =
      LoggerFactory.getLogger(UserCookieSignInAdapter.class);


  @Override
  public String signIn(
      String user,
      Connection connection,
      NativeWebRequest request
      )
  {
    LOG.info(
        "signing in user {} (connected via {})",
        user,
        connection.getKey().getProviderId()
        );
    SecurityContext.setCurrentUser(user);
    UserCookieGenerator
        .INSTANCE
        .addCookie(usSigning In Userser, request.getNativeResponse(HttpServletResponse.class));

    return null;
  }
}

It returns null, to indicate, that the user should be redirected to the default-URL after an successful sign-in. This URL can be configured in the ProviderSignInController and defaults to /, which matches our use-case. If you return a string here, for example /welcome.html, the controller would ignore the configured URL and redirect to that URL after a successful sign-in.

Configuration Of The Sign-In

To enable the Sign-In, we have to plug our SignInAdapter into the ProviderSignInController:

@Bean
public ProviderSignInController signInController(
    ConnectionFactoryLocator factoryLocator,
    UsersConnectionRepository repository
    )
{
  ProviderSignInController controller = new ProviderSignInController(
      factoryLocator,
      repository,
      new UserCookieSignInAdapter()
      );
  return controller;
}

Since we are using Spring Boot, an alternative configuration would have been to just create a bean-instance of our implementation named signInAdapter. Then, the auto-configuration of Spring Boot would discover that bean, create an instance of ProviderSignInController and plug in our implementation for us. If you want to learn, how that works, take a look at the implementation of the auto-configuration in the class SocialWebAutoConfiguration, lines 112ff.

Run it!

If you run our refined example and visit it after impersonating different facebook-users, you will see that everything works as expected now. If you visit the app for the first time (after a restart) with a new user, the user is signed up and in automatically and a cookie is generated, that stores the Facebook-ID of the user in the browser. On subsequent calls, his ID is read from this cookie and the corresponding connection is restored from the persistent store by Spring Social.

Coming Next…

In the next part of this little series, we will move the redirect-if-unknown logic from our HomeController into our UserCookieInterceptor, so that the behavior of our so-called “security”-concept more closely resembles the behavior of Spring Security. That will ease the migration to that solution in a later step.

Perhaps you want to skip that, rather short and boring step and jump to the part after the next, that explains, how to sign in users by the signed_request, that Facebook sends, if you integrate your app as a canvas-page.

Funded by the Europian Union

This article was published in the course of a resarch-project, that is funded by the European Union and the federal state Northrhine-Wetphalia.

Europäische Union: Investitionen in unsere Zukunft - Europäischer Fonds für regionale Entwicklung EFRE.NRW 2014-2020: Invesitionen in Wachstum und Beschäftigung

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>