Shared Access Signature authentication for Azure Storage and other services that support SAS tokens. This authentication method provides time-limited, scoped access to Azure resources using pre-signed URLs or tokens, with support for signature updates without recreating the credential object.
Base interface for Shared Access Signature authentication.
/**
* Represents a credential defined by a static shared access signature.
*/
interface SASCredential {
/** The value of the shared access signature represented as a string */
readonly signature: string;
}Concrete implementation of SASCredential with signature rotation support.
/**
* A static-signature-based credential that supports updating the underlying signature value.
*/
class AzureSASCredential implements SASCredential {
/**
* Create an instance of an AzureSASCredential for use with a service client.
* @param signature - The initial value of the shared access signature to use in authentication
* @throws Error if signature is empty or undefined
*/
constructor(signature: string);
/** The value of the shared access signature to be used in authentication */
get signature(): string;
/**
* Change the value of the signature.
* Updates will take effect upon the next request after updating the signature value.
* @param newSignature - The new shared access signature value to be used
* @throws Error if newSignature is empty or undefined
*/
update(newSignature: string): void;
}Usage Examples:
import { AzureSASCredential } from "@azure/core-auth";
// Create credential with SAS token
const sasCredential = new AzureSASCredential(
"sv=2021-06-08&ss=b&srt=sco&sp=rwdlacupx&se=2023-12-31T23:59:59Z&st=2023-01-01T00:00:00Z&spr=https&sig=signature-here"
);
// Use with Azure Storage service client
const blobServiceClient = new BlobServiceClient(
"https://mystorageaccount.blob.core.windows.net",
sasCredential
);
// Access current signature
console.log(sasCredential.signature.substring(0, 20) + "..."); // "sv=2021-06-08&ss=b&sr..."
// Update the signature (useful when SAS token is refreshed)
const newSasToken = generateNewSasToken();
sasCredential.update(newSasToken);
// Future requests will use the new signature
const containers = await blobServiceClient.listContainers();
// Common pattern for SAS token refresh
async function refreshSasToken(credential: AzureSASCredential) {
const newToken = await generateFreshSasToken();
credential.update(newToken);
console.log("SAS token refreshed successfully");
}
// Pattern for time-based SAS renewal
async function maintainSasCredential(credential: AzureSASCredential) {
setInterval(async () => {
try {
const expiryTime = extractExpiryFromSas(credential.signature);
const now = new Date();
const timeUntilExpiry = expiryTime.getTime() - now.getTime();
// Refresh if expiring within 1 hour
if (timeUntilExpiry < 3600000) {
const newSas = await generateFreshSasToken();
credential.update(newSas);
console.log("SAS token automatically renewed");
}
} catch (error) {
console.error("Failed to renew SAS token:", error);
}
}, 300000); // Check every 5 minutes
}
// Pattern for different SAS types
function createBlobSasCredential(containerName: string, permissions: string): AzureSASCredential {
const sasToken = generateContainerSas(containerName, permissions);
return new AzureSASCredential(sasToken);
}
function createServiceSasCredential(serviceName: string): AzureSASCredential {
const sasToken = generateServiceSas(serviceName);
return new AzureSASCredential(sasToken);
}Runtime validation to determine if an object implements the SASCredential interface.
/**
* Tests an object to determine whether it implements SASCredential.
* @param credential - The assumed SASCredential to be tested
* @returns true if the object implements SASCredential, false otherwise
*/
function isSASCredential(credential: unknown): credential is SASCredential;Usage Examples:
import { isSASCredential, AzureSASCredential } from "@azure/core-auth";
function processSasCredential(credential: unknown) {
if (isSASCredential(credential)) {
// TypeScript now knows credential has a 'signature' property
const isExpiring = checkSasExpiry(credential.signature);
if (isExpiring) {
console.warn("SAS token is expiring soon");
}
return true;
}
return false;
}
// Usage in credential validation
function validateSasCredentials(credentials: unknown[]) {
const sasCredentials = credentials.filter(isSASCredential);
sasCredentials.forEach(cred => {
if (!cred.signature.startsWith('sv=')) {
console.warn("Invalid SAS token format");
}
const params = new URLSearchParams(cred.signature);
const expiry = params.get('se');
if (expiry && new Date(expiry) < new Date()) {
console.error("SAS token has expired");
}
});
}
// Usage with credential detection
function getCredentialType(credential: unknown): string {
if (isSASCredential(credential)) {
const params = new URLSearchParams(credential.signature);
const services = params.get('ss') || 'unknown';
return `SAS credential for services: ${services}`;
}
return "Not a SAS credential";
}
// Pattern for handling different credential types
function configureStorageClientWithSas(credential: unknown, endpoint: string) {
if (isSASCredential(credential)) {
return new BlobServiceClient(endpoint, credential);
}
throw new Error("SAS credential required");
}
// Utility function to extract SAS parameters
function extractSasInfo(credential: unknown): object | null {
if (isSASCredential(credential)) {
const params = new URLSearchParams(credential.signature);
return {
version: params.get('sv'),
services: params.get('ss'),
resourceTypes: params.get('srt'),
permissions: params.get('sp'),
expiry: params.get('se'),
start: params.get('st')
};
}
return null;
}The AzureSASCredential constructor and update method will throw Error if the signature is empty or undefined:
import { AzureSASCredential } from "@azure/core-auth";
// Constructor validation
try {
const credential = new AzureSASCredential(""); // Throws Error
} catch (error) {
console.error(error.message); // "shared access signature must be a non-empty string"
}
try {
const credential = new AzureSASCredential(null as any); // Throws Error
} catch (error) {
console.error(error.message); // "shared access signature must be a non-empty string"
}
// Update method validation
const credential = new AzureSASCredential("valid-sas-token");
try {
credential.update(""); // Throws Error
} catch (error) {
console.error(error.message); // "shared access signature must be a non-empty string"
}
try {
credential.update(null as any); // Throws Error
} catch (error) {
console.error(error.message); // "shared access signature must be a non-empty string"
}SAS tokens are query strings with specific parameters. Common parameters include:
sv: Storage service versionss: Services accessible (b=blob, q=queue, t=table, f=file)srt: Resource types (s=service, c=container, o=object)sp: Permissions (r=read, w=write, d=delete, l=list, a=add, c=create, u=update, p=process, x=execute)se: Expiry date/timest: Start date/time (optional)spr: Protocol (https only recommended)sig: The signature hash