Skip to content

Commit

Permalink
apply host validation to configured token oauth token endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Dominik Guggemos <dominik.guggemos@bosch.io>
  • Loading branch information
dguggemos committed Nov 8, 2021
1 parent c960a29 commit 405612c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,9 @@ void validate(final Connection connection, final DittoHeaders dittoHeaders, fina
.ifPresent(tunnel -> SshTunnelValidator.getInstance(dittoHeaders, hostValidator).validate(tunnel));

// validate credentials
connection.getCredentials().ifPresent(credentials ->
credentials.accept(CredentialsValidationVisitor.of(connection, dittoHeaders, connectivityConfig)));
connection.getCredentials()
.ifPresent(credentials -> credentials.accept(
CredentialsValidationVisitor.of(connection, dittoHeaders, connectivityConfig, hostValidator)));

// protocol specific validations
final AbstractProtocolValidator spec = specMap.get(connection.getConnectionType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,23 @@ final class CredentialsValidationVisitor implements CredentialsVisitor<Void> {
private final Connection connection;
private final DittoHeaders dittoHeaders;
private final Set<String> algorithms;
private final HostValidator hostValidator;

private static final String ALLOWED_CHARACTERS = "\\x21\\x23-\\x5B\\x5D-\\x7E";
private static final Pattern REQUESTED_SCOPES_REGEX =
Pattern.compile("^[" + ALLOWED_CHARACTERS + "]+( [" + ALLOWED_CHARACTERS + "]+)*$");

private CredentialsValidationVisitor(final Connection connection, final DittoHeaders dittoHeaders,
final ConnectivityConfig config) {
final ConnectivityConfig config, final HostValidator hostValidator) {
this.connection = connection;
this.dittoHeaders = dittoHeaders;
algorithms = config.getConnectionConfig().getHttpPushConfig().getHmacAlgorithms().keySet();
this.hostValidator = hostValidator;
}

static CredentialsValidationVisitor of(final Connection connection, final DittoHeaders dittoHeaders,
final ConnectivityConfig connectivityConfig) {
return new CredentialsValidationVisitor(connection, dittoHeaders, connectivityConfig);
final ConnectivityConfig connectivityConfig, final HostValidator hostValidator) {
return new CredentialsValidationVisitor(connection, dittoHeaders, connectivityConfig, hostValidator);
}

@Override
Expand Down Expand Up @@ -113,15 +115,7 @@ public Void oauthClientCredentials(final OAuthClientCredentials credentials) {
.dittoHeaders(dittoHeaders)
.build();
}
try {
new URL(credentials.getTokenEndpoint());
} catch (final Exception e) {
throw ConnectionConfigurationInvalidException.newBuilder(
"Invalid token endpoint provided: " + e.getMessage())
.description("Provide a valid URL as token endpoint.")
.dittoHeaders(dittoHeaders)
.build();
}
validateTokenEndpoint(credentials.getTokenEndpoint());
if (!REQUESTED_SCOPES_REGEX.matcher(credentials.getRequestedScopes()).matches()) {
throw ConnectionConfigurationInvalidException.newBuilder(
"Invalid format of requested scopes: " + credentials.getRequestedScopes())
Expand All @@ -132,4 +126,18 @@ public Void oauthClientCredentials(final OAuthClientCredentials credentials) {
}
return null;
}

private void validateTokenEndpoint(final String tokenEndpoint) {
final URL url;
try {
url = new URL(tokenEndpoint);
} catch (final Exception e) {
throw ConnectionConfigurationInvalidException.newBuilder(
String.format("Invalid token endpoint '%s' provided: %s", tokenEndpoint, e.getMessage()))
.description("Provide a valid URL as token endpoint.")
.dittoHeaders(dittoHeaders)
.build();
}
hostValidator.validateHostname(url.getHost(), dittoHeaders);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ public void acceptHttpConnectionWithValidClientCredentials() {
.clientId("id")
.clientSecret("secret")
.scope("scope")
.tokenEndpoint("https://localhost/token")
.tokenEndpoint("https://8.8.4.4/token")
.build())
.build();
final ConnectionValidator underTest = getConnectionValidator();
Expand All @@ -584,7 +584,23 @@ public void rejectInvalidTokenEndpointForOauthClientCredentials() {
final ConnectionValidator underTest = getConnectionValidator();
assertThatExceptionOfType(ConnectionConfigurationInvalidException.class)
.isThrownBy(() -> underTest.validate(connection, DittoHeaders.empty(), actorSystem))
.withMessageContaining("Invalid token endpoint provided");
.withMessageContaining("Invalid token endpoint");
}

@Test
public void rejectBlockedTokenEndpointForOauthClientCredentials() {
final Connection connection = createHttpConnection().toBuilder()
.credentials(OAuthClientCredentials.newBuilder()
.clientId("id")
.clientSecret("secret")
.scope("scope")
.tokenEndpoint("http://8.8.8.8/token")
.build())
.build();
final ConnectionValidator underTest = getConnectionValidator();
assertThatExceptionOfType(ConnectionConfigurationInvalidException.class)
.isThrownBy(() -> underTest.validate(connection, DittoHeaders.empty(), actorSystem))
.withMessageContaining("the host is blocked");
}

@Test
Expand All @@ -594,7 +610,7 @@ public void rejectInvalidScopesForOauthClientCredentials() {
.clientId("id")
.clientSecret("secret")
.scope("\"scope1\" scope2")
.tokenEndpoint("http://localhost/token")
.tokenEndpoint("http://8.8.4.4/token")
.build())
.build();
final ConnectionValidator underTest = getConnectionValidator();
Expand Down

0 comments on commit 405612c

Please sign in to comment.