Auth Audit Log 設計
身份系統不是只要「擋住攻擊」。
它還要能在事後回答:
誰登入了?
誰失敗了?
誰改了密碼?
誰停用了 MFA?
誰新增了管理員?
誰看了敏感資料?
誰匯出了資料?
誰用哪個 session 做了哪個高風險操作?如果回答不出來,系統就算功能正常,也很難說是安全的。
Auth Audit Log 的核心不是:
console.log 一下。而是建立一套可以支援:
- 安全調查。
- 使用者通知。
- 異常偵測。
- 法規稽核。
- 事故應變。
- 內部濫權追蹤。
- 高風險操作證據保存。
的事件紀錄系統。
OWASP Logging Cheat Sheet 也強調,應記錄具有安全意義的事件,例如 authentication successes/failures、authorization failures、敏感資料存取、管理員功能使用、權限變更等。也就是說,Auth Audit Log 是身份系統的安全感測器。
一、 一句話回答
如果面試官問:
Auth Audit Log 要怎麼設計?
可以先回答:
Auth Audit Log 要記錄所有和身份、Session、權限、安全設定與敏感操作有關的事件,例如註冊、登入成功/失敗、登出、MFA 驗證、忘記密碼、密碼變更、Session 撤銷、第三方登入綁定、權限變更、重新驗證、資料匯出與管理員操作。每筆事件應包含 actor、target、action、result、time、IP、user agent、session id、request id、risk score、驗證方式與必要 metadata,但不能記錄密碼、OTP、完整 token、完整敏感資料。Log 要不可被一般管理員任意修改或刪除,支援查詢、告警、保留政策與隱私最小化;高風險事件要能即時通知或送 SIEM。
短一點可以說:
Auth Audit Log 是身份系統的黑盒子:
出事時要能還原誰在什麼時間,用什麼身份,對什麼資源做了什麼。二、 Audit Log 和一般 Log 差在哪
一般 application log 常用來 debug:
API latency
SQL error
stack trace
request failedAuth Audit Log 則是安全證據:
user login success
password changed
mfa disabled
role granted
session revoked
sensitive data exported比較:
| 類型 | 目的 | 保存重點 |
|---|---|---|
| Access Log | HTTP 請求紀錄 | method、path、status、latency |
| Application Log | Debug / 運維 | error、trace、business state |
| Security Log | 安全事件偵測 | attack、blocked、risk |
| Auth Audit Log | 身份與權限證據 | actor、action、target、result、time |
它們可以送到同一個 log 平台,但語意要分清楚。
Audit log 不應該只是散落在應用程式 log 裡的文字。
它應該是結構化事件。
三、 什麼事件一定要記
身份系統至少要記這些。
1. 註冊與身份建立
- 註冊成功。
- 註冊失敗。
- Email 驗證成功/失敗。
- 手機驗證成功/失敗。
- 重寄驗證信。
- 邀請成員。
- 接受邀請。
- 帳號啟用。
- 帳號停用。
2. 登入與登出
- 登入成功。
- 登入失敗。
- 登入被 rate limit。
- 帳號被 lock / unlock。
- 登出目前裝置。
- 登出所有裝置。
- Session timeout。
- Session 被管理員撤銷。
3. MFA 與高強度驗證
- MFA 啟用。
- MFA 停用。
- MFA 驗證成功/失敗。
- Backup codes 產生。
- Backup code 使用。
- Passkey 新增/刪除。
- TOTP secret reset。
- Step-up authentication 成功/失敗。
4. 密碼與帳號恢復
- 忘記密碼請求。
- reset token 產生。
- reset token 使用成功/失敗。
- 密碼修改。
- 帳號恢復開始。
- 帳號恢復成功/失敗。
- 安全聯絡方式變更。
5. 第三方登入與 SSO
- 第三方登入成功/失敗。
- external identity 綁定。
- external identity 解除。
- SSO 登入成功/失敗。
- IdP group / role mapping 變更。
- OIDC / SAML assertion 驗證失敗。
6. 權限與管理員操作
- 角色授予。
- 角色撤銷。
- 權限變更。
- 新增管理員。
- 停用管理員。
- 管理員 MFA reset。
- IP allowlist 變更。
- 安全政策變更。
- Break-glass account 使用。
7. 敏感資料與高風險操作
- 查看完整個資。
- 查看醫療資料。
- 匯出資料。
- 下載報表。
- 修改收款帳號。
- 大額交易。
- 醫療授權。
- 文件簽章。
- impersonation 開始/結束。
這些事件不一定都屬於 Auth Service,但都和身份、權限與安全責任相關。
四、 Event Schema
Audit log 最重要的是欄位穩定。
可以設計成:
type AuthAuditEvent = {
id: string
eventType: string
action: string
result: 'success' | 'failure' | 'denied' | 'pending'
actorType: 'user' | 'admin' | 'system' | 'service'
actorId?: string
targetType?: string
targetId?: string
sessionId?: string
requestId: string
correlationId?: string
ip?: string
userAgent?: string
deviceId?: string
geo?: string
authMethod?: string
mfaMethod?: string
assuranceLevel?: string
reauthRequired?: boolean
reauthMethod?: string
riskScore?: number
reason?: string
metadata?: Record<string, unknown>
occurredAt: string
recordedAt: string
}資料庫概念:
create table auth_audit_logs (
id uuid primary key,
event_type text not null,
action text not null,
result text not null,
actor_type text not null,
actor_id uuid,
target_type text,
target_id text,
session_id uuid,
request_id text not null,
correlation_id text,
ip inet,
user_agent text,
device_id text,
geo text,
auth_method text,
mfa_method text,
assurance_level text,
reauth_required boolean,
reauth_method text,
risk_score integer,
reason text,
metadata jsonb,
occurred_at timestamp not null,
recorded_at timestamp not null
);欄位說明:
| 欄位 | 用途 |
|---|---|
event_type | 分類,例如 auth.login |
action | 具體動作,例如 login |
result | 成功、失敗、拒絕、等待中 |
actor | 誰做的 |
target | 影響誰或什麼資源 |
session_id | 哪個 session |
request_id | 單次 API 請求追蹤 |
correlation_id | 跨服務流程追蹤 |
ip/user_agent/device | 來源上下文 |
auth_method/mfa_method | 使用哪種驗證 |
assurance_level | 當時驗證強度 |
risk_score | 風控判斷 |
metadata | 事件特有補充資訊 |
五、 Event Naming
事件命名要穩定、可搜尋。
建議用階層式命名:
auth.register.success
auth.login.success
auth.login.failure
auth.logout.success
auth.password.reset_requested
auth.password.changed
auth.mfa.enabled
auth.mfa.disabled
auth.session.revoked
auth.reauth.success
auth.external_identity.linked
auth.role.granted
auth.admin.created
auth.data.export_requested
auth.sensitive_data.viewed也可以拆成:
category = auth
action = login
result = success重點是:
- 不要今天叫
login_fail,明天叫LOGIN_FAILED。 - 不要把重要語意塞在 message 字串裡。
- 不要用自然語言當唯一查詢依據。
- 要能讓 SIEM / dashboard / alert rule 穩定使用。
六、 不該記什麼
Audit log 很重要,但不能變成另一個資料外洩點。
不要記:
- 明文密碼。
- OTP。
- TOTP secret。
- recovery code 明文。
- reset token 明文。
- access token / refresh token 完整值。
- session id 原始值。
- 私鑰。
- 完整信用卡號。
- 完整病歷內容。
- 過多個資。
可以記:
- token hash prefix。
- session id hash。
- user id。
- resource id。
- masked email / phone。
- metadata 裡的安全摘要。
例如:
{
"eventType": "auth.password.reset_requested",
"actorType": "anonymous",
"targetType": "user",
"targetId": "user_123",
"metadata": {
"emailMasked": "a***@example.com"
}
}不要:
{
"resetToken": "raw-token-value"
}OWASP ASVS 和 Logging Cheat Sheet 都強調,不應把敏感資料寫進 log,並且 log 本身也要有存取控制。
七、 成功與失敗都要記
只記成功是不夠的。
很多攻擊訊號都在失敗裡:
- 密碼錯誤。
- MFA 失敗。
- OTP 猜測。
- reset token 失敗。
- session 無效。
- 權限不足。
- CSRF token 失敗。
- rate limit 觸發。
例如登入失敗:
{
"eventType": "auth.login.failure",
"result": "failure",
"actorType": "anonymous",
"targetType": "user",
"targetId": "user_123",
"ip": "203.0.113.10",
"reason": "invalid_password",
"riskScore": 42
}但要注意:
對外錯誤訊息要避免帳號枚舉,
對內 audit log 可以記錄更細 reason。也就是:
使用者看到:帳號或密碼錯誤
內部記錄:user exists, invalid password內部 log 的存取權限要嚴格。
八、 Actor 和 Target 要分清楚
Audit log 最常見的坑是:
只記 user_id。但很多事件有 actor 和 target。
例如管理員停用使用者:
actor = admin_1
target = user_9
action = disable_user管理員 impersonate 使用者:
actor = admin_1
target = user_9
effective_user = user_9系統自動撤銷 session:
actor = system
target = user_9
reason = risk_detected如果只記一個 user_id,事後會分不清:
這件事是使用者本人做的?
管理員替他做的?
系統自動做的?所以資料模型要明確支援:
- actor。
- target。
- resource。
- effective subject。
- reason。
九、 Request ID 與 Correlation ID
身份流程常常跨多個服務。
例如:
API Gateway
-> Auth Service
-> Risk Engine
-> MFA Service
-> Session Store
-> Notification Service如果每個服務各記一筆 log,但沒有共同 ID,就很難串起來。
建議:
| ID | 用途 |
|---|---|
request_id | 單一 HTTP request |
correlation_id | 一整個業務流程 |
session_id | 同一登入狀態 |
auth_event_id | 同一身份驗證事件 |
trace_id | 分散式 tracing |
例如登入加 MFA:
login request
-> password verified
-> mfa challenge created
-> mfa verified
-> session created它們可以共享同一個 correlation_id。
十、 Storage 設計
Audit log 的儲存要考慮:
- 寫入量。
- 查詢需求。
- 保留時間。
- 防竄改。
- 成本。
- 隱私。
- 告警延遲。
常見架構:
小系統可以直接寫資料庫。
大系統建議用 event queue,避免 audit 寫入拖慢主流程。
但高風險事件要注意:
不能因為 queue 掛了就完全沒有紀錄。可考慮:
- 本地 fallback log。
- 重試機制。
- dead letter queue。
- 寫入失敗告警。
- 對關鍵事件採同步或半同步寫入。
十一、 防竄改與存取控制
Audit log 如果可以被攻擊者刪掉,就失去價值。
應該考慮:
- Append-only。
- 一般管理員不能修改/刪除。
- 刪除或匯出 log 也要被記錄。
- 定期歸檔。
- 寫入獨立儲存。
- Object storage versioning / retention lock。
- hash chain 或簽章,依需求。
- 權限最小化。
例如高信任系統可以設計:
application writes audit event
-> audit writer append-only
-> daily file hash
-> hash 保存到獨立位置
-> archive 加 retention policy不一定每個產品都要做到這麼重。
但至少要避免:
super admin 在後台按一下就刪掉自己的 audit log。十二、 Retention 與隱私
Audit log 要保存多久?
答案不是越久越好。
要看:
- 法規。
- 風險等級。
- 使用者隱私。
- 儲存成本。
- 事故調查需求。
- 資料刪除需求。
可以分層:
| 類型 | 保存策略 |
|---|---|
| 一般登入事件 | 例如 90 天到 1 年,依需求 |
| 高風險安全事件 | 更長保存 |
| 管理員操作 | 通常更長保存 |
| 金融/醫療敏感操作 | 依法規與合約要求保存 |
| Debug log | 短期保存 |
也要處理:
- 使用者刪除帳號後 audit log 是否保留。
- 保留時是否 pseudonymize。
- metadata 是否含個資。
- 查詢權限是否受控。
工程上可以把:
user_id保留為內部識別碼,但移除不必要的 email、phone、姓名等可讀個資。
十三、 Alerting
Audit log 如果只存不看,效果有限。
應該建立告警規則。
常見告警:
| 事件 | 告警 |
|---|---|
| 同帳號多次登入失敗 | 可能暴力破解 |
| 多帳號同 IP 失敗 | 可能 credential stuffing |
| MFA 連續失敗 | 可能攻擊或使用者被釣魚 |
| 新裝置登入 | 通知使用者 |
| 密碼修改 | 通知使用者 |
| MFA 停用 | 高風險通知 |
| 新增管理員 | 安全團隊告警 |
| 權限提升 | 安全團隊告警 |
| 大量資料匯出 | 即時告警 |
| Break-glass 使用 | Critical 告警 |
| Audit writer 停止 | Critical 告警 |
告警要有等級:
info
low
medium
high
critical不要所有事件都打爆 Slack。
否則團隊會麻木。
十四、 User Notification
有些 audit event 應通知使用者。
例如:
- 新裝置登入。
- 密碼變更。
- Email / 手機變更。
- MFA 停用。
- 新增 Passkey。
- 第三方登入綁定。
- 大額交易。
- 資料匯出。
通知內容:
- 發生時間。
- 操作類型。
- 大略裝置或地點。
- 如果不是本人該怎麼處理。
不要放:
- 完整 token。
- 完整信用卡號。
- 完整病歷。
- 過多敏感資料。
通知本身也可能造成資訊外洩,要小心設計。
十五、 Audit Log API
後台查 audit log 也要控權。
API 範例:
GET /admin/audit-logs?actorId=&targetId=&eventType=&from=&to=
GET /admin/audit-logs/:id
POST /admin/audit-logs/export查詢 audit log 應該:
- 只有特定角色可查。
- 查詢也要被記錄。
- 匯出要重新驗證。
- 匯出檔短效。
- 敏感欄位遮蔽。
- 大量查詢告警。
不要讓一般客服可以自由查所有安全 log。
尤其是金融/醫療場景。
十六、 實作範例
可以建立一個統一 writer:
type AuditInput = {
eventType: string
action: string
result: 'success' | 'failure' | 'denied'
actorType: 'user' | 'admin' | 'system'
actorId?: string
targetType?: string
targetId?: string
sessionId?: string
requestId: string
ip?: string
userAgent?: string
riskScore?: number
metadata?: Record<string, unknown>
}
async function recordAuthAudit(input: AuditInput) {
const sanitized = sanitizeAuditMetadata(input.metadata)
await auditLogStore.insert({
...input,
metadata: sanitized,
occurredAt: new Date(),
recordedAt: new Date()
})
}在登入失敗時:
await recordAuthAudit({
eventType: 'auth.login.failure',
action: 'login',
result: 'failure',
actorType: 'anonymous',
targetType: 'user',
targetId: user?.id,
requestId: req.id,
ip: req.ip,
userAgent: req.headers['user-agent'],
riskScore,
metadata: {
reason: 'invalid_password'
}
})在管理員變更角色時:
await recordAuthAudit({
eventType: 'auth.role.granted',
action: 'grant_role',
result: 'success',
actorType: 'admin',
actorId: admin.id,
targetType: 'admin_user',
targetId: targetAdmin.id,
sessionId: admin.sessionId,
requestId: req.id,
ip: req.ip,
metadata: {
role: 'finance_admin',
reason: req.body.reason
}
})十七、 常見錯誤
1. 只記登入成功
錯誤:
login success 才寫 log。正確:
登入成功、失敗、rate limit、MFA 失敗、權限拒絕都要記。2. Log 裡有敏感資料
錯誤:
metadata 裡放 password、otp、token。正確:
敏感秘密絕不進 log,必要時只存 hash 或 masked value。3. 沒有 actor / target
錯誤:
只記 user_id。正確:
分清楚誰做的、影響誰、作用在哪個 resource。4. 沒有 request id
錯誤:
各服務 log 串不起來。正確:
每筆 audit event 有 request_id / correlation_id。5. Audit log 可以被同權限刪除
錯誤:
管理員可以刪掉自己的操作紀錄。正確:
Audit log 應 append-only 或至少限制修改刪除,並記錄查詢與匯出。6. 只存不告警
錯誤:
log 都在,需要時再查。正確:
高風險事件要即時告警,否則事故發生時已經太晚。十八、 面試追問題庫
Q1:Auth Audit Log 要記哪些事件?
註冊、登入成功/失敗、登出、MFA、忘記密碼、密碼變更、Session 建立/撤銷、第三方登入綁定、權限變更、管理員操作、重新驗證、敏感資料存取與資料匯出。
Q2:Audit log 欄位怎麼設計?
至少包含 event type、action、result、actor、target、session id、request id、IP、user agent、auth method、MFA method、assurance level、risk score、reason、metadata、occurred_at。
Q3:Log 裡不能放什麼?
不能放明文密碼、OTP、TOTP secret、recovery code、reset token、access token、refresh token、session id 原文、私鑰、完整信用卡號、完整病歷或過多敏感個資。
Q4:登入錯誤訊息不能透露帳號存在,那 audit log 可以記嗎?
可以。對外回應應避免帳號枚舉,但內部 audit log 可以記更精細的原因,例如帳號存在但密碼錯誤。不過 log 存取必須嚴格控管。
Q5:Audit log 如何防竄改?
可以使用 append-only 儲存、限制修改刪除、獨立權限、歸檔、object lock、hash chain 或簽章。至少要避免一般管理員能刪除自己的紀錄。
Q6:Audit log 和 alerting 的關係?
Audit log 是事件來源,alerting 是即時偵測。高風險事件如 MFA 停用、新增管理員、大量資料匯出、break-glass 使用、audit writer 停止,都應觸發告警。
Q7:為什麼要分 actor 和 target?
因為很多操作不是本人對自己做的,例如管理員停用使用者、系統撤銷 session、客服 impersonate 使用者。actor 和 target 分開才能事後追責。
十九、 實作題
題目一:設計登入 audit log
好的答案:
- 登入成功和失敗都記。
- 記 actor / target。
- 記 IP、user agent、device。
- 記 session id hash。
- 記 MFA 是否成功。
- 記 risk score。
- 對外錯誤訊息一致,內部 reason 詳細。
- 多次失敗觸發告警。
題目二:設計管理員權限變更 log
好的答案:
- actor_admin_id。
- target_admin_id。
- granted / revoked role。
- reason。
- step-up method。
- request_id。
- IP / user agent。
- result。
- 安全團隊告警。
題目三:設計敏感資料匯出 log
好的答案:
- actor。
- resource scope。
- row count。
- fields exported。
- purpose。
- reauth method。
- file id。
- expires_at。
- result。
- 大量匯出告警。
題目四:設計不可竄改 audit log
好的答案:
- 應用寫入 queue。
- Audit writer 以 append-only 寫入。
- 歸檔到 object storage。
- 啟用 retention / versioning。
- 每批 log 計算 hash。
- 查詢與匯出 log 也記錄。
- 寫入失敗告警。
二十、 資深視角
1. Audit Log 是產品能力,不只是資安需求
它不只給安全團隊看。
客服、法務、合規、SRE、產品營運都可能需要它回答問題。
但不同角色看到的欄位和範圍要不同。
2. Log 的價值在查得到
只存一大堆 JSON 不代表能稽核。
要能查:
- 某使用者最近所有登入。
- 某管理員最近所有高風險操作。
- 某 IP 對多少帳號失敗登入。
- 某筆資料被誰看過。
- 某次事故相關的所有 request。
所以事件命名、索引、欄位設計很重要。
3. Audit Log 自己也是敏感資料
Audit log 會包含使用者行為、IP、裝置、資料存取紀錄。
它本身也是高敏感資料。
因此要有:
- 存取控制。
- 查詢稽核。
- 保留政策。
- 遮蔽。
- 匯出限制。
4. 沒有告警的 Audit Log 只能事後懊悔
事故發生後查 log 很重要。
但更好的系統會在事故擴大前告警。
例如:
新增管理員 + 凌晨登入 + 大量資料匯出這些事件分開看都可能合理,串起來就很可疑。
總結
| 面向 | 設計重點 |
|---|---|
| 事件範圍 | 登入、登出、MFA、密碼、Session、權限、敏感操作 |
| Schema | actor、target、action、result、time、request id、risk |
| 敏感資料 | 不記密碼、OTP、token、完整敏感資料 |
| 成功/失敗 | 兩者都要記,失敗是攻擊訊號 |
| Actor/Target | 分清本人、管理員、系統、被影響資源 |
| Correlation | request id、correlation id、session id 串事件 |
| Storage | 結構化、可查詢、可歸檔、可告警 |
| 防竄改 | append-only、權限隔離、歸檔、hash / retention |
| Retention | 依風險、法規、隱私與成本分層 |
| Alerting | 高風險事件即時告警 |
一句完整的面試回答可以是:
Auth Audit Log 要記錄身份系統中所有安全相關事件,包括註冊、登入成功與失敗、登出、MFA、忘記密碼、密碼變更、Session 撤銷、第三方登入綁定、權限變更、重新驗證、管理員操作與敏感資料存取。每筆 log 應是結構化事件,包含 actor、target、action、result、時間、IP、user agent、session id、request id、驗證方式、assurance level、risk score 與必要 metadata。Log 不能包含密碼、OTP、token 或完整敏感資料,並且要有存取控制、防竄改、保留政策和查詢能力。高風險事件例如 MFA 停用、新增管理員、大量匯出、break-glass 使用,應即時告警。