Turning the app into a pure Facebook-App
[examples/facebook-app] / src / main / java / de / juplo / yourshouter / SocialConfig.java
1 package de.juplo.yourshouter;
2
3
4
5 import javax.inject.Inject;
6 import javax.sql.DataSource;
7 import org.apache.http.HttpRequestFactory;
8 import org.springframework.context.annotation.Bean;
9 import org.springframework.context.annotation.Configuration;
10 import org.springframework.context.annotation.Scope;
11 import org.springframework.context.annotation.ScopedProxyMode;
12 import org.springframework.social.UserIdSource;
13 import org.springframework.core.env.Environment;
14 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
15 import org.springframework.security.core.context.SecurityContext;
16 import org.springframework.security.crypto.encrypt.Encryptors;
17 import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
18 import org.springframework.social.config.annotation.EnableSocial;
19 import org.springframework.social.config.annotation.SocialConfigurerAdapter;
20 import org.springframework.social.connect.Connection;
21 import org.springframework.social.connect.ConnectionFactoryLocator;
22 import org.springframework.social.connect.ConnectionRepository;
23 import org.springframework.social.connect.ConnectionSignUp;
24 import org.springframework.social.connect.UsersConnectionRepository;
25 import org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository;
26 import org.springframework.social.connect.web.ConnectController;
27 import org.springframework.social.connect.web.SignInAdapter;
28 import org.springframework.social.facebook.api.Facebook;
29 import org.springframework.social.facebook.connect.FacebookConnectionFactory;
30 import org.springframework.social.facebook.web.CanvasSignInController;
31
32
33 /**
34  * Spring Social Configuration.
35  *
36  * @author Kai Moritz
37  */
38 @Configuration
39 @EnableSocial
40 public class SocialConfig extends SocialConfigurerAdapter
41 {
42   @Inject
43   DataSource dataSource;
44   @Inject
45   ConnectionSignUp connectionSignUp;
46   @Inject
47   SignInAdapter signInAdapter;
48
49
50   /**
51    * Add a {@link FacebookConnectionFactory} to the configuration.
52    * The factory is configured through the keys <code>facebook.app.id</code>
53    * and <code>facebook.app.secret</code>.
54    *
55    * @param config
56    * @param env 
57    */
58   @Override
59   public void addConnectionFactories(
60       ConnectionFactoryConfigurer config,
61       Environment env
62       )
63   {
64     config.addConnectionFactory(
65         new FacebookConnectionFactory(
66             env.getProperty("facebook.app.id"),
67             env.getProperty("facebook.app.secret")
68             )
69         );
70   }
71
72   /**
73    * {@inheritDoc}
74    *
75    * Configure an instance of {@link JdbcUsersConnection} as persistent
76    * store of user/connection-mappings.
77    * <p>
78    * The app-secret is reused as password for the encryption of the data.
79    * The salt can be changed in the <code>pom.xml</code>
80    * <p>
81    * This does only work, if you have the Java Crypto Extension (JCE) in
82    * full strength version, since Spring Security is using a 256-bit key.
83    *
84    * @see http://stackoverflow.com/a/17637354
85    */
86   @Override
87   public UsersConnectionRepository getUsersConnectionRepository(
88       ConnectionFactoryLocator connectionFactoryLocator
89       )
90   {
91     JdbcUsersConnectionRepository repository =
92         new JdbcUsersConnectionRepository(
93             dataSource,
94             connectionFactoryLocator,
95             Encryptors.noOpText()
96             );
97     repository.setConnectionSignUp(connectionSignUp);
98     return repository;
99   }
100
101   /**
102    * Configure our new implementation of {@link UserIdSource}, that retrieves
103    * the current user from the {@link SecurityContext}.
104    *
105    * @return
106    *     An instance of {@link AnonymousUserIdSource}.
107    *
108    * @see {@link SecurityContextUserIdSource}
109    * @see {@link SecurityContext}
110    * @see {@link UserCookieInterceptor}
111    */
112   @Override
113   public UserIdSource getUserIdSource()
114   {
115     return new SpringSecurityContextUserIdSource();
116   }
117
118
119   /**
120    * Configuration of the controller, that handles the authorization against
121    * the Facebook-API, to connect a user to Facebook.
122    *
123    * At the moment, no special configuration is needed.
124    *
125    * @param factoryLocator
126    *     The {@link ConnectionFactoryLocator} will be injected by Spring.
127    * @param repository
128    *     The {@link ConnectionRepository} will be injected by Spring.
129    * @return
130    *     The configured controller.
131    */
132   @Bean
133   public ConnectController connectController(
134       ConnectionFactoryLocator factoryLocator,
135       ConnectionRepository repository
136       )
137   {
138     ConnectController controller =
139         new ConnectController(factoryLocator, repository);
140     return controller;
141   }
142
143   /**
144    * Configure the {@link CanvasSignInController} to enable sign-in through
145    * the <code>signed_request</code>, that Facebook sends to the canvas-page.
146    *
147    * @param factoryLocator The {@link ConnectionFactoryLocator} will be injected by Spring.
148    * @param repository The {@link UserConnectionRepository} will be injected by Spring.
149    * @param env The {@link Environment}, to read additional parameters from.
150    * @return The configured {@link CanvasSignInController}
151    */
152   @Bean
153   public CanvasSignInController canvasSignInController(
154       ConnectionFactoryLocator factoryLocator,
155       UsersConnectionRepository repository,
156       Environment env
157       )
158   {
159     return
160         new CanvasSignInController(
161             factoryLocator,
162             repository,
163             signInAdapter,
164             env.getProperty("facebook.app.id"),
165             env.getProperty("facebook.app.secret"),
166             env.getProperty("facebook.app.canvas")
167             );
168   }
169
170   /**
171    * Configure a scoped bean named <code>facebook</code>, that enables
172    * access to the Graph-API in the name of the current user.
173    *
174    * @param repository
175    *     The {@link ConnectionRepository} will be injected by Spring.
176    * @return
177    *     A {@Connection<Facebook>}, that represents the authorization of the
178    *     current user against the Graph-API, or <code>null</code>, if the
179    *     current user is not connected to the API.
180    */
181   @Bean
182   @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
183   public Facebook facebook(ConnectionRepository repository)
184   {
185     Connection<Facebook> connection =
186         repository.findPrimaryConnection(Facebook.class);
187     return connection != null ? connection.getApi() : null;
188   }
189
190   /**
191    * Use the <code>HttpClient</code> from Apaches <code>HttpComponents</code>
192    * for HTTP-requests.
193    *
194    * We also configure shorter intervals for the connection timeout and the
195    * read timeout.
196    *
197    * @param env The {@link Environment}, to read additional parameters from.
198    * @return The alternative implementation of {@link HttpRequestFactory}.
199    */
200   @Bean
201   public HttpComponentsClientHttpRequestFactory requestFactory(Environment env)
202   {
203     HttpComponentsClientHttpRequestFactory factory =
204         new HttpComponentsClientHttpRequestFactory();
205     factory.setConnectTimeout(
206         Integer.parseInt(env.getProperty("httpclient.timeout.connection"))
207         );
208     factory.setReadTimeout(
209         Integer.parseInt(env.getProperty("httpclient.timeout.read"))
210         );
211     return factory;
212   }
213 }