or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdkey-authentication.mdnamed-key-authentication.mdsas-authentication.mdtoken-authentication.md
tile.json

sas-authentication.mddocs/

SAS Authentication

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.

Capabilities

SASCredential Interface

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;
}

AzureSASCredential Class

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);
}

SAS Credential Type Guard

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;
}

Error Handling

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 Token Structure

SAS tokens are query strings with specific parameters. Common parameters include:

  • sv: Storage service version
  • ss: 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/time
  • st: Start date/time (optional)
  • spr: Protocol (https only recommended)
  • sig: The signature hash