Skip to content

Commit

Permalink
[eclipse-hono#2292] Adopt authInfo properties in credentials clientCo…
Browse files Browse the repository at this point in the history
…ntext.

Signed-off-by: Carsten Lohmann <[email protected]>
  • Loading branch information
calohmn committed Nov 13, 2020
1 parent d454ebb commit dbf7390
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,29 @@ public UsernamePasswordCredentials getCredentials(final JsonObject authInfo) {
final String password = JsonHelper.getValue(authInfo, CredentialsConstants.FIELD_PASSWORD, String.class, null);
if (username == null || password == null) {
return null;
} else if (password.isEmpty()) {
return tryGetCredentialsEncodedInUsername(username);
}
final JsonObject clientContext = authInfo.copy();
clientContext.remove(CredentialsConstants.FIELD_USERNAME);
clientContext.remove(CredentialsConstants.FIELD_PASSWORD);

if (password.isEmpty()) {
return tryGetCredentialsEncodedInUsername(username, clientContext);
} else {
return UsernamePasswordCredentials.create(username, password);
return UsernamePasswordCredentials.create(username, password, clientContext);
}
}

private UsernamePasswordCredentials tryGetCredentialsEncodedInUsername(final String username) {
private UsernamePasswordCredentials tryGetCredentialsEncodedInUsername(
final String username,
final JsonObject clientContext) {

try {
final String decoded = new String(Base64.getDecoder().decode(username));
final int colonIdx = decoded.indexOf(":");
if (colonIdx > -1) {
final String user = decoded.substring(0, colonIdx);
final String pass = decoded.substring(colonIdx + 1);
return UsernamePasswordCredentials.create(user, pass);
return UsernamePasswordCredentials.create(user, pass, clientContext);
} else {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.vertx.core.json.JsonObject;

/**
* Helper class to parse username/password credentials provided by devices during authentication into properties to be
* used with Hono's <em>Credentials</em> API.
Expand All @@ -35,8 +37,8 @@ public class UsernamePasswordCredentials extends AbstractDeviceCredentials {

private String password;

private UsernamePasswordCredentials(final String tenantId, final String authId) {
super(tenantId, authId);
private UsernamePasswordCredentials(final String tenantId, final String authId, final JsonObject clientContext) {
super(tenantId, authId, clientContext);
}

/**
Expand All @@ -48,17 +50,35 @@ private UsernamePasswordCredentials(final String tenantId, final String authId)
* @throws NullPointerException if any of the parameters is {@code null}.
*/
public static final UsernamePasswordCredentials create(final String username, final String password) {
return create(username, password, new JsonObject());
}

/**
* Creates a new instance for a set of credentials.
*
* @param username The username provided by the device.
* @param password The password provided by the device.
* @param clientContext The client context that can be used to get credentials from the Credentials API.
* @return The credentials or {@code null} if the username does not contain a tenant ID.
* @throws NullPointerException if any of the parameters is {@code null}.
*/
public static final UsernamePasswordCredentials create(
final String username,
final String password,
final JsonObject clientContext) {

Objects.requireNonNull(username);
Objects.requireNonNull(password);
Objects.requireNonNull(clientContext);

// username consists of <userId>@<tenantId>
final String[] userComponents = username.split("@", 2);
if (userComponents.length != 2) {
LOG.trace("username [{}] does not comply with expected pattern [<authId>@<tenantId>]", username);
return null;
}
final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userComponents[1], userComponents[0]);
final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userComponents[1],
userComponents[0], clientContext);
credentials.password = password;
return credentials;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.eclipse.hono.adapter.client.registry.CredentialsClient;
Expand Down Expand Up @@ -276,4 +277,31 @@ public void testGetCredentialsHandlesMalformedBase64InUsername() {

assertThat(credentials).isNull();
}

/**
* Verifies that the provider adopts properties from the authInfo JSON into the clientContext
* of the credentials object.
*
*/
@Test
public void testGetCredentialsSetsClientContext() {

final String username = "device" + "@" + Constants.DEFAULT_TENANT;

final JsonObject originalCredentials = new JsonObject()
.put(CredentialsConstants.FIELD_USERNAME, username)
.put(CredentialsConstants.FIELD_PASSWORD, "the-secret")
.put("client-id", "the-client-id");
final UsernamePasswordCredentials credentials = provider.getCredentials(originalCredentials);

assertThat(credentials).isNotNull();
assertThat(credentials.getAuthId()).isEqualTo("device");
assertThat(credentials.getTenantId()).isEqualTo(Constants.DEFAULT_TENANT);
assertThat(credentials.getPassword()).isEqualTo("the-secret");

assertThat(credentials.getClientContext().size()).isEqualTo(1);
final Map.Entry<String, Object> firstClientContextEntry = credentials.getClientContext().stream().iterator().next();
assertThat(firstClientContextEntry.getKey()).isEqualTo("client-id");
assertThat(firstClientContextEntry.getValue()).isEqualTo("the-client-id");
}
}

0 comments on commit dbf7390

Please sign in to comment.