Table of Contents
How to Fix Spring-Social Facebook one user per application problem.
Problem
What is the cause of this problem?
Spring Boot autoconfigures a lot of things behind the scenes. It does autoconfigure the Facebook, LinkedIn and Twitter properties and sets up the connection factories for social providers. However, the implementation of UserIdSource always returns “anonymous” as the user ID. Once the first Facebook connection is established the second browser will try to find a connection for “anonymous” which it finds and gives you an authorised Facebook object.
Here is the culprit code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Configuration @EnableSocial @ConditionalOnWebApplication @ConditionalOnMissingClass("org.springframework.security.core.context.SecurityContextHolder") protected static class AnonymousUserIdSourceConfig extends SocialConfigurerAdapter { @Override public UserIdSource getUserIdSource() { return new UserIdSource() { @Override public String getUserId() { return "anonymous"; } }; } } |
Solution
The solution is to override the “anonymous” as the UserId for each new user/session. So for each session, we can simply return a SessionID, however, it may not be unique enough to identify users, especially if it’sh being cached or stored somewhere in a connection database.
Using a Universally Unique Identifier(UUID) would be a safer bet.So we will store a new UUID in session so it persists between different requests but is alive only till the session is valid. See the below method which does the trick.
1 2 3 4 5 6 7 8 9 10 11 12 | @Override public String getUserId() { RequestAttributes request = RequestContextHolder.currentRequestAttributes(); String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION); if (uuid == null) { uuid = UUID.randomUUID().toString(); request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION); } return uuid; } |
The Complete Code
You will need to create a class say Socialconfig and make sure it is available in the classpath (src/main/java/).Find below the complete code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import java.util.UUID; import org.springframework.context.annotation.Configuration; import org.springframework.social.UserIdSource; import org.springframework.social.config.annotation.SocialConfigurerAdapter; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; @Configuration public class SocialConfig extends SocialConfigurerAdapter { @Override public UserIdSource getUserIdSource() { return new SessionIdUserIdSource(); } private static final class SessionIdUserIdSource implements UserIdSource { @Override public String getUserId() { RequestAttributes request = RequestContextHolder.currentRequestAttributes(); String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION); if (uuid == null) { uuid = UUID.randomUUID().toString(); request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION); } return uuid; } } } |
Follow this Video