|
47 | 47 | import org.springframework.security.oauth2.jwt.JoseHeaderNames;
|
48 | 48 | import org.springframework.security.oauth2.jwt.Jwt;
|
49 | 49 | import org.springframework.security.oauth2.jwt.JwtEncoder;
|
| 50 | +import org.springframework.security.oauth2.jwt.JwtEncoderParameters; |
50 | 51 | import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
|
51 | 52 | import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
52 | 53 | import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
|
@@ -250,7 +251,86 @@ public void authenticateWhenValidRefreshTokenThenReturnIdToken() {
|
250 | 251 | assertThat(idTokenContext.getJwsHeader()).isNotNull();
|
251 | 252 | assertThat(idTokenContext.getClaims()).isNotNull();
|
252 | 253 |
|
253 |
| - verify(this.jwtEncoder, times(2)).encode(any()); // Access token and ID Token |
| 254 | + ArgumentCaptor<JwtEncoderParameters> jwtEncoderParametersArgumentCaptor = ArgumentCaptor.forClass(JwtEncoderParameters.class); |
| 255 | + verify(this.jwtEncoder, times(2)).encode(jwtEncoderParametersArgumentCaptor.capture()); // Access token and ID Token |
| 256 | + JwtEncoderParameters jwtEncoderParameters = jwtEncoderParametersArgumentCaptor.getValue(); |
| 257 | + assertThat(jwtEncoderParameters.getClaims().getClaims().get("sid")).isNotNull(); |
| 258 | + |
| 259 | + ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class); |
| 260 | + verify(this.authorizationService).save(authorizationCaptor.capture()); |
| 261 | + OAuth2Authorization updatedAuthorization = authorizationCaptor.getValue(); |
| 262 | + |
| 263 | + assertThat(accessTokenAuthentication.getRegisteredClient().getId()).isEqualTo(updatedAuthorization.getRegisteredClientId()); |
| 264 | + assertThat(accessTokenAuthentication.getPrincipal()).isEqualTo(clientPrincipal); |
| 265 | + assertThat(accessTokenAuthentication.getAccessToken()).isEqualTo(updatedAuthorization.getAccessToken().getToken()); |
| 266 | + assertThat(updatedAuthorization.getAccessToken()).isNotEqualTo(authorization.getAccessToken()); |
| 267 | + OAuth2Authorization.Token<OidcIdToken> idToken = updatedAuthorization.getToken(OidcIdToken.class); |
| 268 | + assertThat(idToken).isNotNull(); |
| 269 | + assertThat(accessTokenAuthentication.getAdditionalParameters()) |
| 270 | + .containsExactly(entry(OidcParameterNames.ID_TOKEN, idToken.getToken().getTokenValue())); |
| 271 | + assertThat(accessTokenAuthentication.getRefreshToken()).isEqualTo(updatedAuthorization.getRefreshToken().getToken()); |
| 272 | + // By default, refresh token is reused |
| 273 | + assertThat(updatedAuthorization.getRefreshToken()).isEqualTo(authorization.getRefreshToken()); |
| 274 | + } |
| 275 | + |
| 276 | + @Test |
| 277 | + public void authenticateWhenValidRefreshTokenThenReturnIdTokenWithoutSid() { |
| 278 | + RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build(); |
| 279 | + OidcIdToken authorizedIdToken = OidcIdToken.withTokenValue("id-token") |
| 280 | + .issuer("https://provider.com") |
| 281 | + .subject("subject") |
| 282 | + .issuedAt(Instant.now()) |
| 283 | + .expiresAt(Instant.now().plusSeconds(60)) |
| 284 | + .claim(IdTokenClaimNames.AUTH_TIME, Date.from(Instant.now())) |
| 285 | + .build(); |
| 286 | + OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).token(authorizedIdToken).build(); |
| 287 | + when(this.authorizationService.findByToken( |
| 288 | + eq(authorization.getRefreshToken().getToken().getTokenValue()), |
| 289 | + eq(OAuth2TokenType.REFRESH_TOKEN))) |
| 290 | + .thenReturn(authorization); |
| 291 | + |
| 292 | + OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( |
| 293 | + registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); |
| 294 | + OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken( |
| 295 | + authorization.getRefreshToken().getToken().getTokenValue(), clientPrincipal, null, null); |
| 296 | + |
| 297 | + OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = |
| 298 | + (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication); |
| 299 | + |
| 300 | + ArgumentCaptor<JwtEncodingContext> jwtEncodingContextCaptor = ArgumentCaptor.forClass(JwtEncodingContext.class); |
| 301 | + verify(this.jwtCustomizer, times(2)).customize(jwtEncodingContextCaptor.capture()); |
| 302 | + // Access Token context |
| 303 | + JwtEncodingContext accessTokenContext = jwtEncodingContextCaptor.getAllValues().get(0); |
| 304 | + assertThat(accessTokenContext.getRegisteredClient()).isEqualTo(registeredClient); |
| 305 | + assertThat(accessTokenContext.<Authentication>getPrincipal()).isEqualTo(authorization.getAttribute(Principal.class.getName())); |
| 306 | + assertThat(accessTokenContext.getAuthorization()).isEqualTo(authorization); |
| 307 | + assertThat(accessTokenContext.getAuthorizedScopes()).isEqualTo(authorization.getAuthorizedScopes()); |
| 308 | + assertThat(accessTokenContext.getTokenType()).isEqualTo(OAuth2TokenType.ACCESS_TOKEN); |
| 309 | + assertThat(accessTokenContext.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN); |
| 310 | + assertThat(accessTokenContext.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authentication); |
| 311 | + assertThat(accessTokenContext.getJwsHeader()).isNotNull(); |
| 312 | + assertThat(accessTokenContext.getClaims()).isNotNull(); |
| 313 | + Map<String, Object> claims = new HashMap<>(); |
| 314 | + accessTokenContext.getClaims().claims(claims::putAll); |
| 315 | + assertThat(claims).flatExtracting(OAuth2ParameterNames.SCOPE) |
| 316 | + .containsExactlyInAnyOrder(OidcScopes.OPENID, "scope1"); |
| 317 | + // ID Token context |
| 318 | + JwtEncodingContext idTokenContext = jwtEncodingContextCaptor.getAllValues().get(1); |
| 319 | + assertThat(idTokenContext.getRegisteredClient()).isEqualTo(registeredClient); |
| 320 | + assertThat(idTokenContext.<Authentication>getPrincipal()).isEqualTo(authorization.getAttribute(Principal.class.getName())); |
| 321 | + assertThat(idTokenContext.getAuthorization()).isNotEqualTo(authorization); |
| 322 | + assertThat(idTokenContext.getAuthorization().getAccessToken()).isNotEqualTo(authorization.getAccessToken()); |
| 323 | + assertThat(idTokenContext.getAuthorizedScopes()).isEqualTo(authorization.getAuthorizedScopes()); |
| 324 | + assertThat(idTokenContext.getTokenType().getValue()).isEqualTo(OidcParameterNames.ID_TOKEN); |
| 325 | + assertThat(idTokenContext.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN); |
| 326 | + assertThat(idTokenContext.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authentication); |
| 327 | + assertThat(idTokenContext.getJwsHeader()).isNotNull(); |
| 328 | + assertThat(idTokenContext.getClaims()).isNotNull(); |
| 329 | + |
| 330 | + ArgumentCaptor<JwtEncoderParameters> jwtEncoderParametersArgumentCaptor = ArgumentCaptor.forClass(JwtEncoderParameters.class); |
| 331 | + verify(this.jwtEncoder, times(2)).encode(jwtEncoderParametersArgumentCaptor.capture()); // Access token and ID Token |
| 332 | + JwtEncoderParameters jwtEncoderParameters = jwtEncoderParametersArgumentCaptor.getValue(); |
| 333 | + assertThat(jwtEncoderParameters.getClaims().getClaims().get("sid")).isNull(); |
254 | 334 |
|
255 | 335 | ArgumentCaptor<OAuth2Authorization> authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class);
|
256 | 336 | verify(this.authorizationService).save(authorizationCaptor.capture());
|
|
0 commit comments