Issue
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 href="https://github.com/GoogleCloudPlatform/java-docs-samples/blob/HEAD/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java" rel="nofollow noreferrer">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:
- I generated key of format X509 openssl req -x509 -nodes -newkey rsa:2048 -keyout rsa_private.pem -out rsa_cert.pem -subj "/CN=unused" it also generated certificate rsa_cer.pem
- I converted the key to PKCS8 format openssl pkcs8 -topk8 -inform PEM -outform DER -in rsa_private.pem -out private_key.der -nocrypt
- The certificate I added as public key in Iot-core and rsa_private.der I used in my createJwtRsa method
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
Solution
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);
Answered By - Przemek Grabarek
Answer Checked By - Candace Johnson (JavaFixing Volunteer)