There are several use cases where we need to share the azure resources with limited access based on some conditions. SAS tokens provide a flexible and secure way to grant temporary access to Azure storage resources without compromising the security of the storage account.
In this article, we will explore shared access signature, SAS tokens, and a secure way to share the azure resources. Furthermore, I will demonstrate how to generate SAS tokens with a complete solution using Blazor Apps in .NET 7. For this demo, I will use Azure blob storage files with a view URL using an SAS token.
Uploading files or attachments is one of the common requirements for any application. Azure storage is one of the most efficient cloud storage with all the necessary features, security, and compliance. Azure Storage, a platform owned by Microsoft, is a contemporary cloud storage solution for almost every case scenario that is highly secure, scalable, durable, and easy to manage.
In this article, we learn about SRS token for Azure Blob Storage files and will demonstrate with code in Blazor Application using .NET 7.
- What is a shared access signature, SAS?
- What is Azure Storage?
- How to create an Azure Storage Account?
- What is a Blazor Web App
- Create a Blazor App with .Net 7
- Upload and delete files in Azure Blobs using a Blazor App in .NET 7
- Create a SAS token and view the URL for Azure Blob Files using Blazor App
You can find a complete Solution on GitHub, Upload, delete, Generate SAS Token and View URL
What is a SAS Token?
A SAS (Shared Access Signature) token is a secure way to grant limited access to resources in Azure storage. It provides a way to grant temporary access to a resource without sharing the account keys. With a SAS token, you can define the permissions (such as read, write, or delete) and the time interval for which access is permitted. This allows you to control access to your Azure resources and lessen the risk of unauthorized access.
SAS tokens can be generated for various resources in Azure storage, including blobs, files, queues, and tables. They are created using the storage account key, but the token itself is not a key and can be safely shared with others.
To use an SAS token, the client must include it in the request to Azure storage. The SAS token is included as a query parameter in the URL of the request. The token can also be embedded in a connection string for use by client libraries.
How to generate SAS Token?
SAS token can be generated using various methods: Azure Portal, Azure Storage Explorer, Azure PowerShell, or Azure CLI, and programmatically using Azure SDK. In this article, I will demonstrate using Azure SDK with .Net, however, we can use other programming languages.
While generating the SAS token, we can define the permissions, and expiry duration.
Azure Storage
Azure Storage is a modern cloud storage solution owned by Microsoft, for almost every data storage scenario that is highly secure, scalable, durable, and easy to manage. It is well managed for hardware, updates, critical issues, high availability and is accessible from any part of the globe. Furthermore, the Azure UI is user-friendly, and we can create the services/objects effortlessly with all the configuration features. Additionally, Azure Storage provides all the necessary client libraries/SDK in .NET, Python, JavaScript, Java C++, PHP, Node.js, Ruby, Go, therefore developers can simply implement in their applications using the programming language of their choice. We can even access the storage objects via HTTP, HTTPS or REST API. Azure CLI or Azure PowerShell can be used by IT professionals to create scripts for those services and configuration tasks.
To know more details: Click Here
Azure Storage Data Services
Azure storage consists of 5 data services, as portrayed in the above diagram.
- Azure Blob Storage
- Azure Files
- Azure Tables
- Azure Queues
In my previous article, I illustrated and shared the step-by-step process to create an Azure Storage account.
Upload and Delete files in Azure Blob Storage Using Blazor Apps With .NET 7
In this write-up, I will delve on how to create SAS token and azure storage files to view URL programmatically using Blazor Apps with .NET.
Prerequisites
- Visual Studio 2022
- .NET 7
- Azure Subscription (You can create trial subscription)
- C# Knowledge
Create Azure Storage Account
Azure storage account provides a unique namespace in the cloud for our Azure storage that contains all the azure data storage components including Blob storage, Azure Files, Azure Tables, Azure Queues, and disks and can be accessible through authenticate HTTP(S) calls.
https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview
Please refer to my previous article to create a storage account and container. Click Here.
Install .NET 7 SDK
We can use any version of Visual Studio 2022, and we can download from this link. You can use the community version, which is free. Additionally, you can download .NET 7 SDK for free from this official site. In my case, I am using Visual Studio 2022 Professional, however, the steps and interfaces are the same for other versions.
Create a Web App with Blazor Server
Blazor server runs as an implementation of server side as a part of ASP.NET core app where UI events, button clicks, UI updates and interactions are communicated over SignalR connection. In this approach, the UI is generated on a web server and is transmitted to the visitor’s browser upon request. This two-way interaction occurs using SignalR and a web sockets connection. Any change in DOM content is generated from web server and update in automatically via SignalR with Blazor Server framework. This Blazor type has direct access to server and network resources since app is executed in server side. Let’s open a Visual Studio and create a new project. We will use the Blazor Server App project template.
We will provide a project name and location for the solution.
On the next screen, we will get options to choose .Net framework, Authentication type and a couple options for the project.
After installation of .NET 7 SDK, we will have an option to choose .NET 7 in the framework. We will select the .NET 7 framework and proceed. To keep it simple, we will keep other options default.
We have successfully created a Blazor server web application with .NET 7. We will build and run the solution.
This is how we can create a Blazor server app.
Upload and Delete Files in Azure Blob Storage Using Blazor App with .NET 7
In my previous article, I demonstrated a complete solution to upload and delete files in Azure Blob Storage. Click Here.
In this article, I will show how to create a SAS token and view URLs with the same solution. Storage account and access key are required to generate the SAS token.
Access Keys
Login to Azure Portal, Navigate to Azure Storage Account and click Access Key as portrayed.
Now we will add a storage account and access key into the app setting file as shown below.
Code:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"AzureStorageAccount": "Your Azure Connection"
},
"AzureStorage": {
"AzureAccount": "storageaccount",
"AccessKey": "access key"
},
"AllowedHosts": "*"
}
We will define another function for generating SAS token URL in IBlogStorageService Interface, named, GetBlobSASTOkenByFile.
Task<string> GetBlobSASTOkenByFile(string fileName);
Implementation of the above function in BlogStorageService is as shown below.
Code:
public async Task<string> GetBlobSASTOkenByFile(string fileName)
{
try
{
var azureStorageAccount = _configuration.GetSection("AzureStorage:AzureAccount").Value;
var azureStorageAccessKey = _configuration.GetSection("AzureStorage:AccessKey").Value;
Azure.Storage.Sas.BlobSasBuilder blobSasBuilder = new Azure.Storage.Sas.BlobSasBuilder()
{
BlobContainerName = blobContainerName,
BlobName = fileName,
ExpiresOn = DateTime.UtcNow.AddMinutes(2),//Let SAS token expire after 5 minutes.
};
blobSasBuilder.SetPermissions(Azure.Storage.Sas.BlobSasPermissions.Read);//User will only be able to read the blob and it's properties
var sasToken = blobSasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(azureStorageAccount,
azureStorageAccessKey)).ToString();
return sasToken;
}
catch (Exception)
{
throw;
}
}
The above function will generate our SAS token, which can be used to allow the access of Azure resources. The token can be used to view the files.
Please note, we can set expiry and permissions while generating SAS token in the parameter as highlighted.
Example SAS token generated from above function.
sv=2021-10-04&se=2023-03-20T11%3A20%3A45Z&sr=b&sp=r&sig=M5GaoRgyIWcLMMfggqfZ9pI01dZLyFD0Em5WdCNsUuk%3D
We will update the Blazor component to view the file with SAS token.
We will use a view icon with the below function.
Code
private async void OnFileViewClick(FileUploadViewModel attachment)
{
try
{
var sasToken = await blobStorageService.GetBlobSASTOkenByFile(attachment.FileName);
if (sasToken != null)
{
string fileUrl = attachment.FileStorageUrl + "?" + sasToken;
await jsRuntime.InvokeAsync<object>("open", fileUrl, "_blank");
}
}
catch (Exception)
{
warninngMessage = "Something went wrong! Please try again.";
}
this.StateHasChanged();
}
We need to inject JSRunTime.
@inject IJSRuntime jsRuntime
Complete Blazor Page Code.
@page "/"
@using RijsatFileUploadAzureStorage.Services;
@using RijsatFileUploadAzureStorage.Services.Dto;
@inject IBlobStorageService blobStorageService
@inject IJSRuntime jsRuntime
<PageTitle>Index</PageTitle>
@if (warninngMessage.Length > 0)
{
<div class="alert alert-warning">
<strong>Warning!</strong> @warninngMessage.
</div>
}
<h4>File Upload (Azure Blob Storage)</h4>
<div class="row">
<div class="col-sm-6">
<label>
<InputFile class="form-control" disabled="@fileLoading" OnChange="@OnInputFileChange" single />
</label>
@if (fileLoading)
{
<i class="fa fa-refresh"></i> <span>Loading...</span>
}
</div>
<div class="col-sm-2">
<button type="button" disabled="@fileLoading" class="btn btn-primary" @onclick="OnUploadSubmit">
Upload File
</button>
</div>
</div>
@if (displayMessage.Length > 0)
{
<div class="alert alert-success">
<strong>Success!</strong> @displayMessage.
</div>
}
<br />
<div class="row">
@if (fileUploadViewModels.Count > 0)
{
<table class="table table-responsive table-bordered">
<thead class="text-primary">
<tr>
<th>File</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach (var attachment in fileUploadViewModels)
{
<tr>
<td>
<a class="text-primary"><i class="fa-solid fa-paperclip"></i> @attachment.FileName</a>
</td>
<td>
<span class="oi oi-delete" aria-hidden="true" @onclick="() => OnFileDeleteClick(attachment)"></span>
<span class="oi oi-eye" aria-hidden="true" @onclick="() => OnFileViewClick(attachment)"></span>
</td>
</tr>
}
</tbody>
</table>
}
else
{
<div class="alert alert-info">
<strong>No Files!</strong>
</div>
}
</div>
Code
@code {
private string warninngMessage = "";
private string displayMessage = "";
private List<IBrowserFile> loadedFiles = new();
private long maxFileSize = 1024 * 15;
private int maxAllowedFiles = 3;
private bool fileLoading;
string Message = "No file(s) selected";
IReadOnlyList<IBrowserFile> selectedFiles;
private List<FileUploadViewModel> fileUploadViewModels = new();
private void OnInputFileChange(InputFileChangeEventArgs e)
{
selectedFiles = e.GetMultipleFiles();
Message = $"{selectedFiles.Count} file(s) selected";
this.StateHasChanged();
}
private async void OnUploadSubmit()
{
fileLoading = true;
foreach (var file in selectedFiles)
{
try
{
var trustedFileNameForFileStorage = file.Name;
var blobUrl = await blobStorageService.UploadFileToBlobAsync(trustedFileNameForFileStorage, file.ContentType, file.OpenReadStream(20971520));
if (blobUrl != null)
{
FileUploadViewModel fileUploadViewModel = new FileUploadViewModel()
{
FileName = trustedFileNameForFileStorage,
FileStorageUrl = blobUrl,
ContentType = file.ContentType,
};
fileUploadViewModels.Add(fileUploadViewModel);
displayMessage = trustedFileNameForFileStorage + " Uploaded!!";
}
else
warninngMessage = "File Upload failed, Please try again!!";
}
catch (Exception ex)
{
warninngMessage = "File Upload failed, Please try again!!";
}
}
fileLoading = false;
this.StateHasChanged();
}
private async void OnFileDeleteClick(FileUploadViewModel attachment)
{
try
{
var deleteResponse = await blobStorageService.DeleteFileToBlobAsync(attachment.FileName);
if (deleteResponse)
{
fileUploadViewModels.Remove(attachment);
displayMessage = attachment.FileName + " Deleted!!";
}
}
catch (Exception)
{
warninngMessage = "Something went wrong! Please try again.";
}
this.StateHasChanged();
}
private async void OnFileViewClick(FileUploadViewModel attachment)
{
try
{
var sasToken = await blobStorageService.GetBlobSASTOkenByFile(attachment.FileName);
if (sasToken != null)
{
string fileUrl = attachment.FileStorageUrl + "?" + sasToken;
await jsRuntime.InvokeAsync<object>("open", fileUrl, "_blank");
}
}
catch (Exception)
{
warninngMessage = "Something went wrong! Please try again.";
}
this.StateHasChanged();
}
}
Let’s run the application and test it.
First, I will upload a file.
Thus, we can view the azure blob files using SAS token.
The view URL will be a combination of the azure blob storage and SAS token.
View URL = blogstorageURL + SAS Token
Full source code GitHub: Upload, delete, Generate SAS Token and View URL
Conclusion
SAS is a flexible and secure way to grant temporary access to azure storage resources without compromising the security. We can add permissions and expire with SAS token. In this article, I have explored SAS token and methods to generate it. In my previous article, I show how to upload and delete the azure blob storage files using Blazor apps and .NET 7. This article is a continuation of the article where I have shown how to create SAS token and view files using Blazor apps and .NET 7. I have demonstrated with examples and a complete solution is available in GitHub (Shared).