Introduction
Azure Storage is a service provided by Microsoft to store the data, such as text or binary. You can use this data to make it available to the public or secure it from public access. There are multiple ways I found on the internet to upload the content to Azure Blob Storage like you can use shared keys, or use a Connection string, or a native app.
Problem
Now, here is the problem. Suppose you have to create a Windows Service that will upload and download your files to the Azure Blob Storage. And as per the requirements, you don’t have to use a shared key or connection string, or simply your client didn’t share it. The client wants to get it done by Active Directory Authentication. With the Native app, as most of the samples are over the internet, user consent is required if your token expires and that’s why it cannot be used in Windows Service.
Solution
After spending some time on it, I found the right way to upload and download a file on Azure Blob Storage. As I didn’t find any documentation or samples particular to this requirement over the internet, I am sharing it. Hope it will help.
Create an application on Azure
Create an application of Web app/API type on the Azure portal.
Get Keys for Authentication
You need to have the application ID, tenant/Directory ID, and Client Secret key.
After application creation, you will see the below screen where you have the application ID and from the Keys section, you can generate the Client Secret key. See the below screens.
To get a Directory/ Tenant ID.
Role assignment to your Azure application
Now, go to your storage account that you want to use and assign your application Storage Blob Data Owner/Contributor Role.
Actually, the above role gives you permissions to read/write/delete on Blob Management and Data. With Management permission, you can read/write/delete a container in the Blob and with Data, you can read/write/delete content in it.
Now, you have all the things you need to build an application. Let's see the code snippets.
Authentication
The first thing you need is to get an access token and you can get it using the below method.
static string GetUserOAuthToken(string tenantId, string applicationId, string clientSecret)
{
const string ResourceId = "https://storage.azure.com/";
const string AuthInstance = "https://login.microsoftonline.com/{0}/";
string authority = string.Format(CultureInfo.InvariantCulture, AuthInstance, tenantId);
AuthenticationContext authContext = new AuthenticationContext(authority);
var clientCred = new ClientCredential(applicationId, clientSecret);
AuthenticationResult result = authContext.AcquireTokenAsync(
ResourceId,
clientCred
).Result;
return result.AccessToken;
}
File Upload and Download Methods
Below is the code snippet to upload and download the file to Azure Blob Storage.
public static class AzureOperations
{
#region ConfigParams
public static string tenantId;
public static string applicationId;
public static string clientSecret;
#endregion
public static void UploadFile(AzureOperationHelper azureOperationHelper)
{
CloudBlobContainer blobContainer = CreateCloudBlobContainer(
tenantId,
applicationId,
clientSecret,
azureOperationHelper.storageAccountName,
azureOperationHelper.containerName,
azureOperationHelper.storageEndPoint
);
blobContainer.CreateIfNotExists();
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(azureOperationHelper.blobName);
blob.UploadFromFile(azureOperationHelper.srcPath);
}
public static void DownloadFile(AzureOperationHelper azureOperationHelper)
{
CloudBlobContainer blobContainer = CreateCloudBlobContainer(
tenantId,
applicationId,
clientSecret,
azureOperationHelper.storageAccountName,
azureOperationHelper.containerName,
azureOperationHelper.storageEndPoint
);
CloudBlockBlob blob = blobContainer.GetBlockBlobReference(azureOperationHelper.blobName);
blob.DownloadToFile(azureOperationHelper.destinationPath, FileMode.OpenOrCreate);
}
private static CloudBlobContainer CreateCloudBlobContainer(
string tenantId,
string applicationId,
string clientSecret,
string storageAccountName,
string containerName,
string storageEndPoint
)
{
string accessToken = GetUserOAuthToken(tenantId, applicationId, clientSecret);
TokenCredential tokenCredential = new TokenCredential(accessToken);
StorageCredentials storageCredentials = new StorageCredentials(tokenCredential);
CloudStorageAccount cloudStorageAccount = new CloudStorageAccount(
storageCredentials,
storageAccountName,
storageEndPoint,
useHttps: true
);
CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference(containerName);
return blobContainer;
}
static string GetUserOAuthToken(string tenantId, string applicationId, string clientSecret)
{
const string ResourceId = "https://storage.azure.com/";
const string AuthInstance = "https://login.microsoftonline.com/{0}/";
string authority = string.Format(CultureInfo.InvariantCulture, AuthInstance, tenantId);
AuthenticationContext authContext = new AuthenticationContext(authority);
var clientCred = new ClientCredential(applicationId, clientSecret);
AuthenticationResult result = authContext.AcquireTokenAsync(ResourceId, clientCred).Result;
return result.AccessToken;
}
}
Test it in a Console application.
class Program
{
static void Main(string[] args)
{
// Set Ids of your Azure account
AzureOperations.applicationId = "";
AzureOperations.clientSecret = "";
AzureOperations.tenantId = "";
// Demo Upload File
string srcPathToUpload = @"C:\Users\abdul.rehman\Desktop\AzureFileUpload\myfile.txt";
UploadFile(srcPathToUpload);
// Demo Download File
string azurePathInBlob = "dev/files/myfile.txt";
string destinationPath = @"C:\Users\abdul.rehman\Desktop\AzureFileDownload\myfile.txt";
DownloadFile(destinationPath, azurePathInBlob);
}
public static void UploadFile(string srcPath)
{
AzureOperationHelper azureOperationHelper = new AzureOperationHelper();
// your Storage Account Name
azureOperationHelper.storageAccountName = "dbpoc";
azureOperationHelper.storageEndPoint = "core.windows.net";
// File path to upload
azureOperationHelper.srcPath = srcPath;
// Your Container Name
azureOperationHelper.containerName = "filecontainer";
// Destination Path you can set it file name or if you want to put it in folders do it like below
azureOperationHelper.blobName = $"dev/files/{Path.GetFileName(srcPath)}";
AzureOperations.UploadFile(azureOperationHelper);
}
public static void DownloadFile(string destinationPath, string srcPath)
{
AzureOperationHelper azureOperationHelper = new AzureOperationHelper();
// your Storage Account Name
azureOperationHelper.storageAccountName = "dbpoc";
azureOperationHelper.storageEndPoint = "core.windows.net";
// Destination Path where you want to download file
azureOperationHelper.destinationPath = destinationPath;
// Your Container Name
azureOperationHelper.containerName = "filecontainer";
// Blob Path in container where to download File
azureOperationHelper.blobName = srcPath;
AzureOperations.DownloadFile(azureOperationHelper);
}
}
NuGet Dependencies
- WindowsAzure.Storage (I have installed v9.3.3).
- Microsoft.IdentityModel.Clients.ActiveDirectory (I have installed v4.4.2).
There are a few things you need to check.
- The container name should be in lowercase. I don't know why it is not handled but in this version, it is not working with uppercase.
- Permissions are very critical. Your application role must have read/write/delete permissions on Blob Management and Data as well.
Summary
In this above sample, we learned how to manage our files on Azure Blob Storage with Active Directory Authentication using the application Secret Key. And like the Native app, no popup will be shown to enter the credentials in order to get the access token.
I have also uploaded the sample console application that you can download and test with your Azure credentials. Feel free to contact me in case of an issue.
Download Complete Sample
References