@Override
  public Optional<AuthenticatedDevice> authenticate(BasicCredentials basicCredentials) {
    boolean succeeded = false;
    String failureReason = null;

    try {
      final UUID accountUuid;
      final byte deviceId;
      {
        final Pair<String, Byte> identifierAndDeviceId = getIdentifierAndDeviceId(basicCredentials.getUsername());

        accountUuid = UUID.fromString(identifierAndDeviceId.first());
        deviceId = identifierAndDeviceId.second();
      }

      Optional<Account> account = accountsManager.getByAccountIdentifier(accountUuid);

      if (account.isEmpty()) {
        failureReason = "noSuchAccount";
        return Optional.empty();
      }

      Optional<Device> device = account.get().getDevice(deviceId);

      if (device.isEmpty()) {
        failureReason = "noSuchDevice";
        return Optional.empty();
      }

      SaltedTokenHash deviceSaltedTokenHash = device.get().getAuthTokenHash();
      if (deviceSaltedTokenHash.verify(basicCredentials.getPassword())) {
        succeeded = true;
        Account authenticatedAccount = updateLastSeen(account.get(), device.get());
        if (deviceSaltedTokenHash.getVersion() != SaltedTokenHash.CURRENT_VERSION) {
          OLD_TOKEN_VERSION_COUNTER.increment();
          authenticatedAccount = accountsManager.updateDeviceAuthentication(
              authenticatedAccount,
              device.get(),
              SaltedTokenHash.generateFor(basicCredentials.getPassword()));  // new credentials have current version
        }
        return Optional.of(new AuthenticatedDevice(authenticatedAccount, device.get()));
      } else {
        failureReason = "incorrectPassword";
        return Optional.empty();
      }
    } catch (IllegalArgumentException | InvalidAuthorizationHeaderException iae) {
      failureReason = "invalidHeader";
      return Optional.empty();
    } finally {
      Tags tags = Tags.of(
          AUTHENTICATION_SUCCEEDED_TAG_NAME, String.valueOf(succeeded));

      if (StringUtils.isNotBlank(failureReason)) {
        tags = tags.and(AUTHENTICATION_FAILURE_REASON_TAG_NAME, failureReason);
      }

      Metrics.counter(AUTHENTICATION_COUNTER_NAME, tags).increment();
    }
  }
@Test
  void testAuthenticateNonDefaultDevice() {
    final UUID uuid = UUID.randomUUID();
    final byte deviceId = 2;
    final String password = "12345";

    final Account account = mock(Account.class);
    final Device device = mock(Device.class);
    final SaltedTokenHash credentials = mock(SaltedTokenHash.class);

    clock.unpin();
    when(accountsManager.getByAccountIdentifier(uuid)).thenReturn(Optional.of(account));
    when(account.getUuid()).thenReturn(uuid);
    when(account.getDevice(deviceId)).thenReturn(Optional.of(device));
    when(device.getId()).thenReturn(deviceId);
    when(device.getAuthTokenHash()).thenReturn(credentials);
    when(credentials.verify(password)).thenReturn(true);
    when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION);

    final Optional<AuthenticatedDevice> maybeAuthenticatedAccount =
        accountAuthenticator.authenticate(new BasicCredentials(uuid + "." + deviceId, password));

    assertThat(maybeAuthenticatedAccount).isPresent();
    assertThat(maybeAuthenticatedAccount.get().getAccount().getUuid()).isEqualTo(uuid);
    assertThat(maybeAuthenticatedAccount.get().getAuthenticatedDevice()).isEqualTo(device);
    verify(accountsManager, never()).updateDeviceAuthentication(any(), any(), any());
  }