package it.inaf.ia2.gms.rap; import it.inaf.ia2.gms.authn.SessionData; import it.inaf.ia2.gms.model.RapUser; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import org.mockito.Mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException.Unauthorized; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpServerErrorException.InternalServerError; import org.springframework.web.client.RestTemplate; @RunWith(MockitoJUnitRunner.class) public class RapClientTest { @Mock private HttpServletRequest request; @Mock private SessionData sessionData; @Mock private RestTemplate restTemplate; @Mock private RestTemplate refreshTokenRestTemplate; private RapClient rapClient; @Before public void init() { rapClient = new RapClient(restTemplate); ReflectionTestUtils.setField(rapClient, "request", request); ReflectionTestUtils.setField(rapClient, "refreshTokenRestTemplate", refreshTokenRestTemplate); ReflectionTestUtils.setField(rapClient, "scope", "openid"); } @Test public void testUnauthorizedNoRefreshJsonMsg() { String jsonError = "{\"error\":\"Unauthorized: foo\"}"; HttpClientErrorException exception = Unauthorized .create(HttpStatus.UNAUTHORIZED, "401", HttpHeaders.EMPTY, jsonError.getBytes(), StandardCharsets.UTF_8); when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(new ParameterizedTypeReference() { }))).thenThrow(exception); try { rapClient.getUser("123"); } catch (HttpClientErrorException ex) { assertEquals("401 Unauthorized: foo", ex.getMessage()); } } @Test public void testUnauthorizedNoRefreshNotJsonMsg() { String errorMessage = "THIS IS NOT A JSON"; HttpClientErrorException exception = Unauthorized .create(HttpStatus.UNAUTHORIZED, "401", HttpHeaders.EMPTY, errorMessage.getBytes(), StandardCharsets.UTF_8); when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(new ParameterizedTypeReference() { }))).thenThrow(exception); try { rapClient.getUser("123"); } catch (HttpClientErrorException ex) { assertNotNull(ex.getMessage()); } } @Test public void testServerErrorJsonMsg() { String jsonError = "{\"error\":\"Fatal error\"}"; HttpServerErrorException exception = InternalServerError .create(HttpStatus.INTERNAL_SERVER_ERROR, "500", HttpHeaders.EMPTY, jsonError.getBytes(), StandardCharsets.UTF_8); when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(new ParameterizedTypeReference() { }))).thenThrow(exception); try { rapClient.getUser("123"); } catch (HttpServerErrorException ex) { assertEquals("500 Fatal error", ex.getMessage()); } } @Test public void testRefreshToken() { when(request.getSession(eq(false))).thenReturn(mock(HttpSession.class)); when(sessionData.getExpiresIn()).thenReturn(-100l); ReflectionTestUtils.setField(rapClient, "sessionData", sessionData); ReflectionTestUtils.setField(rapClient, "clientId", "clientId"); ReflectionTestUtils.setField(rapClient, "clientSecret", "clientSecret"); ReflectionTestUtils.setField(rapClient, "accessTokenUri", "https://sso.ia2.inaf.it"); String jsonError = "{\"error\":\"Unauthorized: token expired\"}"; HttpClientErrorException exception = Unauthorized .create(HttpStatus.UNAUTHORIZED, "401", HttpHeaders.EMPTY, jsonError.getBytes(), StandardCharsets.UTF_8); when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(new ParameterizedTypeReference() { }))).thenThrow(exception) .thenReturn(ResponseEntity.ok(new RapUser())); ResponseEntity refreshTokenResponse = mock(ResponseEntity.class); Map mockedBody = new HashMap<>(); mockedBody.put("access_token", ""); mockedBody.put("refresh_token", ""); mockedBody.put("expires_in", 3600); when(refreshTokenResponse.getBody()).thenReturn(mockedBody); when(refreshTokenRestTemplate.postForEntity(anyString(), any(HttpEntity.class), any())) .thenReturn(refreshTokenResponse); RapUser user = rapClient.getUser("123"); assertNotNull(user); // verifies that token is refreshed verify(sessionData, times(1)).setAccessToken(eq("")); verify(sessionData, times(1)).setExpiresIn(eq(3600l)); } }