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