Technology
Distributed Tracing Capacity Planning | SiamCafe Blog
2025-11-01· อ. บอม — SiamCafe.net· 11,508 คำ

Passkeys ????????? WebAuthn ?????????????????????

Passkeys ????????????????????????????????? passwordless authentication ????????????????????????????????? FIDO Alliance ????????? W3C ????????? public-key cryptography ????????? passwords ??????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????? biometrics (fingerprint, Face ID), security keys (YubiKey) ????????? device PIN

WebAuthn (Web Authentication API) ???????????? browser API ???????????????????????????????????????????????????????????? passkeys ???????????????????????????????????? authenticators ???????????? Touch ID, Windows Hello, Android biometrics ??????????????? shared secret ????????????????????? client ????????? server ?????????????????????????????? phishing, credential stuffing ????????? data breaches

Infrastructure as Code (IaC) ?????????????????? passkeys ????????????????????? ????????? provision ????????? manage WebAuthn infrastructure ???????????? code (Terraform, Pulumi) ?????????????????? database ?????????????????????????????? credentials, API servers, CDN, monitoring ??????????????? reproducible, version-controlled ????????? scalable

????????????????????? WebAuthn Server

Setup WebAuthn server ?????????????????? passkey authentication

# === WebAuthn Server Setup ===

# 1. Install dependencies (Node.js)
cat > package.json << 'EOF'
{
  "name": "webauthn-server",
  "version": "1.0.0",
  "dependencies": {
    "@simplewebauthn/server": "^9.0.0",
    "@simplewebauthn/types": "^9.0.0",
    "express": "^4.18.0",
    "express-session": "^1.17.0",
    "redis": "^4.6.0"
  }
}
EOF

npm install

# 2. Docker Compose
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
  webauthn-api:
    build: .
    ports:
      - "3000:3000"
    environment:
      - RP_NAME=MyApp
      - RP_ID=example.com
      - ORIGIN=https://example.com
      - REDIS_URL=redis://redis:6379
      - DATABASE_URL=postgres://user:pass@postgres:5432/webauthn
    depends_on:
      - redis
      - postgres

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: webauthn
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - pg-data:/var/lib/postgresql/data
      - ./schema.sql:/docker-entrypoint-initdb.d/schema.sql

volumes:
  redis-data:
  pg-data:
EOF

# 3. Database Schema
cat > schema.sql << 'EOF'
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username VARCHAR(255) UNIQUE NOT NULL,
    display_name VARCHAR(255),
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE credentials (
    id VARCHAR(512) PRIMARY KEY,
    user_id UUID REFERENCES users(id),
    public_key BYTEA NOT NULL,
    counter BIGINT DEFAULT 0,
    device_type VARCHAR(50),
    backed_up BOOLEAN DEFAULT false,
    transports TEXT[],
    created_at TIMESTAMPTZ DEFAULT NOW(),
    last_used_at TIMESTAMPTZ
);

CREATE INDEX idx_credentials_user ON credentials(user_id);
EOF

echo "WebAuthn server setup complete"

Infrastructure as Code ?????????????????? Passkeys

Terraform configuration ?????????????????? WebAuthn infrastructure

# === Terraform Infrastructure ===

cat > main.tf << 'EOF'
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.region
}

# VPC
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.5.0"
  
  name = "webauthn-vpc"
  cidr = "10.0.0.0/16"
  
  azs             = ["a", "b"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24"]
  
  enable_nat_gateway = true
}

# RDS PostgreSQL for credentials
resource "aws_db_instance" "webauthn" {
  identifier     = "webauthn-db"
  engine         = "postgres"
  engine_version = "16.1"
  instance_class = "db.t3.medium"
  
  allocated_storage     = 20
  max_allocated_storage = 100
  storage_encrypted     = true
  
  db_name  = "webauthn"
  username = "webauthn_admin"
  password = var.db_password
  
  vpc_security_group_ids = [aws_security_group.db.id]
  db_subnet_group_name   = aws_db_subnet_group.main.name
  
  backup_retention_period = 7
  multi_az               = true
  deletion_protection    = true
  
  tags = { Service = "webauthn" }
}

# ElastiCache Redis for sessions/challenges
resource "aws_elasticache_cluster" "sessions" {
  cluster_id           = "webauthn-sessions"
  engine               = "redis"
  node_type            = "cache.t3.medium"
  num_cache_nodes      = 1
  parameter_group_name = "default.redis7"
  port                 = 6379
  
  security_group_ids = [aws_security_group.redis.id]
  subnet_group_name  = aws_elasticache_subnet_group.main.name
}

