I'm following this google guide on how to sign urls manually since I need to create a signed URL in other to let other user upload files without having to authenticate manually and while I manage to follow all steps required and showed in the python example, my java code always receives an io.grpc.StatusRuntimeException: INVALID_ARGUMENT: Request contains an invalid argument.
I'm getting crazy trying to find what is the issue and I'm not sure if I'm doing it correctly.
The dependency I'm using to signBlob is the google-cloud-iamcredentials. Is there something I'm missing out?
Here you can check the code
try (IamCredentialsClient iamCredentialsClient = IamCredentialsClient.create()){
final LocalDateTime currentTime = LocalDateTime.now();
final String completeTimeStamp = currentTime.format(DateTimeFormatter.ofPattern("yyyyMMdd HHmmss"))
.replace(" ", "T") + 'Z';
final String pathToResource = "/" + filename;
final String credentialScope = currentTime.format(DateTimeFormatter.BASIC_ISO_DATE) + "/eu/storage/goog4_request";
String credential = clientEmail + '/' + credentialScope;
credential = credential.replace("@", "%40");
credential = credential.replace("/", "%2F");
final String canonicalHeader = "host:" + bucketName + ".storage.googleapis.com\n";
final String signedHeader = "host";
final String canonicalQueryString =
"X-Goog-Algorithm=GOOG4-RSA-SHA256&" +
"X-Goog-Credential=" + credential + '&' +
"X-Goog-Date=" + completeTimeStamp + '&' +
"X-Goog-Expires=" + expiration + '&' +
"X-Goog-SignedHeaders=" + signedHeader;
final String canonicalRequest =
"PUT" + '\n' +
pathToResource + '\n' +
canonicalQueryString + '\n' +
canonicalHeader + '\n' +
signedHeader + '\n' +
"UNSIGNED-PAYLOAD";
final String hashedCanonicalRequest =
DigestUtils.sha256Hex(canonicalRequest.getBytes(StandardCharsets.UTF_8));
final String stringToSign = "GOOG4-RSA-SHA256" + '\n' +
completeTimeStamp + '\n' +
credentialScope + '\n' +
hashedCanonicalRequest;
final String signature = iamCredentialsClient.signBlobCallable()
.call(
SignBlobRequest.newBuilder()
.setName(ServiceAccountName.of(projectId, clientEmail).toString())
.addAllDelegates(new ArrayList<>())
.setPayload(ByteString.copyFrom(stringToSign.getBytes(StandardCharsets.UTF_8)))
.build()
).toString();
return String.format(CLOUD_URL, pathToResource,
canonicalQueryString, "&X-Goog-Signature=".concat(signature));