Automatically refresh AWS SSO tokens in the background, eliminating the need for frequent manual re-authentication during your workday.
When using AWS SSO, access tokens typically expire after 1 hour, forcing you to repeatedly run aws sso login. This daemon monitors your AWS SSO token and automatically refreshes it before expiration, keeping you authenticated throughout the day.
- 🔄 Automatic token refresh - No more "SSO token expired" errors mid-work
- 🔔 macOS notifications - Get notified on refresh success/failure
- 📊 Comprehensive monitoring - Track token status and refresh history
- ⚙️ Fully configurable - All settings via environment variables
- 🛡️ Secure - Works directly with AWS CLI cache, no credential storage
- 🚀 Production-ready - pm2 managed with auto-restart and logging
- 📝 Rich logging - Structured logs with automatic rotation
┌─────────────────┐
│ AWS CLI │
│ aws sso login │ (one-time manual login)
└────────┬────────┘
│ writes tokens
▼
┌─────────────────────────────┐
│ ~/.aws/sso/cache/ │
│ <sha1-hash>.json │ ◄────┐
│ (SHA1 of SSO start URL) │ │
│ │ │
│ - accessToken │ │
│ - refreshToken │ │
│ - clientId/clientSecret │ │
│ - expiresAt │ │
└─────────────────────────────┘ │
▲ │
│ reads & updates │ refreshes
│ │
┌────────┴─────────┐ │
│ Daemon Process │─────────────────┘
│ (pm2 managed) │
│ │
│ - Monitors │
│ - Refreshes │
│ - Notifies │
└──────────────────┘
- Node.js v14 or higher
- AWS CLI configured with SSO
- macOS (for notifications - works on Linux/Windows without notifications)
- Existing AWS SSO profile configured
# Clone or download this repository
cd ~/Sites/aws-auto-refresh
# Run installation script
./scripts/install.shThis will:
- Install npm dependencies
- Install pm2 globally
- Create
.envfrom template - Make scripts executable
Edit .env and set your AWS profile:
vim .envRequired settings:
AWS_SSO_PROFILE=my-aws-profile
AWS_SSO_SESSION=my-sso-sessionYou can find these values in ~/.aws/config:
[profile my-aws-profile]
sso_session = my-sso-session
sso_account_id = 123456789012
sso_role_name = MyRoleName
region = us-east-1
[sso-session my-sso-session]
sso_start_url = https://my-organization.awsapps.com/start
sso_region = us-east-1
sso_registration_scopes = sso:account:accessaws sso login --profile my-aws-profileThis creates the initial token cache that the daemon will maintain.
./scripts/start.shThat's it! The daemon is now running and will keep your tokens fresh.
./scripts/status.shOutput:
📊 AWS SSO Token Refresh - Status
=================================
🔧 Process Status:
status : online
uptime : 2h 15m
restarts : 0
memory : 45.2MB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔑 Token Status:
✅ Token is valid
⏰ Time remaining: 45m
📅 Expires at: 1/24/2026, 2:30:00 PM
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📝 Recent Activity:
2026-01-24 13:45:23 [info] 🔄 Token expires in 4 minutes - refreshing now
2026-01-24 13:45:24 [info] ✅ Token refresh successful
# View last 50 lines
./scripts/logs.sh
# Follow logs in real-time
./scripts/logs.sh --follow
# View last 100 lines
./scripts/logs.sh --lines 100./scripts/restart.shUseful after changing .env configuration.
./scripts/stop.shJust use AWS CLI normally - tokens are kept fresh automatically!
# No need to run aws sso login anymore!
aws s3 ls --profile my-aws-profile
aws sts get-caller-identity --profile my-aws-profile
aws ec2 describe-instances --profile my-aws-profileAll configuration is done via environment variables in .env:
| Variable | Description | Example |
|---|---|---|
AWS_SSO_PROFILE |
Your AWS profile name | my-aws-profile |
AWS_SSO_SESSION |
Your SSO session name | my-sso-session |
| Variable | Description | Default |
|---|---|---|
AWS_SSO_CACHE_DIR |
AWS SSO cache directory | ~/.aws/sso/cache |
AWS_REGION |
AWS region | us-east-1 |
REFRESH_CHECK_INTERVAL |
Check interval (seconds) | 60 |
REFRESH_THRESHOLD |
Refresh before expiry (seconds) | 300 (5 min) |
MAX_RETRY_ATTEMPTS |
Retry failed refreshes | 3 |
RETRY_BACKOFF_SECONDS |
Wait between retries | 10 |
LOG_LEVEL |
Logging verbosity | info |
LOG_FILE |
Log file path | ./logs/refresh.log |
LOG_MAX_SIZE |
Max log file size | 10M |
LOG_MAX_FILES |
Number of log files to keep | 5 |
NOTIFY_ON_SUCCESS |
Notify on refresh success | false |
NOTIFY_ON_ERROR |
Notify on refresh error | true |
NOTIFY_ON_STARTUP |
Notify when daemon starts | true |
NOTIFY_SOUND |
macOS notification sound | default |
# Run all tests
npm test
# Run tests in watch mode (auto-rerun on changes)
npm run test:watch
# Run tests with coverage report
npm run test:coverage
# Type check without running tests
npm run type-check- Unit Tests:
tests/unit/*.test.js - Coverage Threshold: 70% (branches, functions, lines, statements)
- Test Framework: Jest
- Assertion Library: Jest built-in
# Run only config tests
npm test -- config.test.js
# Run tests matching pattern
npm test -- --testNamePattern="token refresh"After running npm run test:coverage, view the coverage report:
open coverage/lcov-report/index.html| Test File | What It Tests |
|---|---|
config.test.js |
Configuration loading and validation |
logger.test.js |
Logging functionality |
cache-manager.test.js |
AWS cache file operations |
token-refresher.test.js |
OIDC token refresh logic |
notifier.test.js |
macOS notification system |
When contributing tests:
- Use descriptive test names:
should refresh token when expiring soon - Test error conditions and edge cases
- Mock external dependencies (AWS cache files, OIDC API)
- Maintain or improve the 70% coverage threshold
- Follow existing test patterns in
tests/unit/
Jest is configured in package.json:
{
"jest": {
"testEnvironment": "node",
"coverageThreshold": {
"global": {
"branches": 70,
"functions": 70,
"lines": 70,
"statements": 70
}
}
}
}The daemon sends macOS notifications for important events:
- ✅ Token Refreshed - When token is successfully refreshed (optional)
- ❌ Refresh Failed - When token refresh fails
⚠️ Expiring Soon - When token is about to expire- 🔐 Re-login Required - When refresh token has expired
- 🚀 Daemon Started - When daemon starts (optional)
Check configuration:
cat .env
# Ensure AWS_SSO_PROFILE and AWS_SSO_SESSION are set correctlyCheck if already running:
pm2 listView error logs:
./scripts/logs.shVerify cache file exists:
ls -la ~/.aws/sso/cache/Check daemon logs:
./scripts/logs.sh --followTry manual login:
aws sso login --profile <your-profile>
./scripts/restart.shCheck profile name matches:
grep AWS_SSO_PROFILE .env
cat ~/.aws/config | grep profileVerify cache file is being updated:
./scripts/status.shThe refresh token has expired (typically 90 days). Re-login:
aws sso login --profile <your-profile>
./scripts/restart.shCheck for issues:
pm2 monitRestart daemon:
./scripts/restart.shQ: How do I monitor multiple AWS profiles simultaneously?
A: Run a separate daemon instance for each profile. Here's a complete setup guide:
Step 1: Create separate directories
# Create parent directory for all profile instances
mkdir -p ~/aws-refresh
# Create directory for each profile
mkdir -p ~/aws-refresh/profile-dev
mkdir -p ~/aws-refresh/profile-prod
mkdir -p ~/aws-refresh/profile-stagingStep 2: Copy project to each directory
# Copy entire project to each profile directory
cp -r ~/Sites/aws-auto-refresh ~/aws-refresh/profile-dev/
cp -r ~/Sites/aws-auto-refresh ~/aws-refresh/profile-prod/
cp -r ~/Sites/aws-auto-refresh ~/aws-refresh/profile-staging/Step 3: Configure each instance
# Configure dev profile
cd ~/aws-refresh/profile-dev/aws-auto-refresh
cp .env.example .env
vim .envEdit .env for dev profile:
# Required: Set your dev profile details
AWS_SSO_PROFILE=my-aws-dev-profile
AWS_SSO_SESSION=my-sso-session
# IMPORTANT: Use unique PM2 app name to avoid conflicts
PM2_APP_NAME=aws-sso-refresh-dev
# Optional: Use different log file
LOG_FILE=./logs/refresh-dev.logRepeat for prod profile:
cd ~/aws-refresh/profile-prod/aws-auto-refresh
cp .env.example .env
vim .envEdit .env for prod profile:
AWS_SSO_PROFILE=my-aws-prod-profile
AWS_SSO_SESSION=my-sso-session
# Different PM2 app name
PM2_APP_NAME=aws-sso-refresh-prod
LOG_FILE=./logs/refresh-prod.logStep 4: Login to each profile
# Login to dev
aws sso login --profile my-aws-dev-profile
# Login to prod
aws sso login --profile my-aws-prod-profile
# Login to staging
aws sso login --profile my-aws-staging-profileStep 5: Start all daemons
# Start dev daemon
cd ~/aws-refresh/profile-dev/aws-auto-refresh && ./scripts/start.sh
# Start prod daemon
cd ~/aws-refresh/profile-prod/aws-auto-refresh && ./scripts/start.sh
# Start staging daemon
cd ~/aws-refresh/profile-staging/aws-auto-refresh && ./scripts/start.shStep 6: Verify all instances are running
pm2 listExpected output:
┌─────┬──────────────────────────┬─────────┬─────────┬─────────┐
│ id │ name │ status │ cpu │ memory │
├─────┼──────────────────────────┼─────────┼─────────┼─────────┤
│ 0 │ aws-sso-refresh-dev │ online │ 0% │ 45.2 MB │
│ 1 │ aws-sso-refresh-prod │ online │ 0% │ 44.8 MB │
│ 2 │ aws-sso-refresh-staging │ online │ 0% │ 45.5 MB │
└─────┴──────────────────────────┴─────────┴─────────┴─────────┘
Managing multiple instances:
# Check status of specific profile
cd ~/aws-refresh/profile-dev/aws-auto-refresh && ./scripts/status.sh
# View logs for specific profile
pm2 logs aws-sso-refresh-dev
pm2 logs aws-sso-refresh-prod
# Restart specific profile
pm2 restart aws-sso-refresh-dev
# Stop specific profile
pm2 stop aws-sso-refresh-prod
# Stop all profiles
pm2 stop allTroubleshooting multi-profile setup:
Profile names conflict:
# Ensure PM2_APP_NAME is unique in each .env file
grep PM2_APP_NAME ~/aws-refresh/*/aws-auto-refresh/.env
# If duplicates found, edit and use unique namesWrong tokens being refreshed:
# Verify each daemon is using correct profile
pm2 logs aws-sso-refresh-dev --lines 20 | grep "AWS_SSO_PROFILE"
# Check .env configuration
cat ~/aws-refresh/profile-dev/aws-auto-refresh/.env | grep AWS_SSO_PROFILECache file conflicts: Each profile uses a different cache file (based on SHA1 of SSO start URL), so there should be no conflicts. Verify:
# List all cache files
ls -la ~/.aws/sso/cache/
# Each profile should have its own cache fileAlternative: Docker containers (advanced)
For cleaner isolation, run each profile in a Docker container:
# Create Dockerfile
cat > Dockerfile <<EOF
FROM node:14-alpine
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "src/index.js"]
EOF
# Run dev profile container
docker run -d \
--name aws-sso-dev \
-v ~/.aws:/root/.aws \
-e AWS_SSO_PROFILE=my-aws-dev-profile \
-e AWS_SSO_SESSION=my-sso-session \
aws-sso-refresh
# Run prod profile container
docker run -d \
--name aws-sso-prod \
-v ~/.aws:/root/.aws \
-e AWS_SSO_PROFILE=my-aws-prod-profile \
-e AWS_SSO_SESSION=my-sso-session \
aws-sso-refreshNote: macOS notifications won't work inside Docker containers.
Practical usage examples are available in the examples/ directory:
- basic-usage.js - Simple daemon setup (equivalent to
npm start) - multi-profile.js - Managing multiple AWS profiles
- programmatic.js - Using as a library in your code
- custom-notifications.js - Custom notification handlers (Slack, email, webhooks)
- status-check.js - Checking token status programmatically
Run any example from the project root:
node examples/basic-usage.jsSee the examples README for detailed documentation of each example.
# Save pm2 configuration
pm2 save
# Setup startup script
pm2 startup
# Follow the instructions shown
# Verify
pm2 listNow the daemon will start automatically when you login.
For verbose logging:
# Edit .env
LOG_LEVEL=debug
# Restart daemon
./scripts/restart.sh
# View detailed logs
./scripts/logs.sh --followTo check tokens more/less frequently:
# Edit .env
REFRESH_CHECK_INTERVAL=30 # Check every 30 seconds
# Or less frequently
REFRESH_CHECK_INTERVAL=120 # Check every 2 minutes
# Restart
./scripts/restart.shTo refresh earlier/later before expiration:
# Edit .env
REFRESH_THRESHOLD=600 # Refresh 10 minutes before expiry
# Or later
REFRESH_THRESHOLD=60 # Refresh 1 minute before expiry
# Restart
./scripts/restart.shaws-auto-refresh/
├── .env # Your configuration (git-ignored)
├── .env.example # Configuration template
├── .gitignore # Git ignore rules
├── package.json # Dependencies
├── ecosystem.config.js # pm2 configuration
├── src/
│ ├── index.js # Main daemon entry point (227 lines)
│ ├── config.js # Config loader & validator (192 lines)
│ ├── logger.js # Winston logging setup (153 lines)
│ ├── cache-manager.js # AWS SSO cache reader/writer (372 lines)
│ ├── token-refresher.js # OIDC token refresh logic (239 lines)
│ └── notifier.js # macOS notification manager (172 lines)
├── scripts/
│ ├── install.sh # Installation script
│ ├── start.sh # Start daemon
│ ├── stop.sh # Stop daemon
│ ├── restart.sh # Restart daemon
│ ├── status.sh # Check status
│ └── logs.sh # View logs
├── logs/ # Log files (auto-created, git-ignored)
└── README.md # This file
config.js - Configuration Management
- Loads and validates environment variables from
.env - Applies sensible defaults for optional settings
- Validates required fields (profile, session, region)
- Expands home directory paths (
~/.aws/sso/cache) - Converts time intervals to milliseconds
- Provides configuration summary for logging
logger.js - Logging Infrastructure
- Winston-based structured logging with JSON format
- Daily log rotation with configurable retention
- Separate console (human-readable) and file (JSON) formats
- Custom log methods (startup, success, failure, refresh, token)
- Exception and rejection handling
- Log levels: debug, info, warn, error
cache-manager.js - AWS Cache Integration
- Reads AWS config file (
~/.aws/config) to find SSO settings - Computes cache filename (SHA1 of SSO start URL)
- Reads/validates cache file structure
- Atomic writes with backup/restore on failure
- Token expiry calculations and threshold checking
- Human-readable time formatting
token-refresher.js - OIDC Token Refresh
- Posts to AWS OIDC endpoint with refresh token grant
- Validates response structure before using
- Comprehensive error handling (network, auth, timeout)
- Retry logic with linear backoff
- Distinguishes retryable vs non-retryable errors
- Never logs sensitive token data
notifier.js - User Notifications
- Native macOS notification center integration
- Configurable notification types (success, error, warning, info)
- Auto-dismiss after timeout
- Custom sounds per notification type
- Configuration-based filtering
index.js - Main Daemon Process
- Validates configuration on startup
- Sets up signal handlers (SIGINT, SIGTERM)
- Implements monitoring loop with configurable interval
- Coordinates all modules to refresh tokens
- Tracks consecutive failures
- Handles graceful shutdown
- Startup: Validate config → Setup handlers → Start monitoring
- Check Loop: Read cache → Check expiry → Refresh if needed
- Refresh: Extract credentials → Call OIDC API → Update cache
- Notify: Send macOS notification based on outcome
- Repeat: Wait for next interval and check again
- Shutdown: Stop monitoring → Notify user → Exit
This daemon follows enterprise security best practices:
- ✅ No credential storage - Uses AWS CLI cache directly, never stores credentials
- ✅ Atomic file writes - Prevents cache corruption with backup/restore mechanism
- ✅ No tokens in logs - Only metadata logged, never actual token values
- ✅ Secure file permissions - Cache files kept at 600 (user read/write only)
- ✅ Process isolation - Runs as your user, no elevated privileges required
- ✅ HTTPS only - All OIDC API calls use HTTPS
- ✅ Input validation - All configuration validated before use
- ✅ Safe error messages - Error messages never expose sensitive data
Safe to log (metadata only):
- Token expiry timestamps
- Token validity flags (hasAccessToken: true/false)
- Refresh success/failure status
- Configuration values (non-sensitive)
Never logged:
- Actual access tokens
- Refresh tokens
- Client secrets
- Any JWT token contents
The .gitignore file excludes:
.env- Contains your profile/session nameslogs/- May contain operational data*.backup- Cache backup files*.tmp- Temporary cache files.pm2/- PM2 runtime data
Never commit:
- Your
.envfile - AWS credentials or tokens
- Log files
- Cache files
This section catalogs common errors you may encounter and how to resolve them.
Cause: The AWS_SSO_PROFILE environment variable is not set in your .env file.
Solution:
# Edit .env and add your AWS profile name
vim .env
# Add this line:
AWS_SSO_PROFILE=my-aws-profileFind your profile name:
cat ~/.aws/config | grep -E '^\[profile 'Cause: The AWS_SSO_SESSION environment variable is not set in your .env file.
Solution:
# Edit .env and add your SSO session name
vim .env
# Add this line:
AWS_SSO_SESSION=my-sso-sessionFind your session name:
cat ~/.aws/config | grep -E '^\[sso-session 'Cause: Invalid value for LOG_LEVEL in .env.
Solution:
# Valid values only
LOG_LEVEL=info # or debug, warn, errorCause: REFRESH_CHECK_INTERVAL is set to 0 or negative value.
Solution:
# Set to positive number (seconds)
REFRESH_CHECK_INTERVAL=60 # Check every 60 secondsCause: REFRESH_THRESHOLD is set to 0 or negative value.
Solution:
# Set to positive number (seconds)
REFRESH_THRESHOLD=300 # Refresh 5 minutes before expiryCause: AWS SSO cache file is corrupted or incomplete. This typically happens if:
- You haven't run
aws sso loginyet - Cache file was manually edited incorrectly
- Incomplete/interrupted AWS login process
Solution:
# Re-login to AWS SSO
aws sso login --profile your-profile
# Restart daemon
./scripts/restart.shCause: No cache file exists for your SSO session. This means you haven't logged in yet or the cache file was deleted.
Solution:
# Login to AWS SSO (this creates the cache file)
aws sso login --profile your-profile
# Verify cache file was created
ls -la ~/.aws/sso/cache/
# Start daemon
./scripts/start.shCause: Insufficient permissions to read AWS SSO cache directory.
Solution:
# Fix permissions on cache directory
chmod 700 ~/.aws/sso/cache
chmod 600 ~/.aws/sso/cache/*
# Restart daemon
./scripts/restart.shFull error message:
⚠️ Your AWS SSO refresh token is invalid or expired.
This typically means you need to re-authenticate with AWS SSO.
Please run the following command:
aws sso login --profile your-profile
Then restart this daemon:
./scripts/restart.sh
Cause: Your refresh token has expired (typically after 90 days) or was invalidated.
Solution:
# Re-authenticate with AWS SSO
aws sso login --profile your-profile
# Restart daemon to pick up new tokens
./scripts/restart.shPrevention: Refresh tokens typically last 90 days. Make sure to use the daemon regularly to avoid expiration.
Cause: The clientId or clientSecret in your cache file is invalid. This can happen if:
- Cache file was manually edited
- AWS revoked the client credentials
- Corrupted cache during write
Solution:
# Re-login to get fresh credentials
aws sso login --profile your-profile
# Restart daemon
./scripts/restart.shCause: AWS OIDC endpoint returned unexpected response format. This is rare and typically indicates:
- AWS service issue
- Network proxy modifying responses
- Outdated AWS CLI version
Solution:
# 1. Check AWS CLI version (should be >= 2.0)
aws --version
# 2. Update AWS CLI if needed
# macOS: brew upgrade awscli
# Linux: pip install --upgrade awscli
# 3. Try manual login
aws sso login --profile your-profile
# 4. Check daemon logs for full error details
./scripts/logs.sh --lines 50Cause: Daemon was stopped while a token refresh was in progress. This is normal during shutdown.
Solution: No action needed. This is an informational message that appears when you stop the daemon during a refresh operation.
Full error message:
Network error during token refresh: ECONNREFUSED
Cannot connect to AWS OIDC endpoint
Cause: Cannot connect to AWS OIDC endpoint. Possible reasons:
- No internet connection
- Corporate firewall blocking AWS endpoints
- VPN required but not connected
- AWS service outage
Solution:
# 1. Check internet connectivity
ping 8.8.8.8
# 2. Check if you can reach AWS
ping oidc.us-east-1.amazonaws.com
# 3. If behind corporate firewall, check proxy settings
env | grep -i proxy
# 4. Try connecting to AWS directly
aws sts get-caller-identity
# 5. Check AWS service health
# Visit: https://status.aws.amazon.com/Cause: Request to AWS OIDC endpoint timed out (default: 30 seconds). Possible reasons:
- Slow internet connection
- AWS service degradation
- Network congestion
Solution:
# 1. Check network latency to AWS
ping -c 5 oidc.us-east-1.amazonaws.com
# 2. View logs for retry attempts
./scripts/logs.sh --follow
# 3. Daemon will automatically retry with backoff
# If persistent, check AWS service healthThe daemon automatically retries failed requests up to 3 times with 10-second delays.
Cause: Cannot resolve AWS OIDC endpoint hostname. Possible reasons:
- DNS server issues
- No internet connection
- Corporate DNS blocking AWS domains
Solution:
# 1. Check DNS resolution
nslookup oidc.us-east-1.amazonaws.com
# 2. Try alternate DNS (Google DNS)
# macOS: System Preferences > Network > Advanced > DNS
# Add: 8.8.8.8 and 8.8.4.4
# 3. Flush DNS cache
# macOS: sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
# Linux: sudo systemd-resolve --flush-caches
# 4. Restart daemon
./scripts/restart.shError: When running ./scripts/start.sh shows process already exists.
Solution:
# Check if already running
pm2 list
# If running, restart instead
./scripts/restart.sh
# Or stop and start fresh
./scripts/stop.sh
./scripts/start.shError: When running ./scripts/stop.sh shows "process or namespace not found".
Solution: Process is not running. This is normal if you haven't started it yet.
# Start the daemon
./scripts/start.sh
# Verify it's running
pm2 listSymptom: Daemon using more than 100MB RAM continuously.
Solution:
# Check memory usage
pm2 list
# View detailed stats
pm2 monit
# If memory leak suspected, restart
./scripts/restart.sh
# Monitor for a while
watch -n 10 'pm2 list'
# If problem persists, check logs for errors
./scripts/logs.sh --lines 100Normal memory usage: 40-50MB
Symptom: Daemon using high CPU continuously.
Solution:
# Check current CPU usage
pm2 list
# Check if refresh loop is stuck
./scripts/logs.sh --follow
# Restart daemon
./scripts/restart.sh
# If problem persists, check REFRESH_CHECK_INTERVAL
cat .env | grep REFRESH_CHECK_INTERVAL
# Increase interval if too aggressive
vim .env
# Set: REFRESH_CHECK_INTERVAL=120
./scripts/restart.shNormal CPU usage: Near 0% (spikes to 1-2% during checks)
Cause: macOS notification system is not available or denied permission.
Solution:
# 1. Check notification permissions
# System Preferences > Notifications > Node or Terminal
# Ensure notifications are allowed
# 2. Disable notifications if not needed
vim .env
# Set: NOTIFY_ON_SUCCESS=false
# Set: NOTIFY_ON_ERROR=false
./scripts/restart.shNotifications are optional. The daemon will work fine without them.
Cause: Jest configuration or test file syntax error.
Solution:
# Run with verbose output
npm test -- --verbose
# Check for syntax errors
npm run type-check
# Clear Jest cache
jest --clearCache
npm testCause: Your changes reduced code coverage below 70%.
Solution:
# Check current coverage
npm run test:coverage
# View coverage report
open coverage/lcov-report/index.html
# Add tests for uncovered code
# Then run coverage again
npm run test:coverageFor any error that's difficult to diagnose, enable debug logging:
# Edit .env
LOG_LEVEL=debug
# Restart daemon
./scripts/restart.sh
# Watch detailed logs
./scripts/logs.sh --followDebug logs include:
- Configuration values
- Cache file paths and contents (metadata only, not tokens)
- Full API request/response details (tokens redacted)
- Detailed error stack traces
- Timing information
Remember: Never share logs publicly without reviewing them for sensitive information first.
Q: Does this work with multiple AWS profiles?
A: Yes! To monitor multiple profiles simultaneously, run a separate daemon instance for each profile. See the Multiple AWS Profiles section in Troubleshooting for a complete setup guide including:
- Directory structure setup
- Configuration with unique PM2_APP_NAME per profile
- Starting and managing multiple instances
- Docker alternative for cleaner isolation
Q: What happens if my laptop sleeps?
A: The daemon will check the token immediately when it wakes up and refresh if needed. Token expiry is based on absolute timestamps, not elapsed runtime.
Q: Does this work on Linux/Windows?
A: Yes! All functionality works except macOS notifications. On Linux, you could adapt notifier.js to use libnotify. On Windows, use Windows notification API.
Q: Can I use this in CI/CD?
A: Not recommended. This is designed for developer workstations. For CI/CD, use:
- IAM roles (recommended)
- GitHub OIDC provider
- AWS temporary credentials via STS
Q: How much resources does it use?
A: Minimal:
- Memory: ~40-50MB RAM
- CPU: Negligible (only active during token checks, ~1 second per minute)
- Disk: Log files rotate, max ~50MB with default settings
- Network: One HTTPS request per token refresh
Q: What if the refresh token expires?
A: Refresh tokens typically last 90 days. When expired:
- You'll get a notification: "Re-login Required"
- Run:
aws sso login --profile <profile> - Daemon will automatically pick up new tokens
Q: Can I refresh tokens manually while daemon is running?
A: Yes! If you run aws sso login manually, the daemon will detect and use the new tokens on its next check cycle.
Q: What happens if AWS OIDC endpoint is down?
A: The daemon will:
- Retry up to MAX_RETRY_ATTEMPTS times with backoff
- Log the errors
- Send notification
- Continue monitoring (will retry on next interval)
Q: How do I know if it's working?
A: Multiple ways:
- Check status:
./scripts/status.sh - Watch logs:
./scripts/logs.sh --follow - Check notifications (if NOTIFY_ON_SUCCESS=true)
- Verify token expiry extends after refresh:
./scripts/status.sh
Q: Can I run this in Docker?
A: Possible but not ideal because:
- Needs access to
~/.aws/directory - macOS notifications won't work in container
- Better to run natively for development use
Q: Does this work with AWS IAM Identity Center (successor to SSO)?
A: Yes! AWS IAM Identity Center uses the same SSO cache structure and OIDC endpoints. Just configure your profile name and session name.
This project is designed for personal use. Feel free to fork and customize for your needs.
ISC
If you encounter issues:
- Check the Troubleshooting section
- View logs:
./scripts/logs.sh --follow - Check configuration:
cat .env - Verify AWS SSO is working:
aws sso login --profile <your-profile>
Built with: Node.js, pm2, Winston, Axios, node-notifier