@Test public void setJwtDecoderFactoryWhenNullThenIllegalArgumentException() { assertThatThrownBy(() -> this.manager.setJwtDecoderFactory(null)) .isInstanceOf(IllegalArgumentException.class); }
private ReactiveAuthenticationManager createDefault() { WebClientReactiveAuthorizationCodeTokenResponseClient client = new WebClientReactiveAuthorizationCodeTokenResponseClient(); ReactiveAuthenticationManager result = new OAuth2LoginReactiveAuthenticationManager(client, getOauth2UserService()); boolean oidcAuthenticationProviderEnabled = ClassUtils.isPresent( "org.springframework.security.oauth2.jwt.JwtDecoder", this.getClass().getClassLoader()); if (oidcAuthenticationProviderEnabled) { OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager(client, getOidcUserService()); ResolvableType type = ResolvableType.forClassWithGenerics( ReactiveJwtDecoderFactory.class, ClientRegistration.class); ReactiveJwtDecoderFactory<ClientRegistration> jwtDecoderFactory = getBeanOrNull(type); if (jwtDecoderFactory != null) { oidc.setJwtDecoderFactory(jwtDecoderFactory); } result = new DelegatingReactiveAuthenticationManager(oidc, result); } return result; }
private ReactiveAuthenticationManager authenticationManager() { OidcAuthorizationCodeReactiveAuthenticationManager oidc = new OidcAuthorizationCodeReactiveAuthenticationManager(tokenResponseClient, userService); oidc.setJwtDecoderFactory(jwtDecoderFactory()); return oidc; }
@Test public void authenticationWhenOAuth2UserNotFoundThenEmpty() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") .tokenType(OAuth2AccessToken.TokenType.BEARER) .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.")) .build(); Map<String, Object> claims = new HashMap<>(); claims.put(IdTokenClaimNames.ISS, "https://issuer.example.com"); claims.put(IdTokenClaimNames.SUB, "rob"); claims.put(IdTokenClaimNames.AUD, Arrays.asList("client-id")); Instant issuedAt = Instant.now(); Instant expiresAt = Instant.from(issuedAt).plusSeconds(3600); Jwt idToken = new Jwt("id-token", issuedAt, expiresAt, claims, claims); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); when(this.userService.loadUser(any())).thenReturn(Mono.empty()); when(this.jwtDecoder.decode(any())).thenReturn(Mono.just(idToken)); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); assertThat(this.manager.authenticate(loginToken()).block()).isNull(); }
@Test public void authenticateWhenIdTokenValidationErrorThenOAuth2AuthenticationException() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") .tokenType(OAuth2AccessToken.TokenType.BEARER) .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) .build(); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); when(this.jwtDecoder.decode(any())).thenThrow(new JwtException("ID Token Validation Error")); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); assertThatThrownBy(() -> this.manager.authenticate(loginToken()).block()) .isInstanceOf(OAuth2AuthenticationException.class) .hasMessageContaining("[invalid_id_token] ID Token Validation Error"); }
@Test public void authenticationWhenOAuth2UserFoundThenSuccess() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") .tokenType(OAuth2AccessToken.TokenType.BEARER) .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) .build(); Map<String, Object> claims = new HashMap<>(); claims.put(IdTokenClaimNames.ISS, "https://issuer.example.com"); claims.put(IdTokenClaimNames.SUB, "rob"); claims.put(IdTokenClaimNames.AUD, Arrays.asList("client-id")); Instant issuedAt = Instant.now(); Instant expiresAt = Instant.from(issuedAt).plusSeconds(3600); Jwt idToken = new Jwt("id-token", issuedAt, expiresAt, claims, claims); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); DefaultOidcUser user = new DefaultOidcUser(AuthorityUtils.createAuthorityList("ROLE_USER"), this.idToken); when(this.userService.loadUser(any())).thenReturn(Mono.just(user)); when(this.jwtDecoder.decode(any())).thenReturn(Mono.just(idToken)); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(loginToken()).block(); assertThat(result.getPrincipal()).isEqualTo(user); assertThat(result.getAuthorities()).containsOnlyElementsOf(user.getAuthorities()); assertThat(result.isAuthenticated()).isTrue(); }
@Test public void authenticateWhenTokenSuccessResponseThenAdditionalParametersAddedToUserRequest() { ClientRegistration clientRegistration = this.registration.build(); Map<String, Object> additionalParameters = new HashMap<>(); additionalParameters.put(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue()); additionalParameters.put("param1", "value1"); additionalParameters.put("param2", "value2"); OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") .tokenType(OAuth2AccessToken.TokenType.BEARER) .additionalParameters(additionalParameters) .build(); Map<String, Object> claims = new HashMap<>(); claims.put(IdTokenClaimNames.ISS, "https://issuer.example.com"); claims.put(IdTokenClaimNames.SUB, "rob"); claims.put(IdTokenClaimNames.AUD, Arrays.asList(clientRegistration.getClientId())); Instant issuedAt = Instant.now(); Instant expiresAt = Instant.from(issuedAt).plusSeconds(3600); Jwt idToken = new Jwt("id-token", issuedAt, expiresAt, claims, claims); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); DefaultOidcUser user = new DefaultOidcUser(AuthorityUtils.createAuthorityList("ROLE_USER"), this.idToken); ArgumentCaptor<OidcUserRequest> userRequestArgCaptor = ArgumentCaptor.forClass(OidcUserRequest.class); when(this.userService.loadUser(userRequestArgCaptor.capture())).thenReturn(Mono.just(user)); when(this.jwtDecoder.decode(any())).thenReturn(Mono.just(idToken)); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); this.manager.authenticate(loginToken()).block(); assertThat(userRequestArgCaptor.getValue().getAdditionalParameters()) .containsAllEntriesOf(accessTokenResponse.getAdditionalParameters()); }
@Test public void authenticationWhenRefreshTokenThenRefreshTokenInAuthorizedClient() { OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("foo") .tokenType(OAuth2AccessToken.TokenType.BEARER) .additionalParameters(Collections.singletonMap(OidcParameterNames.ID_TOKEN, this.idToken.getTokenValue())) .refreshToken("refresh-token") .build(); Map<String, Object> claims = new HashMap<>(); claims.put(IdTokenClaimNames.ISS, "https://issuer.example.com"); claims.put(IdTokenClaimNames.SUB, "rob"); claims.put(IdTokenClaimNames.AUD, Arrays.asList("client-id")); Instant issuedAt = Instant.now(); Instant expiresAt = Instant.from(issuedAt).plusSeconds(3600); Jwt idToken = new Jwt("id-token", issuedAt, expiresAt, claims, claims); when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(Mono.just(accessTokenResponse)); DefaultOidcUser user = new DefaultOidcUser(AuthorityUtils.createAuthorityList("ROLE_USER"), this.idToken); when(this.userService.loadUser(any())).thenReturn(Mono.just(user)); when(this.jwtDecoder.decode(any())).thenReturn(Mono.just(idToken)); this.manager.setJwtDecoderFactory(c -> this.jwtDecoder); OAuth2LoginAuthenticationToken result = (OAuth2LoginAuthenticationToken) this.manager.authenticate(loginToken()).block(); assertThat(result.getPrincipal()).isEqualTo(user); assertThat(result.getAuthorities()).containsOnlyElementsOf(user.getAuthorities()); assertThat(result.isAuthenticated()).isTrue(); assertThat(result.getRefreshToken().getTokenValue()).isNotNull(); }