6 date: "2016-01-25T13:43:26+00:00"
7 guid: http://juplo.de/?p=613
19 title: 'Develop a Facebook-App with Spring-Social – Part III: Implementing a UserIdSource'
20 url: /develop-a-facebook-app-with-spring-social-part-03-implementing-a-user-id-source/
23 In this series of Mini-How-Tow's I will describe how to develop a facebook app with the help of [Spring-Social](http://projects.spring.io/spring-social/ "Learn more about Spring-Social")
25 In [the last part of this series](/develop-a-facebook-app-with-spring-social-part-02-how-spring-social-works/ "Read part 2 of this series, to understand, why the first example cannot work as a real app!"), I explained, why the nice little example from the Getting-Started-Guide " [Accessing Facebook Data](http://spring.io/guides/gs/accessing-facebook/ "Read the official Getting-Started-Guide")" cannot function as a real facebook-app.
27 In this part, we will try to solve that problem, by implementing a `UserIdSource`, that tells Spring Social, which user it should connect to the API.
29 ## The Source is With You
31 You can find the source-code on [/git/examples/facebook-app/](/git/examples/facebook-app/ "Link for cloning")
32 and [browse it via gitweb](/gitweb/?p=examples/facebook-app;a=summary "Browse the source-code now").
33 Check out `part-03` to get the source for this part of the series.
35 ## Introducing `UserIdSource`
37 The `UserIdSource` is used by Spring Social to ask us, which user it should connect with the social net.
38 Clearly, to answer that question, we must remeber, which user we are currently interested in!
40 ## Remember Your Visitors
42 In order to remember the current user, we implement a simple mechanism, that stores the ID of the current user in a cookie and retrieves it from there for subsequent calls.
43 This concept was borrowed — again — from [the official code examples](https://github.com/spring-projects/spring-social-samples "Clone the official code examples from GitHub").
44 You can find it for example in the [quickstart-example](https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-quickstart "Clone the quickstart-example from GitHub").
46 **It is crucial to stress, that this concept is inherently insecure and should never be used in a production-environment.**
47 As the ID of the user is stored in a cookie, an attacker could simply take over control by sending the ID of any currently connected user, he is interested in.
49 The concept is implemented here only for educational purposes.
50 It will be replaced by Spring Security later on.
51 But for the beginning, it is easier to understand, how Spring Social works, if we implement a simple version of the mechanism ourself.
53 ## Pluging in Our New Memory
55 The internals of our implementation are not of interest.
56 You may explore them by yourself.
57 In short, it stores the ID of each new user in a cookie.
58 By inspecting that cookie, it can restore the ID of the user on subsequent calls.
60 What is from interest here is, how we can plug in this simple example-mechanism in Spring Social.
62 Mainly, there are two hooks to do that, that means: two interfaces, we have to implement:
65 Spring Social uses an instance of this interface to ask us, which users authorizations it should load from its persistent store of user/connection-mappings.
66 We already have seen an implementation of that one in [the last part of our series](develop-a-facebook-app-with-spring-social-part-02-how-spring-social-works/#AnonymousUserIdSource "Jump back to the last part of our series").
68 1. **ConnectionSignUp**:
69 Spring Social uses an instance of this interface, to ask us about the name it should use for a new user during sign-up.
73 The implementation of `ConnectionSignUp` simply uses the ID, that is provided by the social network.
74 Since we are only signing in users from Facebook, these ID's are guaranteed to be unique.
77 public class ProviderUserIdConnectionSignUp implements ConnectionSignUp
80 public String execute(Connection connection)
82 return connection.getKey().getProviderUserId();
88 The implementation of `UserIdSource` retrieves the ID, that was stored in the `SecurityContext` (our simple implementation — not to be confused with the class from Spring Security).
89 If no user is stored in the `SecurityContext`, it falls back to the old behavior and returns the fix id `anonymous`.
92 public class SecurityContextUserIdSource implements UserIdSource
94 private final static Logger LOG =
95 LoggerFactory.getLogger(SecurityContextUserIdSource.class);
98 public String getUserId()
100 String user = SecurityContext.getCurrentUser();
103 LOG.debug("found user \"{}\" in the security-context", user);
107 LOG.info("found no user in the security-context, using \"anonymous\"");
118 To replace the `AnonymousUserIdSource` by our new implementation, we simply instantiate that instead of the old one in our configuration-class `SocialConfig`:
122 public UserIdSource getUserIdSource()
124 return new SecurityContextUserIdSource();
129 There are several ways to plug in the `ConnectionSignUp`.
130 I decided, to plug it into the instance of `InMemoryUsersConnectionRepository`, that our configuration uses, because this way, the user will be signed up automatically on sign in, if it is not known to the application:
134 public UsersConnectionRepository getUsersConnectionRepository(
135 ConnectionFactoryLocator connectionFactoryLocator
138 InMemoryUsersConnectionRepository repository =
139 new InMemoryUsersConnectionRepository(connectionFactoryLocator);
140 repository.setConnectionSignUp(new ProviderUserIdConnectionSignUp());
146 This makes sense, because our facebook-app uses Facebook, to sign in its users, and, because of that, does not have its own user-model.
147 It can just reuse the user-data provided by facebook.
149 The other approach would be, to officially sign up users, that are not known to the app.
150 This is achieved, by redirecting to a special URL, if a sign-in fails, because the user is unknown.
151 These URL then presents a formular for sign-up, which can be prepopulated with the user-data provided by the social network.
152 You can read more about this approach in the [official documentation](http://docs.spring.io/spring-social/docs/1.1.4.RELEASE/reference/htmlsingle/#signing-up-after-a-failed-sign-in "Read more on signing up after a faild sign-in in the official documentation").
156 So, let us see, if our refinement works. Run the following command and log into your app with at least two different users:
159 git clone /git/examples/facebook-app/
162 mvn spring-boot:run \
163 -Dfacebook.app.id=YOUR_ID \
164 -Dfacebook.app.secret=YOUR_SECRET \
165 -Dlogging.level.de.juplo.yourshouter=debug
169 (The last part of the command turns on the `DEBUG` logging-level, to see in detail, what is going on.
171 ## But What The \*\#! Is Going On There?!?
173 **Unfortunately, our application shows exactly the same behavior as, before our last refinement.**
176 If you run the application in a debugger and put a breakpoint in our implementation of `ConnectionSignUp`, you will see, that this code is never called.
177 But it is plugged in in the right place and should be called, if _a new user signs in_!
179 The solution is, that we are using the wrong mechanism.
180 We are still using the `ConnectController` which was configured in the simple example, we extended.
181 But this controller is meant to connect a _known user_ to one or more _new social services_.
182 This controller assumes, that the user is already signed in to the application and can be retrieved via the configured `UserIdSource`.
184 **To sign in a user to our application, we have to use the `ProviderSignInController` instead!**
188 In [the next part](/develop-a-facebook-app-with-spring-social-part-04-signing-in-users "Jump to the next part of this series and read on...") of this series, I will show you, how to change the configuration, so that the `ProviderSignInController` is used to sign in (and automatically sign up) users, that were authenticated through the Graph-API from Facebook.
190 ## Funded by the Europian Union
192 This article was published in the course of a
193 [resarch-project](http://yourshouter.com/projekte/crowdgest%C3%BCtzte-veranstaltungs-suchmaschine.html "Show details about the funded resarch-project"),
194 that is funded by the European Union and the federal state Northrhine-Wetphalia.
196 [](http://yourshouter.com/projekte/crowdgest%C3%BCtzte-veranstaltungs-suchmaschine.html "Show details about the funded resarch-project")