diff --git a/src/main/java/org/solid/testharness/config/TestSubject.java b/src/main/java/org/solid/testharness/config/TestSubject.java index bb3bb0e0..9b81d6a8 100644 --- a/src/main/java/org/solid/testharness/config/TestSubject.java +++ b/src/main/java/org/solid/testharness/config/TestSubject.java @@ -226,7 +226,7 @@ URI findStorage() throws TestHarnessException { final Model profile; try { profile = publicClient.getContentAsModel(webId); - logger.info("Loaded WebID Document for [{}]", webId); + logger.info("Read WebID Document for [{}]", webId); } catch (Exception e) { throw new TestHarnessInitializationException(MessageFormat.format( "Failed to read WebID Document for [{0}]", webId), e); diff --git a/src/main/java/org/solid/testharness/http/AuthManager.java b/src/main/java/org/solid/testharness/http/AuthManager.java index dac7d232..c5588f63 100644 --- a/src/main/java/org/solid/testharness/http/AuthManager.java +++ b/src/main/java/org/solid/testharness/http/AuthManager.java @@ -45,10 +45,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.text.MessageFormat; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -117,6 +114,9 @@ public SolidClientProvider authenticate(@NotNull final String user) { throw new TestHarnessInitializationException(MessageFormat.format( "No user credentials were provided for {0}", user)); } + + checkWebId(userConfig.webId()); + final URI oidcIssuer = Optional.ofNullable(userConfig.getIdp()).orElse(config.getSolidIdentityProvider()); authClient = new Client.Builder(user) @@ -150,6 +150,19 @@ public SolidClientProvider authenticate(@NotNull final String user) { return new SolidClientProvider(authClient); } + void checkWebId(final String webId) { + try { + Objects.requireNonNull(webId, "webId is required"); + final var webIdUri = URI.create(webId); + final var publicClient = new SolidClientProvider(ClientRegistry.ALICE_WEBID); + publicClient.getContentAsModel(webIdUri); + logger.info("Loaded WebID Document for [{}]", webId); + } catch (Exception e) { + throw new TestHarnessInitializationException(MessageFormat.format( + "Failed to read WebID Document for [{0}]", webId), e); + } + } + void exchangeRefreshToken(final Client authClient, final UserCredentials userConfig, final OidcConfiguration oidcConfig) { logger.info("Exchange refresh token for {}: [{}]", authClient.getUser(), userConfig.webId()); diff --git a/src/test/java/org/solid/testharness/http/AuthManagerTest.java b/src/test/java/org/solid/testharness/http/AuthManagerTest.java index 2f19bd14..80ed609d 100644 --- a/src/test/java/org/solid/testharness/http/AuthManagerTest.java +++ b/src/test/java/org/solid/testharness/http/AuthManagerTest.java @@ -43,6 +43,9 @@ @QuarkusTest @QuarkusTestResource(AuthenticationResource.class) class AuthManagerTest { + public static final Map ALICE_WEBID_MAP = Map.of(HttpConstants.ALICE, + "https://alice.target.example.org/profile/card#me"); + private URI baseUri; @Inject @@ -71,23 +74,66 @@ void registerUser() { assertDoesNotThrow(() -> authManager.registerUser(HttpConstants.ALICE)); } + @Test + void authenticateNoWebIdInCredentials() { + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); + when(config.getSolidIdentityProvider()).thenReturn(baseUri); + when(config.getCredentials("nowebid")).thenReturn(new TestCredentials()); + + final TestHarnessInitializationException exception = assertThrows(TestHarnessInitializationException.class, + () -> authManager.authenticate("nowebid")); + + assertEquals("Failed to read WebID Document for [null] " + + "Caused by: java.lang.NullPointerException: webId is required", + exception.getMessage()); + } + + @Test + void authenticateInvalidWebID() { + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); + final var credentials = new TestCredentials(); + credentials.webId = "not a web id"; + when(config.getCredentials("notwebid")).thenReturn(credentials); + final TestHarnessInitializationException exception = assertThrows(TestHarnessInitializationException.class, + () -> authManager.authenticate("notwebid")); + assertEquals("Failed to read WebID Document for [not a web id] Caused by: " + + "java.lang.IllegalArgumentException: Illegal character in path at index 3: not a web id", + exception.getMessage()); + } + + @Test + void authenticateNotFoundWebID() { + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); + final var credentials = new TestCredentials(); + credentials.webId = baseUri.resolve("404webID").toString(); + when(config.getCredentials("notfoundwebid")).thenReturn(credentials); + final TestHarnessInitializationException exception = assertThrows(TestHarnessInitializationException.class, + () -> authManager.authenticate("notfoundwebid")); + assertEquals("Failed to read WebID Document for [" + credentials.webId + "] Caused by: " + + "org.solid.testharness.utils.TestHarnessException: " + + "Error response=404 trying to get content for " + credentials.webId, + exception.getMessage()); + } + + @Test void authenticateNoCredentials() { - when(config.getWebIds()).thenReturn(Map.of(HttpConstants.ALICE, - "https://alice.target.example.org/profile/card#me")); + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); when(config.getSolidIdentityProvider()).thenReturn(baseUri); - when(config.getCredentials("nocredentials")).thenReturn(new TestCredentials()); + final var credentials = new TestCredentials(); + credentials.webId = baseUri.resolve("webID").toString(); + when(config.getCredentials("nocredentials")).thenReturn(credentials); final TestHarnessInitializationException exception = assertThrows(TestHarnessInitializationException.class, () -> authManager.authenticate("nocredentials")); - assertEquals("Neither login credentials nor refresh token details provided for nocredentials: [null]", + assertEquals("Neither login credentials nor refresh token details provided for nocredentials: [" + + credentials.webId + "]", exception.getMessage()); } @Test void authenticateLoginSession() { - when(config.getWebIds()).thenReturn(Map.of(HttpConstants.ALICE, - "https://alice.target.example.org/profile/card#me")); + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); when(config.getOrigin()).thenReturn("https://origin/goodcode"); setupLogin(baseUri, "login", "/login/password", null); @@ -99,8 +145,7 @@ void authenticateLoginSession() { @Test void authenticateLoginUserRegistration() { - when(config.getWebIds()).thenReturn(Map.of(HttpConstants.ALICE, - "https://alice.target.example.org/profile/card#me")); + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); when(config.getOrigin()).thenReturn("https://origin/form"); setupLogin(baseUri, "login", "/login/password", "/idp/register"); @@ -113,10 +158,10 @@ void authenticateLoginUserRegistration() { @Test void authenticateRefreshCredentials() { - when(config.getWebIds()).thenReturn(Map.of(HttpConstants.ALICE, - "https://alice.target.example.org/profile/card#me")); + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); when(config.getSolidIdentityProvider()).thenReturn(baseUri); final TestCredentials credentials = new TestCredentials(); + credentials.webId = baseUri.resolve("webID").toString(); credentials.refreshToken = Optional.of("REFRESH"); credentials.clientId = Optional.of("CLIENTID"); credentials.clientSecret = Optional.of("CLIENTSECRET"); @@ -130,10 +175,10 @@ void authenticateRefreshCredentials() { @Test void authenticateClientCredentials() { - when(config.getWebIds()).thenReturn(Map.of(HttpConstants.ALICE, - "https://alice.target.example.org/profile/card#me")); + when(config.getWebIds()).thenReturn(ALICE_WEBID_MAP); when(config.getSolidIdentityProvider()).thenReturn(baseUri); final TestCredentials credentials = new TestCredentials(); + credentials.webId = baseUri.resolve("webID").toString(); credentials.clientId = Optional.of("CLIENTID"); credentials.clientSecret = Optional.of("CLIENTSECRET"); when(config.getCredentials("client_credentials")).thenReturn(credentials); @@ -158,6 +203,7 @@ private void setupLogin(final URI idpBaseUri, final String testId, when(config.getUserRegistrationEndpoint()).thenReturn(idpBaseUri.resolve(userRegistrationEndpoint)); } final TestCredentials credentials = new TestCredentials(); + credentials.webId = baseUri.resolve("webID").toString(); credentials.username = Optional.of("USERNAME"); credentials.password = Optional.of("PASSWORD"); when(config.getCredentials(testId)).thenReturn(credentials); diff --git a/src/test/java/org/solid/testharness/http/AuthenticationResource.java b/src/test/java/org/solid/testharness/http/AuthenticationResource.java index ab4fcb92..4cfe3ff0 100644 --- a/src/test/java/org/solid/testharness/http/AuthenticationResource.java +++ b/src/test/java/org/solid/testharness/http/AuthenticationResource.java @@ -75,6 +75,13 @@ public Map start() { wireMockServer.stubFor(WireMock.post(WireMock.urlEqualTo("/idp/register")) .willReturn(WireMock.aResponse().withStatus(200))); + // webID responses + wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/404webID")) + .willReturn(WireMock.aResponse().withStatus(404))); + + wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/webID")) + .willReturn(WireMock.aResponse().withStatus(200))); + // return OIDC configuration wireMockServer.stubFor(WireMock.get(WireMock.urlEqualTo("/" + HttpConstants.OPENID_CONFIGURATION)) .willReturn(WireMock.aResponse()