playwright-ms-auth
v0.0.14
Published
Flexible authentication framework for Playwright tests supporting password and certificate auth with multiple credential providers
Maintainers
Readme
Playwright Microsoft Authentication
Enterprise-grade authentication solution for Playwright E2E tests with Microsoft Entra ID (formerly Azure AD)
A robust, production-ready authentication framework that simplifies Microsoft identity integration in Playwright test suites. Built with the Abstract Factory pattern, it supports both password and certificate-based authentication across multiple credential providers including Azure KeyVault, local files, environment variables, and GitHub Secrets.
Perfect for enterprise test automation requiring secure, reusable authentication flows with multi-region support and smart session caching. Get started in seconds with just email and password, or use enterprise-grade providers like Azure KeyVault for production.
Tech Stack
Core Dependencies
- Playwright (v1.44.1) - Browser automation framework
- TypeScript (v5.4.4) - Type-safe development
- Commander.js (v11.0.0) - CLI framework
- @azure/keyvault-secrets (v4.8.0) - Azure KeyVault integration
- @azure/identity (v4.2.1) - Azure authentication
Runtime Requirements
- Node.js ≥18
- Playwright Chromium browser
Build & Development
- TypeScript Compiler - ES2020 target, ESM modules
- Rimraf - Cross-platform file cleanup
Features
- 🔐 Multiple Authentication Methods: Password and certificate-based authentication
- 🏭 Abstract Factory Pattern: Easily extensible credential provider system
- ☁️ Multiple Providers: Azure KeyVault, Local File, Environment Variables, GitHub Secrets
- 🌍 Multi-Region Support: Works with different Microsoft Entra endpoints
- 🔧 CLI Tool: Full-featured command-line interface with direct password support
- 🌳 Environment Variables: Complete configuration via environment variables
- 💾 Smart Caching: Automatic storage state management with expiration
- 📝 TypeScript: Full type safety and IntelliSense support
- 🐛 Debug Logging: Comprehensive logging for troubleshooting
- ⚡ Zero Config for Simple Cases: Just email and password to get started
Installation
npm install playwright-ms-authQuick Start
Using CLI
# Simple password authentication (for testing/development)
npx ms-auth login \
--url https://your-app.com \
--email [email protected] \
--password "your-password"
# Run in headful mode (visible browser window)
npx ms-auth login \
--url https://your-app.com \
--email [email protected] \
--password "your-password" \
--headful
# Authenticate with Azure KeyVault (recommended for production)
npx ms-auth login \
--url https://your-app.com \
--email [email protected] \
--credential-provider azure-keyvault \
--keyvault-endpoint https://your-vault.vault.azure.net \
--keyvault-secret your-secret-name
# Authenticate with local certificate file
npx ms-auth login \
--url https://your-app.com \
--email [email protected] \
--credential-type certificate \
--credential-provider local-file \
--local-file ./cert.pfxUsing Programmatically
import { authenticate, loadConfigFromEnv } from "playwright-ms-auth";
// Load configuration from environment variables
const config = loadConfigFromEnv();
// Perform authentication
await authenticate(config, "https://your-app.com");In Playwright Tests
import { test as base } from "@playwright/test";
import { loadStorageState, type MsAuthConfig } from "playwright-ms-auth";
const config: MsAuthConfig = {
email: "[email protected]",
credentialType: "certificate",
credentialProvider: "azure-keyvault",
providerConfig: {
keyVaultEndpoint: "https://your-vault.vault.azure.net",
secretName: "your-cert-secret",
},
};
const test = base.extend({
context: async ({ browser }, use) => {
const storagePath = await loadStorageState(config);
const context = await browser.newContext({ storageState: storagePath });
await use(context);
await context.close();
},
});
test("authenticated test", async ({ page }) => {
await page.goto("https://your-app.com");
// You're already authenticated!
});Credential Providers
Azure KeyVault
Store credentials securely in Azure KeyVault.
const config: MsAuthConfig = {
email: "[email protected]",
credentialType: "certificate", // or 'password'
credentialProvider: "azure-keyvault",
providerConfig: {
keyVaultEndpoint: "https://your-vault.vault.azure.net",
secretName: "your-secret-name",
secretVersion: "latest", // optional
},
};Environment Variables:
MS_AUTH_KEYVAULT_ENDPOINTMS_AUTH_KEYVAULT_SECRET_NAME
Local File
Read credentials from local file system.
const config: MsAuthConfig = {
email: "[email protected]",
credentialType: "certificate",
credentialProvider: "local-file",
providerConfig: {
filePath: "./path/to/cert.pfx",
certificatePassword: "optional-password", // for encrypted certificates
},
};Environment Variables:
MS_AUTH_LOCAL_FILE_PATHMS_AUTH_CERTIFICATE_PASSWORD
Environment Variables
Read credentials directly from environment variables. Also used when passing --password via CLI.
const config: MsAuthConfig = {
email: "[email protected]",
credentialType: "password",
credentialProvider: "environment",
providerConfig: {
variableName: "MY_PASSWORD_VAR",
},
};CLI Usage:
# Direct password (automatically uses environment provider)
npx ms-auth login \
--url https://your-app.com \
--email [email protected] \
--password "your-password"
# Or use environment variable
export MY_PASSWORD_VAR="your-password"
npx ms-auth login \
--url https://your-app.com \
--email [email protected] \
--credential-provider environment \
--env-variable MY_PASSWORD_VAREnvironment Variables:
MS_AUTH_ENV_VARIABLE_NAME
⚠️ Security Note: Using --password directly in CLI is not recommended for production. Use Azure KeyVault or other secure providers instead.
GitHub Secrets
Use GitHub Actions secrets (reads from environment).
const config: MsAuthConfig = {
email: "[email protected]",
credentialType: "certificate",
credentialProvider: "github-secrets",
providerConfig: {
repository: "owner/repo",
secretName: "MY_CERT_SECRET",
},
};Environment Variables:
MS_AUTH_GITHUB_REPOSITORYMS_AUTH_GITHUB_SECRET_NAMEMS_AUTH_GITHUB_TOKEN(optional)
Environment Variables
All configuration can be provided via environment variables. Run npx ms-auth env-help for complete list.
Core Configuration
MS_AUTH_EMAIL- User email addressMS_AUTH_CREDENTIAL_TYPE-passwordorcertificateMS_AUTH_CREDENTIAL_PROVIDER- Provider type (auto-set toenvironmentwhen using--password)MS_AUTH_OUTPUT_DIR- Directory for storage state files (defaults to project root)MS_AUTH_LOGIN_ENDPOINT- Entra endpoint (default:login.microsoftonline.com)MS_AUTH_STORAGE_STATE_EXPIRATION- Hours until state expires (default: 24)SYSTEM_DEBUG- Enable detailed debug logging (true/false, default:false)
Debugging
Enable detailed logging to troubleshoot authentication issues:
# Enable debug logging via environment variable
export SYSTEM_DEBUG=true
npx ms-auth login --url https://your-app.com --email [email protected] --password "your-password"
# Or inline
SYSTEM_DEBUG=true npx ms-auth login --url https://your-app.com --email [email protected] --password "your-password"
# In .env file
SYSTEM_DEBUG=trueWhen SYSTEM_DEBUG=true, you'll see detailed logs including:
- Authentication flow steps
- Credential provider operations
- Browser launch parameters
- Storage state paths
- Screenshot locations
- URL redirects and navigation events
Quick Reference
| Use Case | Command |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Development/Testing | npx ms-auth login --url <url> --email <email> --password <pwd> |
| Production (KeyVault) | npx ms-auth login --url <url> --email <email> --credential-provider azure-keyvault --keyvault-endpoint <endpoint> --keyvault-secret <secret> |
| Certificate Auth | npx ms-auth login --url <url> --email <email> --credential-type certificate --credential-provider local-file --local-file <path> |
| Environment Var | npx ms-auth login --url <url> --email <email> --credential-provider environment --env-variable MY_VAR |
Architecture
High-Level Architecture
flowchart TB
subgraph CLI["CLI Layer"]
CMD[ms-auth CLI]
end
subgraph Core["Core Authentication"]
AUTH[authenticate.ts]
CERT[certAuth.ts]
CONFIG[config.ts]
end
subgraph Factory["Factory Pattern"]
FACTORY[CredentialProviderFactory]
end
subgraph Providers["Credential Providers"]
AKV[AzureKeyVaultProvider]
LOCAL[LocalFileProvider]
ENV[EnvironmentProvider]
GH[GitHubSecretsProvider]
end
subgraph Storage["State Management"]
UTILS[utils.ts]
CACHE[(Storage State Cache)]
end
subgraph Browser["Playwright Browser"]
PW[Chromium Browser]
ENTRA[Microsoft Entra ID]
end
CMD --> CONFIG
CONFIG --> AUTH
AUTH --> FACTORY
FACTORY --> AKV
FACTORY --> LOCAL
FACTORY --> ENV
FACTORY --> GH
AUTH --> CERT
AUTH --> UTILS
UTILS --> CACHE
AUTH --> PW
PW --> ENTRA
ENTRA --> CACHEAuthentication Flow
sequenceDiagram
participant User
participant CLI
participant Config
participant Factory
participant Provider
participant Auth
participant Browser
participant Entra
participant Storage
User->>CLI: ms-auth login
CLI->>Config: Load configuration
Config->>Factory: Create provider
Factory->>Provider: Instantiate
Auth->>Storage: Check cached state
alt State valid
Storage-->>Auth: Return cached state
else State expired/missing
Auth->>Provider: Get credential
Provider-->>Auth: Return credential
Auth->>Browser: Launch browser
Browser->>Entra: Navigate to login
alt Certificate Auth
Auth->>Browser: Intercept cert request
Browser->>Entra: Present certificate
else Password Auth
Auth->>Browser: Fill password
Browser->>Entra: Submit password
end
Entra-->>Browser: Authentication success
Browser-->>Auth: Session cookies
Auth->>Storage: Save storage state
end
Storage-->>User: Authentication completeFactory Pattern Implementation
classDiagram
class CredentialProvider {
<<abstract>>
+getProviderName() string
+validateConfig() void
+getCredential()* CredentialResult
}
class AzureKeyVaultProvider {
-keyVaultEndpoint: string
-secretName: string
+getCredential() CredentialResult
-createKeyVaultClient() SecretClient
}
class LocalFileProvider {
-filePath: string
-certificatePassword?: string
+getCredential() CredentialResult
-detectCredentialType() CredentialType
}
class EnvironmentProvider {
-variableName: string
+getCredential() CredentialResult
}
class GitHubSecretsProvider {
-repository: string
-secretName: string
+getCredential() CredentialResult
}
class CredentialProviderFactory {
+createProvider(type, config) CredentialProvider
+getSupportedProviders() string[]
}
class MsAuthConfig {
+email: string
+credentialType: CredentialType
+credentialProvider: ProviderType
+providerConfig: ProviderConfig
}
CredentialProvider <|-- AzureKeyVaultProvider
CredentialProvider <|-- LocalFileProvider
CredentialProvider <|-- EnvironmentProvider
CredentialProvider <|-- GitHubSecretsProvider
CredentialProviderFactory ..> CredentialProvider : creates
MsAuthConfig ..> CredentialProviderFactory : configuresData Flow Diagram
flowchart LR
subgraph Input["Configuration Sources"]
ENV_VARS[Environment Variables]
CLI_ARGS[CLI Arguments]
CODE[Programmatic Config]
end
subgraph Processing["Processing"]
CONFIG_LOADER[Config Loader]
VALIDATOR[Config Validator]
end
subgraph Credential["Credential Retrieval"]
KV[(Azure KeyVault)]
FS[(File System)]
ENV_SYS[(Environment)]
GH_API[(GitHub API)]
end
subgraph Auth["Authentication"]
BROWSER[Browser Session]
CERT_HANDLER[Certificate Handler]
PWD_HANDLER[Password Handler]
end
subgraph Output["Output"]
STATE_FILE[Storage State File]
LOGS[Debug Logs]
end
ENV_VARS --> CONFIG_LOADER
CLI_ARGS --> CONFIG_LOADER
CODE --> CONFIG_LOADER
CONFIG_LOADER --> VALIDATOR
VALIDATOR --> KV
VALIDATOR --> FS
VALIDATOR --> ENV_SYS
VALIDATOR --> GH_API
KV --> CERT_HANDLER
FS --> CERT_HANDLER
ENV_SYS --> PWD_HANDLER
GH_API --> CERT_HANDLER
CERT_HANDLER --> BROWSER
PWD_HANDLER --> BROWSER
BROWSER --> STATE_FILE
BROWSER --> LOGSProvider Hierarchy
graph TD
A[CredentialProvider<br/>Abstract Base Class] --> B[AzureKeyVaultProvider]
A --> C[LocalFileProvider]
A --> D[EnvironmentProvider]
A --> E[GitHubSecretsProvider]
B --> B1[Uses ChainedTokenCredential]
B --> B2[Supports AzureCLI, PowerShell,<br/>Developer, Interactive]
C --> C1[Auto-detects file type]
C --> C2[Supports .pfx, .p12, .txt, .pwd]
D --> D1[Direct env var access]
D --> D2[Auto-detects credential type]
E --> E1[Reads GitHub Actions secrets]
E --> E2[Converts to env vars]
style A fill:#e1f5ff
style B fill:#d4edda
style C fill:#d4edda
style D fill:#d4edda
style E fill:#d4eddaCode Structure
playwright-ms-auth/
├── src/
│ ├── types.ts # Type definitions & interfaces
│ ├── config.ts # Environment variable loader
│ ├── authenticate.ts # Main authentication orchestration
│ ├── certAuth.ts # Certificate auth route handler
│ ├── utils.ts # Logging & storage utilities
│ ├── cli.ts # Command-line interface
│ ├── index.ts # Public API exports
│ └── providers/
│ ├── CredentialProvider.ts # Abstract base class
│ ├── AzureKeyVaultProvider.ts # KeyVault implementation
│ ├── LocalFileProvider.ts # File system implementation
│ ├── EnvironmentProvider.ts # Environment var implementation
│ ├── GitHubSecretsProvider.ts # GitHub secrets implementation
│ ├── CredentialProviderFactory.ts # Factory pattern
│ └── index.ts # Provider exports
├── examples/
│ ├── msLogin.ts # Example authentication helper
│ ├── .env.example # Environment template
│ ├── package.json # Example dependencies
│ └── README.md # Example documentation
├── bin/
│ └── ms-auth # CLI executable
├── package.json
├── tsconfig.json
└── README.mdExamples
Check out the examples/ directory for a complete working example:
cd examples
npm install
npm run loginThe example includes:
- 📝 Ready-to-use authentication helper (
msLogin.ts) - 🔧 Pre-configured environment file
- 📚 Complete documentation
- ⚡ NPM scripts for easy execution
See examples/README.md for details.
Abstract Factory Pattern
The package uses the Abstract Factory Pattern for extensibility:
CredentialProvider (abstract)
├── AzureKeyVaultProvider
├── LocalFileProvider
├── EnvironmentProvider
└── GitHubSecretsProvider
CredentialProviderFactory
└── createProvider(type, config)Adding Custom Providers
import { CredentialProvider, type CredentialResult } from "playwright-ms-auth";
class MyCustomProvider extends CredentialProvider {
getProviderName(): string {
return "My Custom Provider";
}
validateConfig(): void {
// Validate your config
}
async getCredential(): Promise<CredentialResult> {
// Retrieve credential from your source
return {
type: "password",
value: "my-password",
};
}
}Troubleshooting & FAQ
Authentication Issues
Q: Browser is not visible when using --headful flag
A: Make sure you're running the latest version and that Microsoft Edge is installed. The package uses Edge for better Windows compatibility.
# Verify Edge channel is working
npx playwright install msedgeQ: Authentication times out waiting for redirect
A: This usually happens when SharePoint redirects to a different page after login. The package automatically handles redirects to any page on the same domain. Enable debug logging to see the actual redirect:
SYSTEM_DEBUG=true npx ms-auth login --url https://your-site.com --email [email protected] --password "pwd"Q: "page.waitForURL: Timeout exceeded" error
A: The authentication may have succeeded but redirected to a different page than expected. Check the logs for "navigated to" message. This is normal for SharePoint sites that redirect to home pages.
Q: Screenshot saved to wrong location
A: Screenshots are saved to <project-root>/screenshots/ by default. To change this, set MS_AUTH_OUTPUT_DIR:
export MS_AUTH_OUTPUT_DIR=/path/to/custom/dirStorage State Issues
Q: Where are storage state files saved?
A: By default, storage state files are saved to <project-root>/.playwright-ms-auth/state-{email}.json. You can customize this with the MS_AUTH_OUTPUT_DIR environment variable.
Q: How long do storage states last?
A: Storage states expire after 24 hours by default. Configure with MS_AUTH_STORAGE_STATE_EXPIRATION (in hours):
export MS_AUTH_STORAGE_STATE_EXPIRATION=48 # 48 hoursQ: How do I force re-authentication?
A: Delete the storage state file or use the CLI:
# Find and delete the storage state file
rm .playwright-ms-auth/[email protected]
# Or use clearAuth from examples
npm run clear-authDebugging
Q: How do I enable detailed logging?
A: Set SYSTEM_DEBUG=true to see detailed authentication flow:
# Temporary (command line)
SYSTEM_DEBUG=true npx ms-auth login --url https://site.com --email [email protected] --password "pwd"
# Permanent (in .env file)
SYSTEM_DEBUG=trueDebug logs include:
- Credential provider operations
- Browser launch parameters (headless/headful)
- Storage state paths
- Screenshot locations
- Navigation events and redirects
- Authentication flow steps
Q: Authentication succeeds but I get errors in my tests
A: Verify the storage state file exists and check its timestamp:
# Check if file exists and when it was created
ls -la .playwright-ms-auth/state-*.json
# View file contents (check cookies)
cat .playwright-ms-auth/state-*.jsonQ: Getting "Cannot find module" errors
A: Make sure to rebuild after making changes:
npm run build
# If using examples directory
cd examples
rm -rf node_modules/playwright-ms-auth
npm installCertificate Authentication
Q: Certificate authentication fails with validation error
A: Ensure:
- Certificate is in PFX/P12 format
- Certificate is not expired
- Certificate password is correct (if encrypted)
- Certificate is trusted by the Entra tenant
Q: How do I convert PEM to PFX?
openssl pkcs12 -export -out cert.pfx -inkey private.key -in certificate.crtProduction Issues
Q: Should I use --password flag in production?
A: No. Use Azure KeyVault or other secure credential providers for production:
# Production (Azure KeyVault)
npx ms-auth login \
--url https://your-site.com \
--email [email protected] \
--credential-provider azure-keyvault \
--keyvault-endpoint https://vault.vault.azure.net \
--keyvault-secret secret-nameQ: How do I handle multiple environments?
A: Use different .env files or environment-specific configuration:
# Development
SYSTEM_DEBUG=true npm run login
# Production
MS_AUTH_CREDENTIAL_PROVIDER=azure-keyvault npm run loginQ: Can I use this in CI/CD pipelines?
A: Yes! Use GitHub Secrets or Azure KeyVault providers:
# GitHub Actions example
- name: Authenticate
env:
MS_AUTH_EMAIL: ${{ secrets.MS_AUTH_EMAIL }}
MS_USER_PASSWORD: ${{ secrets.MS_USER_PASSWORD }}
MS_AUTH_CREDENTIAL_PROVIDER: environment
MS_AUTH_ENV_VARIABLE_NAME: MS_USER_PASSWORD
run: npx ms-auth login --url https://your-site.comLicense
MIT
