I want to connect my backend on Spring boot to one of the devices in my hardware setup in Google Cloud Iot-Core. I basically copied this github repository and adjusted the authentication and connection options. When I run my program it throws this exception:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.eclipse.paho.client.mqttv3.MqttClient]: Factory method 'connectToMqttClient' threw exception; nested exception is Incorrect username or password (4)
To create password I use this method
private static String createJwtRsa(String projectId, String privateKeyFile)
throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
DateTime now = new DateTime();
JwtBuilder jwtBuilder =
Jwts.builder()
.setIssuedAt(now.toDate())
.setExpiration(now.plusMinutes(20).toDate())
.setAudience(projectId);
byte[] keyBytes = Files.readAllBytes(Paths.get(privateKeyFile));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return jwtBuilder.signWith(SignatureAlgorithm.RS256, kf.generatePrivate(spec)).compact();
}
I had an issue with privateKeyFile format. On Iot-core the device has public key of RS256_X509
But Spring Boot only allows RS256_PKCS8 key formats, so I had to do this:
Since then I get the exception: Incorrect Username and password. What can I do to fix it?
Edit:
I also tried generating normal RSA256 key and convert it to PKCS8 format, and I get the same exception. The same with ES256 key
I managed to fix the issue! the clientId was incorrect
final String mqttClientId = String.format("projects/%s/locations/%s/registries/%s/devices/%s",
options.projectId, options.cloudRegion, options.registryId, options.gatewayId);
My gatewayId was an empty string because we don't have a gateway created on Iot Core, we connect directly to devices. So today I set gatewayId to deviceId and the backend connected successfully to the device. So now the line looks like this
final String mqttClientId = String.format("projects/%s/locations/%s/registries/%s/devices/%s",options.projectId,
options.cloudRegion, options.registryId, options.deviceId);