I am authenticating my user using ClientCredentails. My client does have the permission to generate SaS token. Now I want to generate SaS token from code for a short period of time so that the customer can directly download the file.

        String tenantId = "TenantId";
        String clientSecret = "XXXX"
        String clientId = "abc-123"

        String authorityUrl = AzureAuthorityHosts.AZURE_PUBLIC_CLOUD +  tenantId;

        ClientSecretCredential credential = new ClientSecretCredentialBuilder()
                .authorityHost(authorityUrl)
                .tenantId(tenantId)
                .clientSecret(clientSecret)
                .clientId(clientId)
                .build();


         BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
                    .credential(credential)
                    .endpoint(azureStorageEndPoint)
                    .buildClient(); 


        // Upload a file            
        BlobContainerClient blobContainerClient = blobServiceClient.getBlobContainerClient(containerName);            
        BlobClient blobClient = blobContainerClient.getBlobClient("Test.txt");
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(new File("<FILE_PATH>")));
        blobClient.upload(bufferedInputStream, bufferedInputStream.available(),true);     


        BlobSasPermission blobSasPermission = new BlobSasPermission().setReadPermission(true);
        OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1);
        BlobServiceSasSignatureValues values = new BlobServiceSasSignatureValues(expiryTime, blobSasPermission)
                    .setStartTime(OffsetDateTime.now());

        String generateSas = blobClient.generateSas(values);



        Getting Error 

        java.lang.NullPointerException: The argument must not be null or an empty string. Argument name: storageSharedKeyCredentials.

Tried to find some azure docs which clearly says that "Client must be authenticated via StorageSharedKeyCredential"

https://learn.microsoft.com/en-us/java/api/com.azure.storage.blob.blobserviceclient.generateaccountsas?view=azure-java-stable

Question is how to generate StorageSharedKeyCredential programmatically if your code is authenticating with different ways.

2

There are 2 answers

0
Raj On

I finally found the answer, when we login with client credentials then we need to create UserDelegationKey and then use that key to get the SaS token

String tenantId = "TenantId";
        String clientSecret = "XXXX"
        String clientId = "abc-123"

        String authorityUrl = AzureAuthorityHosts.AZURE_PUBLIC_CLOUD +  tenantId;

        ClientSecretCredential credential = new ClientSecretCredentialBuilder()
                .authorityHost(authorityUrl)
                .tenantId(tenantId)
                .clientSecret(clientSecret)
                .clientId(clientId)
                .build();


         BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
                    .credential(credential)
                    .endpoint(azureStorageEndPoint)
                    .buildClient(); 


        // Upload a file            
        BlobContainerClient blobContainerClient = blobServiceClient.getBlobContainerClient(containerName);            
        BlobClient blobClient = blobContainerClient.getBlobClient("Test.txt");
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(new File("<FILE_PATH>")));
        blobClient.upload(bufferedInputStream, bufferedInputStream.available(),true);     


OffsetDateTime keyStart = OffsetDateTime.now();
OffsetDateTime keyExpiry = OffsetDateTime.now().plusDays(7);


UserDelegationKey userDelegationKey = blobServiceClient.getUserDelegationKey(keyStart, keyExpiry);

            BlobContainerSasPermission blobContainerSas = new BlobContainerSasPermission();
            blobContainerSas.setReadPermission(true);
            BlobServiceSasSignatureValues blobServiceSasSignatureValues = new BlobServiceSasSignatureValues(keyExpiry,
                    blobContainerSas);


String sas = blobClient.generateUserDelegationSas(blobServiceSasSignatureValues, userDelegationKey);


I found the answer from this link

Azure sdk for Java How to Setup User Delegation Key and Shared Authentication Signatures SAS

0
Syed Ubed Ali On

Cool! There's one easy way to Generate Sas Token and Pre-signed Url with expiration time.

Here i'm trying to generate Pre-signed Urls for list of azure blob paths:

fun getPreSignedUrls(blobPaths: List<String>): List<String> {
    var preSignedUrls: List<String> = emptyList()
    blobPaths.forEach { blobPath ->
        val blobServiceClient = BlobServiceClientBuilder()
            .connectionString(connectionString)
            .buildClient()

        val containerClient = blobServiceClient.getBlobContainerClient(containerName)

        val blobClient = containerClient.getBlobClient(blobPath)

        val expirationTime = OffsetDateTime.now().plusMinutes(30)
        val sasToken = blobClient.generateSas(
            BlobServiceSasSignatureValues(
                expirationTime,
                BlobContainerSasPermission.parse("rl")
            )
        )
        
        preSignedUrls += blobClient.blobUrl.toString() + "?" + sasToken
    }
    return preSignedUrls
}