# ECS Fargate for API
resource "aws_ecs_service" "webauthn_api" {
  name            = "webauthn-api"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.api.arn
  desired_count   = 2
  launch_type     = "FARGATE"
  
  network_configuration {
    subnets         = module.vpc.private_subnets
    security_groups = [aws_security_group.api.id]
  }
  
  load_balancer {
    target_group_arn = aws_lb_target_group.api.arn
    container_name   = "webauthn-api"
    container_port   = 3000
  }
}

# ALB with HTTPS
resource "aws_lb" "main" {
  name               = "webauthn-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = module.vpc.public_subnets
}

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.main.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = var.certificate_arn
  
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.api.arn
  }
}

# CloudWatch Alarms
resource "aws_cloudwatch_metric_alarm" "auth_errors" {
  alarm_name          = "webauthn-auth-errors"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "AuthenticationErrors"
  namespace           = "WebAuthn"
  period              = 300
  statistic           = "Sum"
  threshold           = 50
  alarm_description   = "High authentication error rate"
  alarm_actions       = [var.sns_topic_arn]
}

variable "region" { default = "ap-southeast-1" }
variable "db_password" { sensitive = true }
variable "certificate_arn" {}
variable "sns_topic_arn" {}
EOF

echo "Terraform infrastructure configured"

Implement Passkeys ?????? Web Application

Implementation ???????????? server ????????? client

#!/usr/bin/env python3
# webauthn_service.py ??? WebAuthn Passkeys Implementation
import json
import logging
import hashlib
import base64
import os
from typing import Dict, List, Optional

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("webauthn")

class WebAuthnService:
    """WebAuthn passkey registration and authentication"""
    
    def __init__(self, rp_id="example.com", rp_name="MyApp"):
        self.rp_id = rp_id
        self.rp_name = rp_name
        self.origin = f"https://{rp_id}"
        self.users = {}
        self.credentials = {}
        self.challenges = {}
    
    def generate_registration_options(self, user_id, username):
        """Generate options for passkey registration"""
        challenge = base64.urlsafe_b64encode(os.urandom(32)).decode()
        
        options = {
            "challenge": challenge,
            "rp": {
                "name": self.rp_name,
                "id": self.rp_id,
            },
            "user": {
                "id": base64.urlsafe_b64encode(user_id.encode()).decode(),
                "name": username,
                "displayName": username,
            },
            "pubKeyCredParams": [
                {"alg": -7, "type": "public-key"},   # ES256
                {"alg": -257, "type": "public-key"},  # RS256
            ],
            "timeout": 60000,
            "attestation": "none",
            "authenticatorSelection": {
                "authenticatorAttachment": "platform",
                "residentKey": "required",
                "userVerification": "required",
            },
            "excludeCredentials": self._get_user_credentials(user_id),
        }
        
        self.challenges[user_id] = challenge
        return options
    
    def verify_registration(self, user_id, credential):
        """Verify registration response"""
        expected_challenge = self.challenges.get(user_id)
        if not expected_challenge:
            return {"success": False, "error": "Challenge not found"}
        
        # In production: verify attestation, extract public key
        cred_id = credential.get("id", "")
        self.credentials[cred_id] = {
            "user_id": user_id,
            "public_key": credential.get("publicKey", ""),
            "counter": 0,
            "device_type": credential.get("authenticatorAttachment", "platform"),
            "backed_up": credential.get("backedUp", False),
        }
        
        del self.challenges[user_id]
        return {"success": True, "credential_id": cred_id}
    
    def generate_authentication_options(self, user_id=None):
        """Generate options for passkey authentication"""
        challenge = base64.urlsafe_b64encode(os.urandom(32)).decode()
        
        options = {
            "challenge": challenge,
            "rpId": self.rp_id,
            "timeout": 60000,
            "userVerification": "required",
        }
        
        if user_id:
            options["allowCredentials"] = self._get_user_credentials(user_id)
            self.challenges[user_id] = challenge
        else:
            # Discoverable credentials (usernameless)
            options["allowCredentials"] = []
            self.challenges["_anonymous"] = challenge
        
        return options
    
    def verify_authentication(self, credential):
        """Verify authentication response"""
        cred_id = credential.get("id", "")
        stored = self.credentials.get(cred_id)
        
        if not stored:
            return {"success": False, "error": "Credential not found"}
        
        # In production: verify signature, check counter
        stored["counter"] += 1
        
        return {
            "success": True,
            "user_id": stored["user_id"],
            "counter": stored["counter"],
        }
    
    def _get_user_credentials(self, user_id):
        return [
            {"id": cid, "type": "public-key"}
            for cid, cred in self.credentials.items()
            if cred["user_id"] == user_id
        ]

# Demo
service = WebAuthnService(rp_id="example.com", rp_name="MyApp")

