# SkillPatch skill: azure-identity-ts

This skill provides detailed guidance for authenticating to Azure services using the @azure/identity JavaScript/TypeScript library. It covers multiple authentication strategies including DefaultAzureCredential, Managed Identity (system and user-assigned), Service Principals (secret and certificate), and interactive authentication flows. Agents can follow the provided code snippets and environment variable configurations to implement Azure authentication in TypeScript projects.

You (the agent) were given this URL and asked to use this skill. This is a **public** skill — no SkillPatch account, API key, or prior setup is required. Two ways to use it:

**1. Use it right now** — the skill's complete file tree (SKILL.md + all reference files) is inlined below; read `SKILL.md` first, then follow it, consulting the other files as it directs.

**2. Install the exact package onto disk** (recommended if you can run a shell — this reproduces the skill byte-for-byte, including any binary assets that can't be inlined):

```bash
mkdir -p .claude/skills/azure-identity-ts
curl -sSL https://skillpatch.dev/install_skill/azure-identity-ts | tar -xz -C .claude/skills/
```

(`.claude/skills/` is Claude Code's convention; use whatever directory your agent loads skills from.)


---

## Skill files (3)

- `SKILL.md`
- `references/browser-auth.md`
- `references/credential-types.md`


### `SKILL.md`

````markdown
---
name: azure-identity-ts
description: Authenticate to Azure services using Azure Identity library for JavaScript (@azure/identity). Use when configuring authentication with DefaultAzureCredential, managed identity, service principals, or interactive browser login.
license: MIT
metadata:
  author: Microsoft
  version: "1.0.0"
  package: '@azure/identity'
---

# Azure Identity library for TypeScript

Authentication library for Azure SDK clients using Microsoft Entra ID.

## Installation

```bash
npm install @azure/identity

# For Visual Studio Code credential support
npm install @azure/identity-vscode
```

## Environment Variables

### Service Principal (Secret)

```bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_SECRET=<client-secret>
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
```

### Service Principal (Certificate)

```bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_CERTIFICATE_PATH=/path/to/cert.pem
AZURE_CLIENT_CERTIFICATE_PASSWORD=<optional-password>
```

### Workload Identity (Kubernetes)

```bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/tokens/azure-identity
```

## DefaultAzureCredential (Recommended for Local Development)

```typescript
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();

// Use with any Azure SDK client
import { BlobServiceClient } from "@azure/storage-blob";
const blobClient = new BlobServiceClient(
  "https://<account>.blob.core.windows.net",
  credential
);
```

See [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#defaultazurecredential-overview) for the current credential chain order and defaults.

## Managed Identity

### System-Assigned

```typescript
import { ManagedIdentityCredential } from "@azure/identity";

const credential = new ManagedIdentityCredential();
```

### User-Assigned (by Client ID)

```typescript
const credential = new ManagedIdentityCredential({
  clientId: "<user-assigned-client-id>"
});
```

### User-Assigned (by Resource ID)

```typescript
const credential = new ManagedIdentityCredential({
  resourceId: "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>"
});
```

### User-Assigned (by Object ID)

```typescript
const credential = new ManagedIdentityCredential({
  objectId: "<user-assigned-object-id>"
});
```

## Service Principal

### Client Secret

```typescript
import { ClientSecretCredential } from "@azure/identity";

const credential = new ClientSecretCredential(
  "<tenant-id>",
  "<client-id>",
  "<client-secret>"
);
```

### Client Certificate

```typescript
import { ClientCertificateCredential } from "@azure/identity";

const credential = new ClientCertificateCredential(
  "<tenant-id>",
  "<client-id>",
  { certificatePath: "/path/to/cert.pem" }
);

// With password
const credentialWithPwd = new ClientCertificateCredential(
  "<tenant-id>",
  "<client-id>",
  { 
    certificatePath: "/path/to/cert.pem",
    certificatePassword: "<password>"
  }
);
```

## Interactive Authentication

### Browser-Based Login

```typescript
import { InteractiveBrowserCredential } from "@azure/identity";

const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  loginHint: "user@example.com"
});
```

### Device Code Flow

```typescript
import { DeviceCodeCredential } from "@azure/identity";

const credential = new DeviceCodeCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  userPromptCallback: (info) => {
    console.log(info.message);
    // "To sign in, use a web browser to open..."
  }
});
```

## Custom Credential Chain

```typescript
import { 
  ChainedTokenCredential,
  ManagedIdentityCredential,
  AzureCliCredential
} from "@azure/identity";

// Try managed identity first, fall back to CLI
const credential = new ChainedTokenCredential(
  new ManagedIdentityCredential(),
  new AzureCliCredential()
);
```

## Developer Credentials

### Visual Studio Code

```typescript
import { useIdentityPlugin, VisualStudioCodeCredential } from "@azure/identity";
import { vsCodePlugin } from "@azure/identity-vscode";

useIdentityPlugin(vsCodePlugin);

const credential = new VisualStudioCodeCredential();
```

### Azure CLI

```typescript
import { AzureCliCredential } from "@azure/identity";

const credential = new AzureCliCredential();
// Uses: az login
```

### Azure Developer CLI

```typescript
import { AzureDeveloperCliCredential } from "@azure/identity";

const credential = new AzureDeveloperCliCredential();
// Uses: azd auth login
```

### Azure PowerShell

```typescript
import { AzurePowerShellCredential } from "@azure/identity";

const credential = new AzurePowerShellCredential();
// Uses: Connect-AzAccount
```

## Sovereign Clouds

```typescript
import { ClientSecretCredential, AzureAuthorityHosts } from "@azure/identity";

// Azure Government
const credential = new ClientSecretCredential(
  "<tenant>", "<client>", "<secret>",
  { authorityHost: AzureAuthorityHosts.AzureGovernment }
);

// Azure China
const credentialChina = new ClientSecretCredential(
  "<tenant>", "<client>", "<secret>",
  { authorityHost: AzureAuthorityHosts.AzureChina }
);
```

## Bearer Token Provider

```typescript
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";

const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});

// Create a function that returns tokens
const getAccessToken = getBearerTokenProvider(
  credential,
  "https://cognitiveservices.azure.com/.default"
);

// Use with APIs that need bearer tokens
const token = await getAccessToken();
```

## Key Types

```typescript
import type { 
  TokenCredential, 
  AccessToken, 
  GetTokenOptions 
} from "@azure/core-auth";

import {
  DefaultAzureCredential,
  DefaultAzureCredentialOptions,
  ManagedIdentityCredential,
  ClientSecretCredential,
  ClientCertificateCredential,
  InteractiveBrowserCredential,
  ChainedTokenCredential,
  AzureCliCredential,
  AzurePowerShellCredential,
  AzureDeveloperCliCredential,
  DeviceCodeCredential,
  AzureAuthorityHosts
} from "@azure/identity";
```

## Custom Credential Implementation

```typescript
import type { TokenCredential, AccessToken, GetTokenOptions } from "@azure/core-auth";

class CustomCredential implements TokenCredential {
  async getToken(
    scopes: string | string[],
    options?: GetTokenOptions
  ): Promise<AccessToken | null> {
    // Custom token acquisition logic
    return {
      token: "<access-token>",
      expiresOnTimestamp: Date.now() + 3600000
    };
  }
}
```

## Debugging

```typescript
import { setLogLevel, AzureLogger } from "@azure/logger";

setLogLevel("verbose");

// Custom log handler
AzureLogger.log = (...args) => {
  console.log("[Azure]", ...args);
};
```

## Best Practices

1. **Use `DefaultAzureCredential` for local development; use `ManagedIdentityCredential` or `WorkloadIdentityCredential` for production**
2. **Never hardcode credentials** - Use environment variables or managed identity
3. **Prefer managed identity** - No secrets to manage in production
4. **Scope credentials appropriately** - Use user-assigned identity for multi-tenant scenarios
5. **Handle token refresh** - Azure SDK handles this automatically
6. **Use ChainedTokenCredential** - For custom fallback scenarios

````


### `references/browser-auth.md`

````markdown
# Browser Authentication Reference

Browser-based authentication for Azure services using the @azure/identity TypeScript SDK.

## Overview

Browser applications require special credential types that handle OAuth redirects and popup windows. This reference covers `InteractiveBrowserCredential`, `BrowserCustomizationOptions`, and SPA authentication patterns.

## Installation

```bash
npm install @azure/identity
```

**Note:** Browser credentials require a bundler (Vite, webpack, etc.) and won't work in Node.js.

## InteractiveBrowserCredential

The primary credential for browser applications.

```typescript
import { InteractiveBrowserCredential } from "@azure/identity";

const credential = new InteractiveBrowserCredential({
  clientId: "<your-app-client-id>",
  tenantId: "<your-tenant-id>",
});

// Use with Azure SDK clients
import { BlobServiceClient } from "@azure/storage-blob";
const blobClient = new BlobServiceClient(
  "https://myaccount.blob.core.windows.net",
  credential
);
```

## App Registration Requirements

Your Azure AD app registration needs:

1. **Platform:** Single-page application (SPA)
2. **Redirect URIs:** 
   - `http://localhost:3000` (development)
   - `https://yourapp.com` (production)
3. **API Permissions:** Configure based on services you're accessing
4. **Implicit grant:** Access tokens (for MSAL.js implicit flow)

## Authentication Modes

### Popup Mode (Default)

```typescript
import { InteractiveBrowserCredential } from "@azure/identity";

const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  // Popup is default - no loginStyle needed
});

// Triggers popup on first getToken call
const token = await credential.getToken("https://storage.azure.com/.default");
```

### Redirect Mode

```typescript
import { InteractiveBrowserCredential } from "@azure/identity";

const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  loginStyle: "redirect",
  redirectUri: window.location.origin, // Must match app registration
});

// Redirects to Azure AD, then back to your app
const token = await credential.getToken("https://storage.azure.com/.default");
```

### Handling Redirect Response

```typescript
import { InteractiveBrowserCredential } from "@azure/identity";

// On app load, check for redirect response
const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  loginStyle: "redirect",
  redirectUri: window.location.origin,
});

// This will handle the response if returning from redirect
try {
  const token = await credential.getToken("https://storage.azure.com/.default");
  console.log("Authenticated successfully");
} catch (error) {
  console.error("Authentication failed:", error);
}
```

## Configuration Options

```typescript
interface InteractiveBrowserCredentialNodeOptions {
  /** Application client ID */
  clientId: string;
  
  /** Azure AD tenant ID */
  tenantId?: string;
  
  /** Redirect URI (must match app registration) */
  redirectUri?: string;
  
  /** Login style: "popup" or "redirect" */
  loginStyle?: "popup" | "redirect";
  
  /** Pre-fill username hint */
  loginHint?: string;
  
  /** Force re-authentication */
  disableAutomaticAuthentication?: boolean;
  
  /** Authority host for sovereign clouds */
  authorityHost?: string;
  
  /** Custom browser customization */
  browserCustomizationOptions?: BrowserCustomizationOptions;
}
```

## Login Hint

Pre-fill the username to skip account selection:

```typescript
const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  loginHint: "user@example.com", // Pre-fills email
});
```

## Token Caching

The credential automatically caches tokens in browser storage:

```typescript
const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
});

// First call - triggers interactive login
await credential.getToken("https://storage.azure.com/.default");

// Subsequent calls - uses cached token (no prompt)
await credential.getToken("https://storage.azure.com/.default");
```

## Silent Authentication

Attempt silent auth first, fall back to interactive:

```typescript
import { InteractiveBrowserCredential } from "@azure/identity";

const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  disableAutomaticAuthentication: true, // Don't auto-prompt
});

async function getTokenSilentlyOrInteractive(scope: string): Promise<string> {
  try {
    // Try silent first
    const token = await credential.getToken(scope);
    return token.token;
  } catch (error) {
    // Silent failed - trigger interactive
    const token = await credential.authenticate(scope);
    return token.token;
  }
}
```

## Multi-Tenant Applications

```typescript
const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "common", // Allow any Azure AD tenant
  // Or "organizations" for work/school accounts only
  // Or "consumers" for personal Microsoft accounts only
});
```

## React Integration Example

```typescript
// auth.ts
import { InteractiveBrowserCredential } from "@azure/identity";

let credentialInstance: InteractiveBrowserCredential | null = null;

export function getCredential(): InteractiveBrowserCredential {
  if (!credentialInstance) {
    credentialInstance = new InteractiveBrowserCredential({
      clientId: import.meta.env.VITE_AZURE_CLIENT_ID,
      tenantId: import.meta.env.VITE_AZURE_TENANT_ID,
      redirectUri: window.location.origin,
    });
  }
  return credentialInstance;
}

export async function login(): Promise<void> {
  const credential = getCredential();
  await credential.authenticate(["https://storage.azure.com/.default"]);
}

// App.tsx
import { useState } from "react";
import { BlobServiceClient } from "@azure/storage-blob";
import { getCredential, login } from "./auth";

function App() {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  
  const handleLogin = async () => {
    try {
      await login();
      setIsAuthenticated(true);
    } catch (error) {
      console.error("Login failed:", error);
    }
  };
  
  const listBlobs = async () => {
    const credential = getCredential();
    const client = new BlobServiceClient(
      "https://myaccount.blob.core.windows.net",
      credential
    );
    
    for await (const container of client.listContainers()) {
      console.log(container.name);
    }
  };
  
  return (
    <div>
      {!isAuthenticated ? (
        <button onClick={handleLogin}>Login with Azure</button>
      ) : (
        <button onClick={listBlobs}>List Blobs</button>
      )}
    </div>
  );
}
```

## Error Handling

```typescript
import { 
  InteractiveBrowserCredential,
  AuthenticationRequiredError,
  CredentialUnavailableError
} from "@azure/identity";

const credential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
});

try {
  const token = await credential.getToken("https://storage.azure.com/.default");
} catch (error) {
  if (error instanceof AuthenticationRequiredError) {
    // User needs to authenticate
    console.log("Please sign in");
    await credential.authenticate(["https://storage.azure.com/.default"]);
  } else if (error instanceof CredentialUnavailableError) {
    // Credential not usable in this environment
    console.error("Browser authentication not available");
  } else {
    // Other error (network, consent denied, etc.)
    console.error("Authentication error:", error);
  }
}
```

## Logout

The credential doesn't provide direct logout. Use MSAL.js or redirect to logout URL:

```typescript
function logout() {
  const logoutUrl = new URL(
    `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/logout`
  );
  logoutUrl.searchParams.set("post_logout_redirect_uri", window.location.origin);
  
  window.location.href = logoutUrl.toString();
}
```

## Sovereign Clouds

```typescript
import { 
  InteractiveBrowserCredential, 
  AzureAuthorityHosts 
} from "@azure/identity";

// Azure Government
const govCredential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  authorityHost: AzureAuthorityHosts.AzureGovernment,
});

// Azure China
const chinaCredential = new InteractiveBrowserCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  authorityHost: AzureAuthorityHosts.AzureChina,
});
```

## DeviceCodeCredential (Alternative)

For environments without browser capability (CLI tools, IoT):

```typescript
import { DeviceCodeCredential } from "@azure/identity";

const credential = new DeviceCodeCredential({
  clientId: "<client-id>",
  tenantId: "<tenant-id>",
  userPromptCallback: (info) => {
    // Display to user
    console.log(info.message);
    // "To sign in, use a web browser to open the page
    //  https://microsoft.com/devicelogin and enter the code ABC123"
  },
});

const token = await credential.getToken("https://storage.azure.com/.default");
```

## CORS Configuration

Azure services need CORS configured for browser access:

**Azure Storage:**
```typescript
import { BlobServiceClient } from "@azure/storage-blob";

// Configure CORS via Azure Portal or CLI:
// az storage cors add --services b --methods GET,PUT,POST,DELETE,HEAD \
//   --origins "http://localhost:3000" --allowed-headers "*" \
//   --exposed-headers "*" --max-age 3600 --account-name <account>
```

## Best Practices

1. **Use popup for UX** — Better user experience than redirect
2. **Handle redirect on load** — Check for redirect response on app initialization
3. **Cache the credential instance** — Don't create new instances repeatedly
4. **Configure CORS** — Required for browser-to-Azure communication
5. **Use environment variables** — Don't hardcode client IDs
6. **Handle authentication errors** — Provide clear feedback to users
7. **Implement logout** — Clear session and redirect to Azure logout
8. **Test both flows** — Popup may be blocked; redirect is fallback

## Security Considerations

- Never expose client secrets in browser code
- Use SPA platform type in app registration (PKCE)
- Validate tokens server-side for sensitive operations
- Configure appropriate redirect URIs
- Use secure (HTTPS) redirect URIs in production

## See Also

- [Credential Types Reference](./credential-types.md)
- [MSAL.js Documentation](https://learn.microsoft.com/azure/active-directory/develop/msal-js-initializing-client-applications)
- [SPA Authentication](https://learn.microsoft.com/azure/active-directory/develop/scenario-spa-overview)

````


### `references/credential-types.md`

````markdown
# Credential Types Reference

Azure Identity credential types for authenticating to Azure services using the @azure/identity TypeScript SDK.

## Overview

The Azure Identity library provides various credential classes for different authentication scenarios. Choose the right credential based on your environment and security requirements.

## Credential Selection Guide

| Scenario | Recommended Credential |
|----------|------------------------|
| Production (any environment) | `DefaultAzureCredential` |
| Azure VM/App Service | `ManagedIdentityCredential` |
| Service Principal (secret) | `ClientSecretCredential` |
| Service Principal (cert) | `ClientCertificateCredential` |
| Local development | `AzureCliCredential` or `AzureDeveloperCliCredential` |
| Browser application | `InteractiveBrowserCredential` |
| CI/CD pipeline | `ClientSecretCredential` or `WorkloadIdentityCredential` |
| Kubernetes (AKS) | `WorkloadIdentityCredential` |

## DefaultAzureCredential (Recommended)

The most versatile credential - automatically tries multiple authentication methods.

```typescript
import { DefaultAzureCredential } from "@azure/identity";

const credential = new DefaultAzureCredential();

// Works in all environments - dev and production
import { BlobServiceClient } from "@azure/storage-blob";
const blobClient = new BlobServiceClient(
  "https://myaccount.blob.core.windows.net",
  credential
);
```

See [DefaultAzureCredential overview](https://aka.ms/azsdk/js/identity/credential-chains#defaultazurecredential-overview) for the current credential chain order and defaults.

### Customizing DefaultAzureCredential

```typescript
import { DefaultAzureCredential } from "@azure/identity";

const credential = new DefaultAzureCredential({
  // Exclude specific credentials
  excludeAzureCliCredential: true,
  excludeAzurePowerShellCredential: true,
  
  // For user-assigned managed identity
  managedIdentityClientId: "<client-id>",
  
  // Tenant hint for multi-tenant
  tenantId: "<tenant-id>",
});
```

## ManagedIdentityCredential

For Azure-hosted resources (VMs, App Service, Functions, AKS).

```typescript
import { ManagedIdentityCredential } from "@azure/identity";

// System-assigned managed identity
const credential = new ManagedIdentityCredential();

// User-assigned managed identity (by client ID)
const credentialByClientId = new ManagedIdentityCredential({
  clientId: "<user-assigned-client-id>"
});

// User-assigned managed identity (by resource ID)
const credentialByResourceId = new ManagedIdentityCredential({
  resourceId: "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>"
});
```

## ClientSecretCredential

For service principal authentication with a client secret.

```typescript
import { ClientSecretCredential } from "@azure/identity";

const credential = new ClientSecretCredential(
  "<tenant-id>",
  "<client-id>",
  "<client-secret>"
);

// From environment variables
const credentialFromEnv = new ClientSecretCredential(
  process.env.AZURE_TENANT_ID!,
  process.env.AZURE_CLIENT_ID!,
  process.env.AZURE_CLIENT_SECRET!
);
```

**Required Environment Variables:**

```bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_SECRET=<client-secret>
```

## ClientCertificateCredential

For service principal authentication with a certificate (more secure than secret).

```typescript
import { ClientCertificateCredential } from "@azure/identity";

// Certificate from file path
const credential = new ClientCertificateCredential(
  "<tenant-id>",
  "<client-id>",
  { certificatePath: "/path/to/cert.pem" }
);

// Certificate with password
const credentialWithPassword = new ClientCertificateCredential(
  "<tenant-id>",
  "<client-id>",
  {
    certificatePath: "/path/to/cert.pfx",
    certificatePassword: "<password>"
  }
);

// Certificate from PEM string
const credentialFromString = new ClientCertificateCredential(
  "<tenant-id>",
  "<client-id>",
  { certificate: "-----BEGIN CERTIFICATE-----\n..." }
);
```

## WorkloadIdentityCredential

For Kubernetes workload identity (AKS, Azure Arc).

```typescript
import { WorkloadIdentityCredential } from "@azure/identity";

// Uses environment variables automatically set by AKS
const credential = new WorkloadIdentityCredential();

// Explicit configuration
const credentialExplicit = new WorkloadIdentityCredential({
  tenantId: "<tenant-id>",
  clientId: "<client-id>",
  tokenFilePath: "/var/run/secrets/azure/tokens/azure-identity-token"
});
```

**Required Environment Variables (set by AKS):**
```bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/tokens/azure-identity
```

## Developer Credentials

### AzureCliCredential

```typescript
import { AzureCliCredential } from "@azure/identity";

// Uses token from: az login
const credential = new AzureCliCredential();

// With tenant hint
const credentialWithTenant = new AzureCliCredential({
  tenantId: "<tenant-id>"
});
```

### AzureDeveloperCliCredential

```typescript
import { AzureDeveloperCliCredential } from "@azure/identity";

// Uses token from: azd auth login
const credential = new AzureDeveloperCliCredential();
```

### AzurePowerShellCredential

```typescript
import { AzurePowerShellCredential } from "@azure/identity";

// Uses token from: Connect-AzAccount
const credential = new AzurePowerShellCredential();
```

### VisualStudioCodeCredential

```typescript
import { useIdentityPlugin, VisualStudioCodeCredential } from "@azure/identity";
import { vsCodePlugin } from "@azure/identity-vscode";

useIdentityPlugin(vsCodePlugin);

// Uses Azure Account extension in VS Code
const credential = new VisualStudioCodeCredential();
```

## ChainedTokenCredential

Create custom credential chains for specific scenarios.

```typescript
import {
  ChainedTokenCredential,
  ManagedIdentityCredential,
  AzureCliCredential,
  ClientSecretCredential
} from "@azure/identity";

// Try managed identity first, then CLI
const credential = new ChainedTokenCredential(
  new ManagedIdentityCredential(),
  new AzureCliCredential()
);

// Production: managed identity → service principal fallback
const productionCredential = new ChainedTokenCredential(
  new ManagedIdentityCredential(),
  new ClientSecretCredential(
    process.env.AZURE_TENANT_ID!,
    process.env.AZURE_CLIENT_ID!,
    process.env.AZURE_CLIENT_SECRET!
  )
);
```

## EnvironmentCredential

Automatically selects credential based on environment variables.

```typescript
import { EnvironmentCredential } from "@azure/identity";

// Checks env vars and creates appropriate credential
const credential = new EnvironmentCredential();
```

**Supported Environment Variable Sets:**

Service Principal (Secret):
```bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_SECRET=<client-secret>
```

Service Principal (Certificate):
```bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_CERTIFICATE_PATH=/path/to/cert.pem
AZURE_CLIENT_CERTIFICATE_PASSWORD=<optional>
```

## TokenCredential Interface

All credentials implement `TokenCredential`:

```typescript
import type { TokenCredential, AccessToken, GetTokenOptions } from "@azure/core-auth";

interface TokenCredential {
  getToken(
    scopes: string | string[],
    options?: GetTokenOptions
  ): Promise<AccessToken | null>;
}

interface AccessToken {
  token: string;
  expiresOnTimestamp: number;
}
```

### Custom Credential Implementation

```typescript
import type { TokenCredential, AccessToken, GetTokenOptions } from "@azure/core-auth";

class CustomCredential implements TokenCredential {
  async getToken(
    scopes: string | string[],
    options?: GetTokenOptions
  ): Promise<AccessToken | null> {
    // Custom token acquisition logic
    const token = await fetchTokenFromCustomSource(scopes);
    
    return {
      token: token.accessToken,
      expiresOnTimestamp: token.expiresOn.getTime()
    };
  }
}
```

## Sovereign Clouds

```typescript
import { 
  ClientSecretCredential, 
  AzureAuthorityHosts 
} from "@azure/identity";

// Azure Government
const govCredential = new ClientSecretCredential(
  "<tenant>", "<client>", "<secret>",
  { authorityHost: AzureAuthorityHosts.AzureGovernment }
);

// Azure China (21Vianet)
const chinaCredential = new ClientSecretCredential(
  "<tenant>", "<client>", "<secret>",
  { authorityHost: AzureAuthorityHosts.AzureChina }
);

// Available authority hosts
// AzureAuthorityHosts.AzurePublicCloud (default)
// AzureAuthorityHosts.AzureGovernment
// AzureAuthorityHosts.AzureChina
```

## Bearer Token Provider

For APIs that need raw tokens:

```typescript
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";

const credential = new DefaultAzureCredential();

// Create token provider for specific scope
const getAccessToken = getBearerTokenProvider(
  credential,
  "https://cognitiveservices.azure.com/.default"
);

// Get token when needed
const token = await getAccessToken();
console.log(`Bearer ${token}`);
```

## Debugging

```typescript
import { setLogLevel, AzureLogger } from "@azure/logger";

// Enable verbose logging
setLogLevel("verbose");

// Custom log handler
AzureLogger.log = (...args) => {
  console.log("[Azure Identity]", ...args);
};
```

## Best Practices

1. **Use DefaultAzureCredential** — Works across all environments
2. **Never hardcode credentials** — Use environment variables or managed identity
3. **Prefer managed identity** — No secrets to manage
4. **Use certificates over secrets** — More secure, easier to rotate
5. **Scope user-assigned identity** — Use for multi-tenant or specific permissions
6. **Enable logging for debugging** — Helps diagnose auth issues
7. **Handle token refresh** — Azure SDK handles this automatically

## See Also

- [Browser Authentication Reference](./browser-auth.md)
- [Azure Identity Best Practices](https://learn.microsoft.com/azure/developer/javascript/sdk/authentication/)
- [Managed Identity Overview](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview)

````
