Oauth20AutoConfiguration.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.maxkey.autoconfigure;
  17. import java.net.URI;
  18. import java.security.NoSuchAlgorithmException;
  19. import java.security.spec.InvalidKeySpecException;
  20. import javax.servlet.Filter;
  21. import javax.sql.DataSource;
  22. import org.maxkey.authn.support.jwt.JwtLoginService;
  23. import org.maxkey.authz.oauth2.common.OAuth2Constants;
  24. import org.maxkey.authz.oauth2.provider.ClientDetailsService;
  25. import org.maxkey.authz.oauth2.provider.OAuth2UserDetailsService;
  26. import org.maxkey.authz.oauth2.provider.approval.TokenApprovalStore;
  27. import org.maxkey.authz.oauth2.provider.approval.endpoint.OAuth20UserApprovalHandler;
  28. import org.maxkey.authz.oauth2.provider.client.ClientDetailsUserDetailsService;
  29. import org.maxkey.authz.oauth2.provider.client.JdbcClientDetailsService;
  30. import org.maxkey.authz.oauth2.provider.code.AuthorizationCodeServices;
  31. import org.maxkey.authz.oauth2.provider.code.AuthorizationCodeServicesFactory;
  32. import org.maxkey.authz.oauth2.provider.endpoint.TokenEndpointAuthenticationFilter;
  33. import org.maxkey.authz.oauth2.provider.request.DefaultOAuth2RequestFactory;
  34. import org.maxkey.authz.oauth2.provider.token.TokenStore;
  35. import org.maxkey.authz.oauth2.provider.token.DefaultTokenServices;
  36. import org.maxkey.authz.oauth2.provider.token.store.JwtAccessTokenConverter;
  37. import org.maxkey.authz.oauth2.provider.token.store.TokenStoreFactory;
  38. import org.maxkey.authz.oidc.idtoken.OIDCIdTokenEnhancer;
  39. import org.maxkey.configuration.oidc.OIDCProviderMetadataDetails;
  40. import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
  41. import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
  42. import org.maxkey.crypto.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
  43. import org.maxkey.persistence.db.LoginService;
  44. import org.maxkey.persistence.redis.RedisConnectionFactory;
  45. import org.slf4j.Logger;
  46. import org.slf4j.LoggerFactory;
  47. import org.springframework.beans.factory.InitializingBean;
  48. import org.springframework.beans.factory.annotation.Value;
  49. import org.springframework.boot.web.servlet.FilterRegistrationBean;
  50. import org.springframework.context.annotation.Bean;
  51. import org.springframework.context.annotation.ComponentScan;
  52. import org.springframework.context.annotation.Configuration;
  53. import org.springframework.core.io.ClassPathResource;
  54. import org.springframework.jdbc.core.JdbcTemplate;
  55. import org.springframework.security.authentication.ProviderManager;
  56. import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
  57. import org.springframework.security.crypto.password.PasswordEncoder;
  58. import com.nimbusds.jose.JOSEException;
  59. import com.nimbusds.jose.JWEAlgorithm;
  60. @Configuration
  61. @ComponentScan(basePackages = {
  62. "org.maxkey.authz.oauth2.provider.endpoint",
  63. "org.maxkey.authz.oauth2.provider.userinfo.endpoint",
  64. "org.maxkey.authz.oauth2.provider.approval.controller"
  65. })
  66. public class Oauth20AutoConfiguration implements InitializingBean {
  67. private static final Logger _logger = LoggerFactory.getLogger(Oauth20AutoConfiguration.class);
  68. @Bean
  69. public FilterRegistrationBean<Filter> TokenEndpointAuthenticationFilter() {
  70. _logger.debug("TokenEndpointAuthenticationFilter init ");
  71. FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<Filter>();
  72. registration.setFilter(new TokenEndpointAuthenticationFilter());
  73. registration.addUrlPatterns(OAuth2Constants.ENDPOINT.ENDPOINT_TOKEN + "/*");
  74. registration.setName("TokenEndpointAuthenticationFilter");
  75. registration.setOrder(1);
  76. return registration;
  77. }
  78. /**
  79. * OIDCProviderMetadataDetails.
  80. * Self-issued Provider Metadata
  81. * http://openid.net/specs/openid-connect-core-1_0.html#SelfIssued
  82. */
  83. @Bean(name = "oidcProviderMetadata")
  84. public OIDCProviderMetadataDetails OIDCProviderMetadataDetails(
  85. @Value("${maxkey.oidc.metadata.issuer}")
  86. String issuer,
  87. @Value("${maxkey.oidc.metadata.authorizationEndpoint}")
  88. URI authorizationEndpoint,
  89. @Value("${maxkey.oidc.metadata.tokenEndpoint}")
  90. URI tokenEndpoint,
  91. @Value("${maxkey.oidc.metadata.userinfoEndpoint}")
  92. URI userinfoEndpoint) {
  93. _logger.debug("OIDCProviderMetadataDetails init .");
  94. OIDCProviderMetadataDetails oidcProviderMetadata = new OIDCProviderMetadataDetails();
  95. oidcProviderMetadata.setIssuer(issuer);
  96. oidcProviderMetadata.setAuthorizationEndpoint(authorizationEndpoint);
  97. oidcProviderMetadata.setTokenEndpoint(tokenEndpoint);
  98. oidcProviderMetadata.setUserinfoEndpoint(userinfoEndpoint);
  99. return oidcProviderMetadata;
  100. }
  101. /**
  102. * jwtSetKeyStore.
  103. * @return
  104. */
  105. @Bean(name = "jwkSetKeyStore")
  106. public JWKSetKeyStore jwtSetKeyStore() {
  107. JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore();
  108. ClassPathResource classPathResource = new ClassPathResource("/config/keystore.jwks");
  109. jwkSetKeyStore.setLocation(classPathResource);
  110. return jwkSetKeyStore;
  111. }
  112. /**
  113. * jwtSetKeyStore.
  114. * @return
  115. * @throws JOSEException
  116. * @throws InvalidKeySpecException
  117. * @throws NoSuchAlgorithmException
  118. */
  119. @Bean(name = "jwtSignerValidationService")
  120. public DefaultJwtSigningAndValidationService jwtSignerValidationService(
  121. JWKSetKeyStore jwtSetKeyStore)
  122. throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
  123. DefaultJwtSigningAndValidationService jwtSignerValidationService =
  124. new DefaultJwtSigningAndValidationService(jwtSetKeyStore);
  125. jwtSignerValidationService.setDefaultSignerKeyId("maxkey_rsa");
  126. jwtSignerValidationService.setDefaultSigningAlgorithmName("RS256");
  127. return jwtSignerValidationService;
  128. }
  129. /**
  130. * jwtSetKeyStore.
  131. * @return
  132. * @throws JOSEException
  133. * @throws InvalidKeySpecException
  134. * @throws NoSuchAlgorithmException
  135. */
  136. @Bean(name = "jwtEncryptionService")
  137. public DefaultJwtEncryptionAndDecryptionService jwtEncryptionService(
  138. JWKSetKeyStore jwtSetKeyStore)
  139. throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
  140. DefaultJwtEncryptionAndDecryptionService jwtEncryptionService =
  141. new DefaultJwtEncryptionAndDecryptionService(jwtSetKeyStore);
  142. jwtEncryptionService.setDefaultAlgorithm(JWEAlgorithm.RSA1_5);//RSA1_5
  143. jwtEncryptionService.setDefaultDecryptionKeyId("maxkey_rsa");
  144. jwtEncryptionService.setDefaultEncryptionKeyId("maxkey_rsa");
  145. return jwtEncryptionService;
  146. }
  147. /**
  148. * JwtLoginService.
  149. * @return
  150. */
  151. @Bean(name = "jwtLoginService")
  152. public JwtLoginService jwtLoginService(
  153. DefaultJwtSigningAndValidationService jwtSignerValidationService,
  154. OIDCProviderMetadataDetails oidcProviderMetadata) {
  155. JwtLoginService jwtLoginService = new JwtLoginService(
  156. oidcProviderMetadata,
  157. jwtSignerValidationService
  158. );
  159. return jwtLoginService;
  160. }
  161. /**
  162. * tokenEnhancer.
  163. * @return
  164. */
  165. @Bean(name = "tokenEnhancer")
  166. public OIDCIdTokenEnhancer tokenEnhancer(
  167. DefaultJwtSigningAndValidationService jwtSignerValidationService,
  168. DefaultJwtEncryptionAndDecryptionService jwtEncryptionService,
  169. OIDCProviderMetadataDetails oidcProviderMetadata,
  170. ClientDetailsService oauth20JdbcClientDetailsService) {
  171. OIDCIdTokenEnhancer tokenEnhancer = new OIDCIdTokenEnhancer();
  172. tokenEnhancer.setJwtSignerService(jwtSignerValidationService);
  173. tokenEnhancer.setJwtEnDecryptionService(jwtEncryptionService);
  174. tokenEnhancer.setClientDetailsService(oauth20JdbcClientDetailsService);
  175. tokenEnhancer.setProviderMetadata(oidcProviderMetadata);
  176. return tokenEnhancer;
  177. }
  178. //以上部分为了支持OpenID Connect 1.0
  179. /**
  180. * AuthorizationCodeServices.
  181. * @param persistence int
  182. * @return oauth20AuthorizationCodeServices
  183. */
  184. @Bean(name = "oauth20AuthorizationCodeServices")
  185. public AuthorizationCodeServices oauth20AuthorizationCodeServices(
  186. @Value("${maxkey.server.persistence}") int persistence,
  187. JdbcTemplate jdbcTemplate,
  188. RedisConnectionFactory redisConnFactory) {
  189. return new AuthorizationCodeServicesFactory().getService(persistence, jdbcTemplate, redisConnFactory);
  190. }
  191. /**
  192. * TokenStore.
  193. * @param persistence int
  194. * @return oauth20TokenStore
  195. */
  196. @Bean(name = "oauth20TokenStore")
  197. public TokenStore oauth20TokenStore(
  198. @Value("${maxkey.server.persistence}") int persistence,
  199. JdbcTemplate jdbcTemplate,
  200. RedisConnectionFactory redisConnFactory) {
  201. return new TokenStoreFactory().getTokenStore(persistence, jdbcTemplate, redisConnFactory);
  202. }
  203. /**
  204. * jwtAccessTokenConverter.
  205. * @return converter
  206. */
  207. @Bean(name = "converter")
  208. public JwtAccessTokenConverter jwtAccessTokenConverter() {
  209. JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
  210. return jwtAccessTokenConverter;
  211. }
  212. /**
  213. * clientDetailsService.
  214. * @return oauth20JdbcClientDetailsService
  215. */
  216. @Bean(name = "oauth20JdbcClientDetailsService")
  217. public JdbcClientDetailsService clientDetailsService(DataSource dataSource,PasswordEncoder passwordReciprocal) {
  218. JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
  219. clientDetailsService.setPasswordEncoder(passwordReciprocal);
  220. return clientDetailsService;
  221. }
  222. /**
  223. * clientDetailsUserDetailsService.
  224. * @return oauth20TokenServices
  225. */
  226. @Bean(name = "oauth20TokenServices")
  227. public DefaultTokenServices DefaultTokenServices(
  228. JdbcClientDetailsService oauth20JdbcClientDetailsService,
  229. TokenStore oauth20TokenStore,
  230. OIDCIdTokenEnhancer tokenEnhancer) {
  231. DefaultTokenServices tokenServices = new DefaultTokenServices();
  232. tokenServices.setClientDetailsService(oauth20JdbcClientDetailsService);
  233. tokenServices.setTokenEnhancer(tokenEnhancer);
  234. tokenServices.setTokenStore(oauth20TokenStore);
  235. tokenServices.setSupportRefreshToken(true);
  236. return tokenServices;
  237. }
  238. /**
  239. * TokenApprovalStore.
  240. * @return oauth20ApprovalStore
  241. */
  242. @Bean(name = "oauth20ApprovalStore")
  243. public TokenApprovalStore tokenApprovalStore(
  244. TokenStore oauth20TokenStore) {
  245. TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
  246. tokenApprovalStore.setTokenStore(oauth20TokenStore);
  247. return tokenApprovalStore;
  248. }
  249. /**
  250. * OAuth2RequestFactory.
  251. * @return oAuth2RequestFactory
  252. */
  253. @Bean(name = "oAuth2RequestFactory")
  254. public DefaultOAuth2RequestFactory oauth2RequestFactory(
  255. JdbcClientDetailsService oauth20JdbcClientDetailsService) {
  256. DefaultOAuth2RequestFactory oauth2RequestFactory =
  257. new DefaultOAuth2RequestFactory(oauth20JdbcClientDetailsService);
  258. return oauth2RequestFactory;
  259. }
  260. /**
  261. * OAuth20UserApprovalHandler.
  262. * @return oauth20UserApprovalHandler
  263. */
  264. @Bean(name = "oauth20UserApprovalHandler")
  265. public OAuth20UserApprovalHandler oauth20UserApprovalHandler(
  266. JdbcClientDetailsService oauth20JdbcClientDetailsService,
  267. DefaultOAuth2RequestFactory oAuth2RequestFactory,
  268. TokenApprovalStore oauth20ApprovalStore
  269. ) {
  270. OAuth20UserApprovalHandler userApprovalHandler = new OAuth20UserApprovalHandler();
  271. userApprovalHandler.setApprovalStore(oauth20ApprovalStore);
  272. userApprovalHandler.setRequestFactory(oAuth2RequestFactory);
  273. userApprovalHandler.setClientDetailsService(oauth20JdbcClientDetailsService);
  274. return userApprovalHandler;
  275. }
  276. /**
  277. * ProviderManager.
  278. * @return oauth20UserAuthenticationManager
  279. */
  280. @Bean(name = "oauth20UserAuthenticationManager")
  281. public ProviderManager oauth20UserAuthenticationManager(
  282. PasswordEncoder passwordEncoder,
  283. LoginService loginService
  284. ) {
  285. OAuth2UserDetailsService userDetailsService =new OAuth2UserDetailsService();
  286. userDetailsService.setLoginService(loginService);
  287. DaoAuthenticationProvider daoAuthenticationProvider= new DaoAuthenticationProvider();
  288. daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
  289. daoAuthenticationProvider.setUserDetailsService(userDetailsService);
  290. ProviderManager authenticationManager = new ProviderManager(daoAuthenticationProvider);
  291. return authenticationManager;
  292. }
  293. /**
  294. * ProviderManager.
  295. * @return oauth20ClientAuthenticationManager
  296. */
  297. @Bean(name = "oauth20ClientAuthenticationManager")
  298. public ProviderManager oauth20ClientAuthenticationManager(
  299. JdbcClientDetailsService oauth20JdbcClientDetailsService,
  300. PasswordEncoder passwordReciprocal
  301. ) {
  302. ClientDetailsUserDetailsService cientDetailsUserDetailsService =
  303. new ClientDetailsUserDetailsService(oauth20JdbcClientDetailsService);
  304. DaoAuthenticationProvider daoAuthenticationProvider= new DaoAuthenticationProvider();
  305. daoAuthenticationProvider.setPasswordEncoder(passwordReciprocal);
  306. daoAuthenticationProvider.setUserDetailsService(cientDetailsUserDetailsService);
  307. ProviderManager authenticationManager = new ProviderManager(daoAuthenticationProvider);
  308. return authenticationManager;
  309. }
  310. @Override
  311. public void afterPropertiesSet() throws Exception {
  312. // TODO Auto-generated method stub
  313. }
  314. }