# Registration
reg_options = service.generate_registration_options("user-001", "john@example.com")
print(f"Registration Options:")
print(f"  RP: {reg_options['rp']['name']} ({reg_options['rp']['id']})")
print(f"  Challenge: {reg_options['challenge'][:30]}...")
print(f"  Algorithms: {[p['alg'] for p in reg_options['pubKeyCredParams']]}")

# Simulate registration
result = service.verify_registration("user-001", {
    "id": "cred-abc123",
    "publicKey": "mock-public-key",
    "authenticatorAttachment": "platform",
    "backedUp": True,
})
print(f"\nRegistration: {result}")

# Authentication
auth_options = service.generate_authentication_options("user-001")
print(f"\nAuth Options: challenge={auth_options['challenge'][:30]}...")

auth_result = service.verify_authentication({"id": "cred-abc123"})
print(f"Authentication: {auth_result}")

Security ????????? Best Practices

Security considerations ?????????????????? passkeys

# === Security Best Practices ===

cat > security_config.yaml << 'EOF'
passkeys_security:
  server_side:
    challenge:
      - "Generate cryptographically random challenge (32+ bytes)"
      - "Store challenge server-side (Redis with TTL 5min)"
      - "Validate challenge on response (prevent replay)"
      - "One-time use only (delete after verification)"
    
    credential_storage:
      - "Store public key only (never private key)"
      - "Encrypt credential data at rest"
      - "Use parameterized queries (prevent SQL injection)"
      - "Implement rate limiting on registration/authentication"
    
    origin_validation:
      - "Verify origin matches expected RP ID"
      - "HTTPS required (no HTTP)"
      - "Validate RP ID against allowed list"
    
    counter_verification:
      - "Track signature counter per credential"
      - "Reject if counter goes backward (cloned authenticator)"
      - "Alert on counter anomalies"

  client_side:
    - "Use Conditional UI (autofill) for seamless UX"
    - "Support both platform and cross-platform authenticators"
    - "Graceful fallback for unsupported browsers"
    - "Clear error messages for user guidance"

  infrastructure:
    - "HTTPS everywhere (TLS 1.3)"
    - "Database encryption at rest (AES-256)"
    - "Redis with AUTH and TLS"
    - "VPC isolation for backend services"
    - "WAF for API protection"
    - "DDoS protection (CloudFlare/AWS Shield)"

  compliance:
    - "FIDO2 certification for authenticators"
    - "WebAuthn Level 2 specification compliance"
    - "GDPR: user can delete passkeys"
    - "Audit logging for all auth events"
EOF

python3 -c "
import yaml
with open('security_config.yaml') as f:
    data = yaml.safe_load(f)
sec = data['passkeys_security']
print('Passkeys Security Best Practices:')
print('\nServer-side:')
for item in sec['server_side']['challenge'][:3]:
    print(f'  - {item}')
print('\nInfrastructure:')
for item in sec['infrastructure'][:4]:
    print(f'  - {item}')
"

echo "Security guide ready"

Monitoring ????????? Analytics

?????????????????? passkey authentication

#!/usr/bin/env python3
# passkey_monitor.py ??? Passkeys Monitoring & Analytics
import json
import logging
from typing import Dict, List

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("monitor")

class PasskeyMonitor:
    def __init__(self):
        pass
    
    def dashboard(self):
        return {
            "adoption_metrics": {
                "total_users": 50000,
                "passkey_users": 12500,
                "adoption_rate": "25%",
                "trend": "+5% month-over-month",
                "by_platform": {
                    "iOS_Safari": 45,
                    "Android_Chrome": 30,
                    "Windows_Chrome": 15,
                    "macOS_Safari": 10,
                },
            },
            "auth_metrics_24h": {
                "total_authentications": 85000,
                "passkey_auths": 21250,
                "password_auths": 63750,
                "passkey_success_rate": "99.8%",
                "password_success_rate": "94.2%",
                "avg_auth_time_passkey_ms": 850,
                "avg_auth_time_password_ms": 3500,
            },
            "security_metrics": {
                "phishing_attempts_blocked": 0,
                "credential_stuffing_blocked": 245,
                "suspicious_counter_anomalies": 1,
                "failed_auth_attempts": 42,
            },
            "recommendations": [
                "Promote passkeys to remaining 75% users (in-app prompts)",
                "Add conditional UI for seamless passkey autofill",
                "Investigate 1 counter anomaly (possible cloned authenticator)",
                "Consider removing password option for passkey-enrolled users",
            ],
        }

