0
votes

I'm trying to generate in Java an SAS Token for a file in an Azure Data Lake Gen. 2 storage account, but everytime, I get the error "Signature fields not well formed" when I try to access the file with the generated token.

A similar problem was already discussed, but there an older version of Azure SDK was used and the signature was created manually. I'm using the latest version azure-storage-8.6.3 but also tried 8.0.0 and 7.0.0 without success.

Here's my code:

public class SasTokenExample {

    public static String generateSasToken(URI fileUri) throws StorageException, URISyntaxException, InvalidKeyException {
        StorageCredentials credentials = new StorageCredentialsAccountAndKey("myaccount", "thisisnottheac+tualkeybutonlyanexampletode+monstratewhatsgoingonhere+12+34567890123456==");
        CloudFile file = new CloudFile(fileUri, credentials);

        SharedAccessFilePolicy policy = new SharedAccessFilePolicy();
        policy.setPermissions(EnumSet.of(SharedAccessFilePermissions.READ));
        policy.setSharedAccessStartTime(null);
        policy.setSharedAccessExpiryTime(getExpirationTime());

        return file.generateSharedAccessSignature(policy, null);
    }

    private static Date getExpirationTime() {
        LocalDateTime expLDT = LocalDateTime.now().plusMinutes(30);
        Instant expInstant = expLDT.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(expInstant);
    }

    public static void main(String[] args) throws URISyntaxException, InvalidKeyException, StorageException, MalformedURLException {
        URI uri = new URI("http://myaccount.blob.core.windows.net/mycontainer/my.file");
        System.out.println(uri.toString() + "?" + generateSasToken(uri));
    }
}

From that, I get URLs like this one:

http://myaccount.blob.core.windows.net/mycontainer/my.file?sig=ngk3fX081paEHbYDcmf7f2Zkp6ZbYUSlshYLB2O%2F3%2B0%3D&se=2020-05-08T16%3A49%3A23Z&sv=2019-02-02&sp=r&sr=f

And when I open the link in the browser I get the following result:

<?xml version="1.0" encoding="utf-8"?>
<Error>
  <Code>AuthenticationFailed</Code>
  <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. 
RequestId:3dfc7fb8-701e-0057-2054-25add3000000
Time:2020-05-08T16:19:28.4764866Z</Message>
  <AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
</Error>
1

1 Answers

1
votes

I believe your problem is that you're using SharedAccessFilePolicy to generate a SAS URL for a blob resource (Data Lake Gen2 resources are essentially blobs). You will need to use SharedAccessBlobPolicy. So your code would be:

    CloudBlob file = new CloudBlob (fileUri, credentials);
    SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy ();
    policy.setPermissions(EnumSet.of(SharedAccessBlobPermissions.READ));
    policy.setSharedAccessStartTime(null);
    policy.setSharedAccessExpiryTime(getExpirationTime());

    return file.generateSharedAccessSignature(policy, null);

Give this a try and it should work.