|
2 | 2 |
|
3 | 3 | import com.auth0.client.MockServer; |
4 | 4 | import com.auth0.exception.APIException; |
| 5 | +import com.auth0.json.ObjectMapperProvider; |
5 | 6 | import com.auth0.json.auth.*; |
6 | 7 | import com.auth0.net.BaseRequest; |
7 | 8 | import com.auth0.net.Request; |
|
11 | 12 | import com.auth0.net.client.Auth0HttpRequest; |
12 | 13 | import com.auth0.net.client.Auth0HttpResponse; |
13 | 14 | import com.auth0.net.client.HttpMethod; |
| 15 | +import com.fasterxml.jackson.core.JsonProcessingException; |
14 | 16 | import com.fasterxml.jackson.core.type.TypeReference; |
15 | 17 | import com.fasterxml.jackson.databind.ObjectMapper; |
16 | 18 | import okhttp3.mockwebserver.RecordedRequest; |
|
19 | 21 | import org.junit.jupiter.api.Test; |
20 | 22 |
|
21 | 23 | import java.io.FileReader; |
22 | | -import java.util.Collections; |
23 | | -import java.util.HashMap; |
24 | | -import java.util.List; |
25 | | -import java.util.Map; |
| 24 | +import java.net.URLDecoder; |
| 25 | +import java.nio.charset.StandardCharsets; |
| 26 | +import java.util.*; |
26 | 27 | import java.util.concurrent.CompletableFuture; |
| 28 | +import java.util.stream.Collectors; |
27 | 29 |
|
28 | 30 | import static com.auth0.AssertsUtil.verifyThrows; |
29 | 31 | import static com.auth0.client.MockServer.*; |
|
35 | 37 | import static org.hamcrest.Matchers.*; |
36 | 38 | import static org.hamcrest.collection.IsMapContaining.hasEntry; |
37 | 39 | import static org.hamcrest.collection.IsMapContaining.hasKey; |
| 40 | +import static org.mockito.Mockito.mock; |
| 41 | +import static org.mockito.Mockito.when; |
38 | 42 |
|
39 | 43 | public class AuthAPITest { |
40 | 44 |
|
@@ -256,6 +260,7 @@ public void shouldCreateUserInfoRequest() throws Exception { |
256 | 260 | assertThat(response.getValues(), hasEntry("created_at", "2016-12-05T11:16:59.640Z")); |
257 | 261 | assertThat(response.getValues(), hasEntry("sub", "auth0|58454...")); |
258 | 262 | assertThat(response.getValues(), hasKey("identities")); |
| 263 | + @SuppressWarnings("unchecked") |
259 | 264 | List<Map<String, Object>> identities = (List<Map<String, Object>>) response.getValues().get("identities"); |
260 | 265 | assertThat(identities, hasSize(1)); |
261 | 266 | assertThat(identities.get(0), hasEntry("user_id", "58454...")); |
@@ -497,6 +502,7 @@ public void shouldCreateSignUpRequestWithCustomParameters() throws Exception { |
497 | 502 | assertThat(body, hasEntry("connection", "db-connection")); |
498 | 503 | assertThat(body, hasEntry("client_id", CLIENT_ID)); |
499 | 504 | assertThat(body, hasKey("user_metadata")); |
| 505 | + @SuppressWarnings("unchecked") |
500 | 506 | Map<String, String> metadata = (Map<String, String>) body.get("user_metadata"); |
501 | 507 | assertThat(metadata, hasEntry("age", "25")); |
502 | 508 | assertThat(metadata, hasEntry("address", "123, fake street")); |
@@ -1004,6 +1010,7 @@ public void shouldCreateStartEmailPasswordlessFlowRequestWithCustomParams() thro |
1004 | 1010 | assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); |
1005 | 1011 | assertThat(body, hasEntry("email", "user@domain.com")); |
1006 | 1012 | assertThat(body, hasKey("authParams")); |
| 1013 | + @SuppressWarnings("unchecked") |
1007 | 1014 | Map<String, String> authParamsSent = (Map<String, String>) body.get("authParams"); |
1008 | 1015 | assertThat(authParamsSent, hasEntry("scope", authParams.get("scope"))); |
1009 | 1016 | assertThat(authParamsSent, hasEntry("state", authParams.get("state"))); |
@@ -1745,6 +1752,68 @@ public void shouldCreatePushedAuthorizationRequestWithAdditionalParams() throws |
1745 | 1752 | assertThat(response.getExpiresIn(), notNullValue()); |
1746 | 1753 | } |
1747 | 1754 |
|
| 1755 | + @Test |
| 1756 | + @SuppressWarnings("unchecked") |
| 1757 | + public void shouldCreatePushedAuthorizationRequestWithAuthDetails() throws Exception { |
| 1758 | + Map<String, Object> authorizationDetails = new HashMap<>(); |
| 1759 | + authorizationDetails.put("type", "account information"); |
| 1760 | + authorizationDetails.put("locations", Collections.singletonList("https://example.com/customers")); |
| 1761 | + authorizationDetails.put("actions", Arrays.asList("read", "write")); |
| 1762 | + List<Map<String, Object>> authDetailsList = Collections.singletonList(authorizationDetails); |
| 1763 | + |
| 1764 | + Request<PushedAuthorizationResponse> request = api.pushedAuthorizationRequest("https://domain.com/callback", "code", null, authDetailsList); |
| 1765 | + assertThat(request, is(notNullValue())); |
| 1766 | + |
| 1767 | + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); |
| 1768 | + PushedAuthorizationResponse response = request.execute().getBody(); |
| 1769 | + RecordedRequest recordedRequest = server.takeRequest(); |
| 1770 | + |
| 1771 | + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); |
| 1772 | + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); |
| 1773 | + |
| 1774 | + String body = readFromRequest(recordedRequest); |
| 1775 | + assertThat(body, containsString("client_id=" + CLIENT_ID)); |
| 1776 | + assertThat(body, containsString("redirect_uri=" + "https%3A%2F%2Fdomain.com%2Fcallback")); |
| 1777 | + assertThat(body, containsString("response_type=" + "code")); |
| 1778 | + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); |
| 1779 | + |
| 1780 | + String authDetailsParam = getQueryMap(body).get("authorization_details"); |
| 1781 | + String decodedAuthDetails = URLDecoder.decode(authDetailsParam, StandardCharsets.UTF_8.name()); |
| 1782 | + TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<List<Map<String, Object>>>() { |
| 1783 | + }; |
| 1784 | + List<Map<String, Object>> deserialized = ObjectMapperProvider.getMapper().readValue(decodedAuthDetails, typeReference); |
| 1785 | + assertThat(deserialized, notNullValue()); |
| 1786 | + assertThat(deserialized, hasSize(1)); |
| 1787 | + assertThat(deserialized.get(0).get("type"), is("account information")); |
| 1788 | + |
| 1789 | + List<String> locations = (List<String>) deserialized.get(0).get("locations"); |
| 1790 | + List<String> actions = (List<String>) deserialized.get(0).get("actions"); |
| 1791 | + |
| 1792 | + assertThat(locations, hasSize(1)); |
| 1793 | + assertThat(locations.get(0), is("https://example.com/customers")); |
| 1794 | + assertThat(actions, hasSize(2)); |
| 1795 | + assertThat(actions, contains("read", "write")); |
| 1796 | + |
| 1797 | + assertThat(response, is(notNullValue())); |
| 1798 | + assertThat(response.getRequestURI(), not(emptyOrNullString())); |
| 1799 | + assertThat(response.getExpiresIn(), notNullValue()); |
| 1800 | + } |
| 1801 | + |
| 1802 | + @Test |
| 1803 | + public void shouldThrowWhenCreatePushedAuthorizationRequestWithInvalidAuthDetails() { |
| 1804 | + // force Jackson to throw error on serialization |
| 1805 | + // see https://stackoverflow.com/questions/26716020/how-to-get-a-jsonprocessingexception-using-jackson |
| 1806 | + @SuppressWarnings("unchecked") |
| 1807 | + List<Map<String, Object>> mockList = mock(List.class); |
| 1808 | + when(mockList.toString()).thenReturn(mockList.getClass().getName()); |
| 1809 | + |
| 1810 | + IllegalArgumentException e = verifyThrows(IllegalArgumentException.class, |
| 1811 | + () -> api.pushedAuthorizationRequest("https://domain.com/callback", "code", null, mockList)); |
| 1812 | + |
| 1813 | + assertThat(e.getMessage(), is("'authorizationDetails' must be a list that can be serialized to JSON")); |
| 1814 | + assertThat(e.getCause(), instanceOf(JsonProcessingException.class)); |
| 1815 | + } |
| 1816 | + |
1748 | 1817 | @Test |
1749 | 1818 | public void shouldCreatePushedAuthorizationRequestWithoutSecret() throws Exception { |
1750 | 1819 | AuthAPI api = AuthAPI.newBuilder(server.getBaseUrl(), CLIENT_ID).build(); |
@@ -1842,6 +1911,77 @@ public void shouldCreatePushedAuthorizationJarRequestWithoutSecret() throws Exce |
1842 | 1911 | assertThat(response.getExpiresIn(), notNullValue()); |
1843 | 1912 | } |
1844 | 1913 |
|
| 1914 | + @Test |
| 1915 | + @SuppressWarnings("unchecked") |
| 1916 | + public void shouldCreatePushedAuthorizationJarRequestWithoutAuthDetails() throws Exception { |
| 1917 | + String requestJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"; |
| 1918 | + Map<String, Object> authorizationDetails = new HashMap<>(); |
| 1919 | + authorizationDetails.put("type", "account information"); |
| 1920 | + authorizationDetails.put("locations", Collections.singletonList("https://example.com/customers")); |
| 1921 | + authorizationDetails.put("actions", Arrays.asList("read", "write")); |
| 1922 | + List<Map<String, Object>> authDetailsList = Collections.singletonList(authorizationDetails); |
| 1923 | + |
| 1924 | + Request<PushedAuthorizationResponse> request = api.pushedAuthorizationRequestWithJAR(requestJwt, authDetailsList); |
| 1925 | + assertThat(request, is(notNullValue())); |
| 1926 | + |
| 1927 | + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); |
| 1928 | + PushedAuthorizationResponse response = request.execute().getBody(); |
| 1929 | + RecordedRequest recordedRequest = server.takeRequest(); |
| 1930 | + |
| 1931 | + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); |
| 1932 | + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); |
| 1933 | + |
| 1934 | + String body = readFromRequest(recordedRequest); |
| 1935 | + assertThat(body, containsString("client_id=" + CLIENT_ID)); |
| 1936 | + assertThat(body, containsString("request=" + requestJwt)); |
| 1937 | + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); |
| 1938 | + |
| 1939 | + String authDetailsParam = getQueryMap(body).get("authorization_details"); |
| 1940 | + String decodedAuthDetails = URLDecoder.decode(authDetailsParam, StandardCharsets.UTF_8.name()); |
| 1941 | + TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<List<Map<String, Object>>>() { |
| 1942 | + }; |
| 1943 | + List<Map<String, Object>> deserialized = ObjectMapperProvider.getMapper().readValue(decodedAuthDetails, typeReference); |
| 1944 | + assertThat(deserialized, notNullValue()); |
| 1945 | + assertThat(deserialized, hasSize(1)); |
| 1946 | + assertThat(deserialized.get(0).get("type"), is("account information")); |
| 1947 | + |
| 1948 | + List<String> locations = (List<String>) deserialized.get(0).get("locations"); |
| 1949 | + List<String> actions = (List<String>) deserialized.get(0).get("actions"); |
| 1950 | + |
| 1951 | + assertThat(locations, hasSize(1)); |
| 1952 | + assertThat(locations.get(0), is("https://example.com/customers")); |
| 1953 | + assertThat(actions, hasSize(2)); |
| 1954 | + assertThat(actions, contains("read", "write")); |
| 1955 | + |
| 1956 | + assertThat(response, is(notNullValue())); |
| 1957 | + assertThat(response.getRequestURI(), not(emptyOrNullString())); |
| 1958 | + assertThat(response.getExpiresIn(), notNullValue()); |
| 1959 | + } |
| 1960 | + |
| 1961 | + @Test |
| 1962 | + @SuppressWarnings("unchecked") |
| 1963 | + public void shouldThrowWhenCreatePushedAuthorizationJarRequestWithInvalidAuthDetails() { |
| 1964 | + String requestJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"; |
| 1965 | + // force Jackson to throw error on serialization |
| 1966 | + // see https://stackoverflow.com/questions/26716020/how-to-get-a-jsonprocessingexception-using-jackson |
| 1967 | + List mockList = mock(List.class); |
| 1968 | + when(mockList.toString()).thenReturn(mockList.getClass().getName()); |
| 1969 | + |
| 1970 | + IllegalArgumentException e = verifyThrows(IllegalArgumentException.class, |
| 1971 | + () -> api.pushedAuthorizationRequestWithJAR(requestJwt, mockList)); |
| 1972 | + |
| 1973 | + assertThat(e.getMessage(), is("'authorizationDetails' must be a list that can be serialized to JSON")); |
| 1974 | + assertThat(e.getCause(), instanceOf(JsonProcessingException.class)); |
| 1975 | + } |
| 1976 | + |
| 1977 | + private Map<String, String> getQueryMap(String input) { |
| 1978 | + String[] params = input.split("&"); |
| 1979 | + |
| 1980 | + return Arrays.stream(params) |
| 1981 | + .map(param -> param.split("=")) |
| 1982 | + .collect(Collectors.toMap(p -> p[0], p -> p[1])); |
| 1983 | + } |
| 1984 | + |
1845 | 1985 | static class TestAssertionSigner implements ClientAssertionSigner { |
1846 | 1986 |
|
1847 | 1987 | private final String token; |
|
0 commit comments