monitor = PasskeyMonitor()
dash = monitor.dashboard()
adoption = dash["adoption_metrics"]
print(f"Passkeys Dashboard:")
print(f"  Adoption: {adoption['adoption_rate']} ({adoption['passkey_users']:,}/{adoption['total_users']:,})")
print(f"  Trend: {adoption['trend']}")

auth = dash["auth_metrics_24h"]
print(f"\nAuthentication (24h):")
print(f"  Passkey: {auth['passkey_auths']:,} ({auth['passkey_success_rate']}), avg {auth['avg_auth_time_passkey_ms']}ms")
print(f"  Password: {auth['password_auths']:,} ({auth['password_success_rate']}), avg {auth['avg_auth_time_password_ms']}ms")

sec = dash["security_metrics"]
print(f"\nSecurity: Phishing={sec['phishing_attempts_blocked']}, Stuffing={sec['credential_stuffing_blocked']}")

print(f"\nRecommendations:")
for r in dash["recommendations"]:
    print(f"  - {r}")

FAQ ??????????????????????????????????????????

Q: Passkeys ????????? Password ???????????????????????????????????????????

A: Password ???????????? shared secret ???????????? user ????????? server ????????? ??????????????????????????? phishing, brute force, credential stuffing, data breach ????????? server ????????? hack password ????????????????????? Passkeys ????????? public-key cryptography server ??????????????????????????? public key private key ?????????????????? device ????????? user ???????????????????????? ????????? server ????????? hack ??????????????? credentials ??????????????????????????? ????????????????????? phishing 100% ??????????????? browser verify origin ??????????????????????????? UX ?????????????????? ????????? scan fingerprint ???????????? Face ID ??????????????????????????? password ????????????????????? ???????????? browser/OS ?????????????????? (Chrome 108+, Safari 16+, Edge 108+), device ????????????????????????????????????????????? ???????????? recovery flow

Q: Infrastructure as Code ???????????????????????????????????? passkeys ??????????

A: ????????????????????????????????????????????? app ???????????? ?????????????????????????????????????????? production WebAuthn infrastructure ?????????????????? components Database (credentials), Cache (challenges), API server, Load balancer, Monitoring IaC ???????????? Reproducible ??????????????? environment ???????????????????????????????????????????????????, Version control ????????? change ????????? track, Disaster recovery ??????????????? infrastructure ????????????????????? code, Multi-environment dev/staging/prod ????????? code ??????????????? ?????????????????? startup/???????????????????????? ????????? managed services (Auth0, Firebase Auth, Supabase) ??????????????????????????? passkeys ????????????????????? manage infrastructure ????????? ?????????????????? enterprise ????????? IaC + self-hosted ????????? control ?????????????????????

Q: Passkeys sync ???????????? devices ???????????????????

A: ????????? ????????????????????? 2022 Apple, Google, Microsoft ?????????????????? synced passkeys Apple iCloud Keychain sync passkeys ???????????? iPhone, iPad, Mac, Google Password Manager sync ???????????? Android devices ????????? Chrome, Microsoft sync ???????????? Windows devices ???????????? Microsoft account Cross-platform ????????? QR code scan ????????? device ???????????? ???????????? iPhone scan QR ?????? Windows Chrome ???????????????????????? ????????? ecosystem ????????????????????? (Apple ??? Android) ?????????????????? sync ??????????????????????????? ??????????????????????????????????????? passkey ?????????????????? device ???????????? ????????????????????? QR cross-device authentication ??????????????? ????????? users ??????????????????????????????????????? passkeys (1 per ecosystem)

Q: Library ?????????????????????????????????????????? implement WebAuthn?

A: ????????????????????????????????? Node.js ????????? @simplewebauthn/server (??????????????? ?????????????????????) ???????????? fido2-lib, Python ????????? py_webauthn (Flask/Django) ???????????? python-fido2, Go ????????? go-webauthn/webauthn, Java ????????? java-webauthn-server (Yubico), .NET ????????? Fido2.AspNet Frontend ????????? @simplewebauthn/browser ???????????? native WebAuthn API ?????????????????? Managed services Auth0, Okta, Firebase Auth, Supabase Auth ?????????????????? passkeys built-in ????????????????????? implement ????????? ??????????????? ??????????????????????????? SimpleWebAuthn (Node.js) ???????????? py_webauthn (Python) ?????????????????????????????? documentation ??????

📖 บทความที่เกี่ยวข้อง

Distributed Tracing Batch Processing Pipelineอ่านบทความ → Java Virtual Threads Capacity Planningอ่านบทความ → Nuclei Scanner Capacity Planningอ่านบทความ → TTS Coqui Capacity Planningอ่านบทความ → Redis Pub Sub Capacity Planningอ่านบทความ →

📚 ดูบทความทั้งหมด →