/** * Retrieves credentials from the Credentials service. * * @param deviceCredentials The credentials provided by the device. * @param spanContext The {@code SpanContext} (may be {@code null}). * @return A future containing the credentials on record as retrieved from * Hono's <em>Credentials</em> API. * @throws NullPointerException if device credentials is {@code null}. */ protected final Future<CredentialsObject> getCredentialsForDevice(final DeviceCredentials deviceCredentials, final SpanContext spanContext) { Objects.requireNonNull(deviceCredentials); if (credentialsServiceClient == null) { return Future.failedFuture(new IllegalStateException("Credentials API client is not set")); } else { return getCredentialsClient(deviceCredentials.getTenantId()).compose(client -> client.get(deviceCredentials.getType(), deviceCredentials.getAuthId(), new JsonObject(), spanContext)); } }
/** * Sets up the fixture. */ @Before public void setUp() { credentialsClient = mock(CredentialsClient.class); when(credentialsClient.isOpen()).thenReturn(Boolean.TRUE); honoClient = mock(HonoClient.class); when(honoClient.getOrCreateCredentialsClient(anyString())).thenReturn(Future.succeededFuture(credentialsClient)); provider = getProvider(getDeviceCredentials("type", "TENANT", "user"), NoopTracerFactory.create()); }
/** * Retrieves credentials from the Credentials service. * * @param deviceCredentials The credentials provided by the device. * @return A future containing the credentials on record as retrieved from * Hono's <em>Credentials</em> API. * @throws NullPointerException if device credentials is {@code null}. */ protected final Future<CredentialsObject> getCredentialsForDevice(final DeviceCredentials deviceCredentials) { Objects.requireNonNull(deviceCredentials); if (credentialsServiceClient == null) { return Future.failedFuture(new IllegalStateException("Credentials API client is not set")); } else { return getCredentialsClient(deviceCredentials.getTenantId()).compose(client -> client.get(deviceCredentials.getType(), deviceCredentials.getAuthId())); } }
/** * Verifies that the auth provider propagates the exception reported by a failed invocation * of the credentials service. * * @param ctx The vert.x test context. */ @Test public void testAuthenticateFailsWithExceptionReportedByCredentialsClient(final TestContext ctx) { final ServerErrorException reportedException = new ServerErrorException(503); when(credentialsClient.get(anyString(), anyString(), any(JsonObject.class), any())).thenReturn(Future.failedFuture(reportedException)); provider.authenticate(new JsonObject(), ctx.asyncAssertFailure(t -> { ctx.assertEquals(t, reportedException); })); }
/** * Verifies that the auth provider fails an authentication request with a 401 * {@code ClientErrorException} if the auth-id is unknown. * * @param ctx The vert.x test context. */ @Test public void testAuthenticateFailsWith401ForNonExistingAuthId(final TestContext ctx) { // WHEN trying to authenticate using an auth-id that is not known when(credentialsClient.get(anyString(), eq("user"), any(JsonObject.class), any())) .thenReturn(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND))); provider.authenticate(new JsonObject(), ctx.asyncAssertFailure(t -> { // THEN authentication fails with a 401 client error ctx.assertEquals(HttpURLConnection.HTTP_UNAUTHORIZED, ((ClientErrorException) t).getErrorCode()); })); }
/** * Get pre-shared-key for device from credentials service. * <p> * On success, add hono device to cache. * * @param handshakeIdentity pre-shared-key identity of device. * @return future with pre-shared-key. */ protected final Future<byte[]> getSharedKeyForDevice(final PreSharedKeyDeviceIdentity handshakeIdentity) { Objects.requireNonNull(handshakeIdentity); return credentialsServiceClient.getOrCreateCredentialsClient(handshakeIdentity.getTenantId()) .compose(client -> client.get(handshakeIdentity.getType(), handshakeIdentity.getAuthId())) .compose((credentials) -> { final byte[] key = getCandidateKey(credentials); if (key != null) { devices.put(handshakeIdentity, new Device(handshakeIdentity.getTenantId(), credentials.getDeviceId())); return Future.succeededFuture(key); } else { return Future.failedFuture("secret key missing!"); } }); }
/** * Sets up the fixture. */ @Before public void setUp() { credentialsOnRecord = new CredentialsObject() .setAuthId("device") .setDeviceId("4711") .setType(CredentialsConstants.SECRETS_TYPE_HASHED_PASSWORD) .setEnabled(true); credentialsClient = mock(CredentialsClient.class); when(credentialsClient.get(anyString(), anyString(), any(JsonObject.class), any())).thenReturn(Future.succeededFuture(credentialsOnRecord)); credentialsServiceClient = mock(HonoClient.class); when(credentialsServiceClient.getOrCreateCredentialsClient(anyString())).thenReturn(Future.succeededFuture(credentialsClient)); pwdEncoder = mock(HonoPasswordEncoder.class); when(pwdEncoder.matches(anyString(), any(JsonObject.class))).thenReturn(true); provider = new UsernamePasswordAuthProvider(credentialsServiceClient, pwdEncoder, new ServiceConfigProperties(), NoopTracerFactory.create()); }
/** * Verifies that credentials validation fails if the credentials on record are disabled. * * @param ctx The vert.x test context. */ @Test public void testValidateFailsIfCredentialsAreDisabled(final TestContext ctx) { // WHEN trying to authenticate a disabled device final AbstractDeviceCredentials creds = getDeviceCredentials("type", "tenant", "identity"); final CredentialsObject credentialsOnRecord = getCredentialsObject("type", "identity", "device", false) .addSecret(CredentialsObject.emptySecret(Instant.now().minusSeconds(120), null)); when(credentialsClient.get(eq("type"), eq("identity"), any(JsonObject.class), any())) .thenReturn(Future.succeededFuture(credentialsOnRecord)); provider.authenticate(creds, null, ctx.asyncAssertFailure(t -> { // THEN authentication fails with a 401 client error ctx.assertEquals(HttpURLConnection.HTTP_UNAUTHORIZED, ((ClientErrorException) t).getErrorCode()); })); }