RedisTests.java 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright 2020-2024 the original author or authors.
  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. * https://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 sample.redis;
  17. import java.io.IOException;
  18. import java.util.Map;
  19. import jakarta.annotation.PostConstruct;
  20. import jakarta.annotation.PreDestroy;
  21. import org.assertj.core.api.ObjectAssert;
  22. import org.junit.jupiter.api.Test;
  23. import redis.embedded.RedisServer;
  24. import sample.AuthorizationCodeGrantFlow;
  25. import sample.DeviceAuthorizationGrantFlow;
  26. import sample.redis.service.RedisOAuth2AuthorizationConsentService;
  27. import sample.redis.service.RedisOAuth2AuthorizationService;
  28. import sample.redis.service.RedisRegisteredClientRepository;
  29. import sample.util.RegisteredClients;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  32. import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
  33. import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
  34. import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
  35. import org.springframework.boot.test.context.SpringBootTest;
  36. import org.springframework.boot.test.context.TestConfiguration;
  37. import org.springframework.context.annotation.ComponentScan;
  38. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  39. import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
  40. import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
  41. import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
  42. import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsent;
  43. import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
  44. import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
  45. import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
  46. import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
  47. import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
  48. import org.springframework.test.web.servlet.MockMvc;
  49. import org.springframework.util.StringUtils;
  50. import static org.assertj.core.api.Assertions.assertThat;
  51. /**
  52. * Tests for the guide How-to: Implement core services with Redis.
  53. *
  54. * @author Joe Grandja
  55. */
  56. @SpringBootTest(classes = {RedisTests.AuthorizationServerConfig.class})
  57. @AutoConfigureMockMvc
  58. public class RedisTests {
  59. private static final RegisteredClient TEST_MESSAGING_CLIENT = RegisteredClients.messagingClient();
  60. @Autowired
  61. private MockMvc mockMvc;
  62. @Autowired
  63. private RegisteredClientRepository registeredClientRepository;
  64. @Autowired
  65. private OAuth2AuthorizationService authorizationService;
  66. @Autowired
  67. private OAuth2AuthorizationConsentService authorizationConsentService;
  68. @Test
  69. public void oidcLoginWhenRedisCoreServicesAutowiredThenUsed() throws Exception {
  70. assertThat(this.registeredClientRepository).isInstanceOf(RedisRegisteredClientRepository.class);
  71. assertThat(this.authorizationService).isInstanceOf(RedisOAuth2AuthorizationService.class);
  72. assertThat(this.authorizationConsentService).isInstanceOf(RedisOAuth2AuthorizationConsentService.class);
  73. RegisteredClient registeredClient = TEST_MESSAGING_CLIENT;
  74. AuthorizationCodeGrantFlow authorizationCodeGrantFlow = new AuthorizationCodeGrantFlow(this.mockMvc);
  75. authorizationCodeGrantFlow.setUsername("user");
  76. authorizationCodeGrantFlow.addScope("message.read");
  77. authorizationCodeGrantFlow.addScope("message.write");
  78. String state = authorizationCodeGrantFlow.authorize(registeredClient);
  79. assertThatAuthorization(state, OAuth2ParameterNames.STATE).isNotNull();
  80. assertThatAuthorization(state, null).isNotNull();
  81. String authorizationCode = authorizationCodeGrantFlow.submitConsent(registeredClient, state);
  82. assertThatAuthorization(authorizationCode, OAuth2ParameterNames.CODE).isNotNull();
  83. assertThatAuthorization(authorizationCode, null).isNotNull();
  84. Map<String, Object> tokenResponse = authorizationCodeGrantFlow.getTokenResponse(registeredClient, authorizationCode);
  85. String accessToken = (String) tokenResponse.get(OAuth2ParameterNames.ACCESS_TOKEN);
  86. assertThatAuthorization(accessToken, OAuth2ParameterNames.ACCESS_TOKEN).isNotNull();
  87. assertThatAuthorization(accessToken, null).isNotNull();
  88. String refreshToken = (String) tokenResponse.get(OAuth2ParameterNames.REFRESH_TOKEN);
  89. assertThatAuthorization(refreshToken, OAuth2ParameterNames.REFRESH_TOKEN).isNotNull();
  90. assertThatAuthorization(refreshToken, null).isNotNull();
  91. String idToken = (String) tokenResponse.get(OidcParameterNames.ID_TOKEN);
  92. assertThatAuthorization(idToken, OidcParameterNames.ID_TOKEN).isNotNull();
  93. assertThatAuthorization(idToken, null).isNotNull();
  94. OAuth2Authorization authorization = findAuthorization(accessToken, OAuth2ParameterNames.ACCESS_TOKEN);
  95. assertThat(authorization.getToken(idToken)).isNotNull();
  96. String scopes = (String) tokenResponse.get(OAuth2ParameterNames.SCOPE);
  97. OAuth2AuthorizationConsent authorizationConsent = this.authorizationConsentService.findById(
  98. registeredClient.getId(), "user");
  99. assertThat(authorizationConsent).isNotNull();
  100. assertThat(authorizationConsent.getScopes()).containsExactlyInAnyOrder(
  101. StringUtils.delimitedListToStringArray(scopes, " "));
  102. }
  103. @Test
  104. public void deviceAuthorizationWhenRedisCoreServicesAutowiredThenUsed() throws Exception {
  105. assertThat(this.registeredClientRepository).isInstanceOf(RedisRegisteredClientRepository.class);
  106. assertThat(this.authorizationService).isInstanceOf(RedisOAuth2AuthorizationService.class);
  107. assertThat(this.authorizationConsentService).isInstanceOf(RedisOAuth2AuthorizationConsentService.class);
  108. RegisteredClient registeredClient = TEST_MESSAGING_CLIENT;
  109. DeviceAuthorizationGrantFlow deviceAuthorizationGrantFlow = new DeviceAuthorizationGrantFlow(this.mockMvc);
  110. deviceAuthorizationGrantFlow.setUsername("user");
  111. deviceAuthorizationGrantFlow.addScope("message.read");
  112. deviceAuthorizationGrantFlow.addScope("message.write");
  113. Map<String, Object> deviceAuthorizationResponse = deviceAuthorizationGrantFlow.authorize(registeredClient);
  114. String userCode = (String) deviceAuthorizationResponse.get(OAuth2ParameterNames.USER_CODE);
  115. assertThatAuthorization(userCode, OAuth2ParameterNames.USER_CODE).isNotNull();
  116. assertThatAuthorization(userCode, null).isNotNull();
  117. String deviceCode = (String) deviceAuthorizationResponse.get(OAuth2ParameterNames.DEVICE_CODE);
  118. assertThatAuthorization(deviceCode, OAuth2ParameterNames.DEVICE_CODE).isNotNull();
  119. assertThatAuthorization(deviceCode, null).isNotNull();
  120. String state = deviceAuthorizationGrantFlow.submitCode(userCode);
  121. assertThatAuthorization(state, OAuth2ParameterNames.STATE).isNotNull();
  122. assertThatAuthorization(state, null).isNotNull();
  123. deviceAuthorizationGrantFlow.submitConsent(registeredClient, state, userCode);
  124. Map<String, Object> tokenResponse = deviceAuthorizationGrantFlow.getTokenResponse(registeredClient, deviceCode);
  125. String accessToken = (String) tokenResponse.get(OAuth2ParameterNames.ACCESS_TOKEN);
  126. assertThatAuthorization(accessToken, OAuth2ParameterNames.ACCESS_TOKEN).isNotNull();
  127. assertThatAuthorization(accessToken, null).isNotNull();
  128. String refreshToken = (String) tokenResponse.get(OAuth2ParameterNames.REFRESH_TOKEN);
  129. assertThatAuthorization(refreshToken, OAuth2ParameterNames.REFRESH_TOKEN).isNotNull();
  130. assertThatAuthorization(refreshToken, null).isNotNull();
  131. String scopes = (String) tokenResponse.get(OAuth2ParameterNames.SCOPE);
  132. OAuth2AuthorizationConsent authorizationConsent = this.authorizationConsentService.findById(
  133. registeredClient.getId(), "user");
  134. assertThat(authorizationConsent).isNotNull();
  135. assertThat(authorizationConsent.getScopes()).containsExactlyInAnyOrder(
  136. StringUtils.delimitedListToStringArray(scopes, " "));
  137. }
  138. private ObjectAssert<OAuth2Authorization> assertThatAuthorization(String token, String tokenType) {
  139. return assertThat(findAuthorization(token, tokenType));
  140. }
  141. private OAuth2Authorization findAuthorization(String token, String tokenType) {
  142. return this.authorizationService.findByToken(token, tokenType == null ? null : new OAuth2TokenType(tokenType));
  143. }
  144. @EnableWebSecurity
  145. @EnableAutoConfiguration(exclude = {JpaRepositoriesAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
  146. @ComponentScan
  147. static class AuthorizationServerConfig {
  148. }
  149. @TestConfiguration
  150. static class RedisServerConfig {
  151. private final RedisServer redisServer;
  152. @Autowired
  153. private RegisteredClientRepository registeredClientRepository;
  154. RedisServerConfig() throws IOException {
  155. this.redisServer = new RedisServer();
  156. }
  157. @PostConstruct
  158. void postConstruct() throws IOException {
  159. this.redisServer.start();
  160. this.registeredClientRepository.save(TEST_MESSAGING_CLIENT);
  161. }
  162. @PreDestroy
  163. void preDestroy() throws IOException {
  164. this.redisServer.stop();
  165. }
  166. }
  167. }