|
47 | 47 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
48 | 48 | import org.springframework.mock.http.client.MockClientHttpResponse;
|
49 | 49 | import org.springframework.mock.web.MockHttpServletResponse;
|
| 50 | +import org.springframework.mock.web.MockHttpSession; |
50 | 51 | import org.springframework.security.authentication.TestingAuthenticationToken;
|
51 | 52 | import org.springframework.security.config.Customizer;
|
52 | 53 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
123 | 124 | public class OidcTests {
|
124 | 125 | private static final String DEFAULT_AUTHORIZATION_ENDPOINT_URI = "/oauth2/authorize";
|
125 | 126 | private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/oauth2/token";
|
| 127 | + private static final String DEFAULT_OIDC_LOGOUT_ENDPOINT_URI = "/connect/logout"; |
126 | 128 | private static final String AUTHORITIES_CLAIM = "authorities";
|
127 | 129 | private static final OAuth2TokenType AUTHORIZATION_CODE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.CODE);
|
128 | 130 | private static EmbeddedDatabase db;
|
@@ -216,15 +218,69 @@ public void requestWhenAuthenticationRequestThenTokenResponseIncludesIdToken() t
|
216 | 218 | servletResponse.getContentAsByteArray(), HttpStatus.valueOf(servletResponse.getStatus()));
|
217 | 219 | OAuth2AccessTokenResponse accessTokenResponse = accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, httpResponse);
|
218 | 220 |
|
219 |
| - // Assert user authorities was propagated as claim in ID Token |
220 | 221 | Jwt idToken = this.jwtDecoder.decode((String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN));
|
| 222 | + |
| 223 | + // Assert user authorities was propagated as claim in ID Token |
221 | 224 | List<String> authoritiesClaim = idToken.getClaim(AUTHORITIES_CLAIM);
|
222 | 225 | Authentication principal = authorization.getAttribute(Principal.class.getName());
|
223 | 226 | Set<String> userAuthorities = new HashSet<>();
|
224 | 227 | for (GrantedAuthority authority : principal.getAuthorities()) {
|
225 | 228 | userAuthorities.add(authority.getAuthority());
|
226 | 229 | }
|
227 | 230 | assertThat(authoritiesClaim).containsExactlyInAnyOrderElementsOf(userAuthorities);
|
| 231 | + |
| 232 | + // Assert sid claim was added in ID Token |
| 233 | + assertThat(idToken.<String>getClaim("sid")).isNotNull(); |
| 234 | + } |
| 235 | + |
| 236 | + @Test |
| 237 | + public void requestWhenLogoutRequestThenLogout() throws Exception { |
| 238 | + this.spring.register(AuthorizationServerConfiguration.class).autowire(); |
| 239 | + |
| 240 | + RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build(); |
| 241 | + this.registeredClientRepository.save(registeredClient); |
| 242 | + |
| 243 | + // Login |
| 244 | + MultiValueMap<String, String> authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient); |
| 245 | + MvcResult mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI) |
| 246 | + .params(authorizationRequestParameters) |
| 247 | + .with(user("user"))) |
| 248 | + .andExpect(status().is3xxRedirection()) |
| 249 | + .andReturn(); |
| 250 | + |
| 251 | + MockHttpSession session = (MockHttpSession) mvcResult.getRequest().getSession(); |
| 252 | + assertThat(session.isNew()).isTrue(); |
| 253 | + |
| 254 | + String redirectedUrl = mvcResult.getResponse().getRedirectedUrl(); |
| 255 | + String authorizationCode = extractParameterFromRedirectUri(redirectedUrl, "code"); |
| 256 | + OAuth2Authorization authorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE); |
| 257 | + |
| 258 | + // Get ID Token |
| 259 | + mvcResult = this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) |
| 260 | + .params(getTokenRequestParameters(registeredClient, authorization)) |
| 261 | + .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth( |
| 262 | + registeredClient.getClientId(), registeredClient.getClientSecret())) |
| 263 | + .session(session)) |
| 264 | + .andExpect(status().isOk()) |
| 265 | + .andReturn(); |
| 266 | + |
| 267 | + MockHttpServletResponse servletResponse = mvcResult.getResponse(); |
| 268 | + MockClientHttpResponse httpResponse = new MockClientHttpResponse( |
| 269 | + servletResponse.getContentAsByteArray(), HttpStatus.valueOf(servletResponse.getStatus())); |
| 270 | + OAuth2AccessTokenResponse accessTokenResponse = accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, httpResponse); |
| 271 | + |
| 272 | + String idToken = (String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN); |
| 273 | + |
| 274 | + // Logout |
| 275 | + mvcResult = this.mvc.perform(post(DEFAULT_OIDC_LOGOUT_ENDPOINT_URI) |
| 276 | + .param("id_token_hint", idToken) |
| 277 | + .session(session)) |
| 278 | + .andExpect(status().is3xxRedirection()) |
| 279 | + .andReturn(); |
| 280 | + redirectedUrl = mvcResult.getResponse().getRedirectedUrl(); |
| 281 | + |
| 282 | + assertThat(redirectedUrl).matches("/"); |
| 283 | + assertThat(session.isInvalid()).isTrue(); |
228 | 284 | }
|
229 | 285 |
|
230 | 286 | @Test
|
|
0 commit comments