Search code examples
azureazure-blob-storageapex

Apex class which uploads document error: The MAC signature found in the HTTP request '' is not the same as any computed signature


I want to upload documents to Azure Blob with Apex code.

I have below Apex class which uploads document to Azure but gives error

"The MAC signature found in the HTTP request '' is not the same as any computed signature".

I am not sure where I am messing up the HTTP Authentication header. I did use this code from https://stackoverflow.com.

public class AzureService {

    private String storageKey;
    private String storageName;
    private String storageContainer;
    private String storageUrl;
    private String blobName;
    private String requestURL;
    private String fileLength;
    private String formattedDate ;
    private String fileType;
    private String fileName;


    private final string DATEFORMAT = 'EEE, dd MMM yyyy HH:mm:ss z';
    private final string VERSION = '2015-12-11';
    private final string BLOB_TYPE = 'BlockBlob';


    public Boolean uploadBlob( Blob fileBody, Integer intFileLength, String strFileType, String strFileName)
    {

        Boolean isUploaded= false;
        this.fileName = EncodingUtil.urlEncode(strFileName, 'UTF-8');
        this.fileType = strFileType;
        this.storageName = 'STORAGE_ACCOUNT';
        this.storageContainer = 'CONTAINER_NAME';
        this.storageKey = 'ACCESS_KEY';
        this.storageUrl ='https://STORAGE_ACCOUNT.blob.core.windows.net';

        this.blobName = '/'+storageName+'/'+storageContainer+'/'+fileName;
        System.debug('blobName--->'+blobName);
        this.requestURL = storageUrl+'/'+storageContainer+'/'+fileName;
        System.debug('requestURL--->'+requestURL);

        this.fileLength = String.valueof(intFileLength);

        String strSharedKey = getBlobSharedKey();

        try
        {
            this.uploadBlob(fileBody, strSharedKey);
            isUploaded = true;

        }catch(Exception exp)
        {
            System.debug('Exception occur while uploading the Blob-->'+exp.getMessage());
            isUploaded = false;
        }

        return isUploaded;
    }


    public String getBlobSharedKey()
    {
        System.debug('getBlobSharedKey--->Start');
        String sharedKey;
        String signature;
        Datetime dt = Datetime.now();

        this.formattedDate = dt.formatGMT(DATEFORMAT);
        String stringToSign = 'PUT\n\n\n'+fileLength+'\n\n'+fileType+'\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:'+formattedDate+'\nx-ms-version:2015-12-11\n'+blobName;

        System.debug('stringToSign--->'+stringToSign);

        Blob unicodeKey = EncodingUtil.base64Decode(storageKey);
        Blob data = Crypto.generateMac('hmacSHA256', Blob.valueOf(stringToSign), unicodeKey);
        signature = EncodingUtil.base64Encode(data);

        sharedKey = 'SharedKey '+storageName+':' + signature;
        return sharedKey;
    }

   public void uploadBlob(Blob fileBody, String sharedKey)
   {
       HttpRequest req = new HttpRequest();


       req.setMethod('PUT');

       req.setHeader('x-ms-blob-type', BLOB_TYPE);
       req.setHeader('x-ms-version', VERSION);
       req.setHeader('x-ms-date', formattedDate);
       req.setHeader('Authorization', sharedKey);
       req.setHeader('Content-Type', fileType);
       req.setHeader('Content-Length', fileLength);

       req.setEndpoint(this.requestURL);

       req.setBodyAsBlob(fileBody);

       Http http = new Http();
       HTTPResponse res = http.send(req);
       // in the response body you have your blob
       System.debug('Response Body--->'+res.getBody());
       System.debug('Status--->'+res.getStatus());

   }

}

Solution

  • Thank you Gaurav Mantri for your suggestion .Converting it as answer to help other community members.

    Please check with value used for stringToSign by Azure Storage Service. Compare that with the value of stringToSign you're computing. Both of them should exactly match