要約
APIのHIPAA準拠には、転送中および保存中の暗号化、監査ログ、アクセス制御、ビジネスアソシエイト契約など、保護対象保健情報(PHI)に関する厳格なセキュリティ制御の実装が必要です。このガイドでは、PHIを扱うヘルスケアアプリケーション向けのAPIアーキテクチャパターン、認証要件、監査証跡の実装、およびコンプライアンス検証について説明します。
はじめに
ヘルスケアデータの侵害は、1件あたり平均1,093万ドルの費用がかかります。ヘルスケアアプリケーションを構築する開発者にとって、APIセキュリティは選択肢ではなく、HIPAA(医療保険の携行性と説明責任に関する法律)に基づく法的要件です。
現実として、ヘルスケアデータ侵害の79%は、APIやアプリケーションの脆弱性を介した不正アクセスによるものです。適切に設計されたHIPAA準拠のAPIアーキテクチャは、侵害を防止し、監査証跡を可能にし、患者のプライバシーを保護します。
このガイドでは、HIPAA API準拠の完全なプロセスを順を追って説明します。PHIの取り扱い要件、暗号化標準、アクセス制御の実装、監査ログ、およびコンプライアンス文書化について学びます。最終的には、本番環境に対応したHIPAA準拠のAPIアーキテクチャを構築できるようになります。
HIPAAとは何か、そしてAPIにとってなぜ重要なのか?
HIPAAは、機密性の高い患者の健康情報を保護するための国家基準を確立する連邦法です。HIPAAセキュリティ規則は、APIを介して送信される電子保護対象保健情報(ePHI)に特に対処しています。
誰が遵守しなければならないか
| エンティティの種類 | 例 | APIへの影響 |
|---|---|---|
| 対象事業体 | 医療提供者、医療保険機関、保険情報処理機関 | 直接的なHIPAA責任 |
| ビジネスアソシエイト | APIプロバイダー、クラウドサービス、ソフトウェアベンダー | BAAが必要、直接的な責任 |
| 下請け業者 | サブプロセッサ、下流のAPIサービス | BAAが必要 |
APIに関する主要なHIPAA規則
プライバシー規則: PHIの使用と開示を管理する
- 最小必要限度基準
- 患者のアクセス権
- 承認要件
セキュリティ規則: ePHIの技術的保護措置
- アクセス制御
- 監査制御
- 完全性制御
- 送信セキュリティ
侵害通知規則: インシデント対応要件
- 60日間の通知期間
- リスク評価文書
- 軽減策
APIアーキテクチャの概要
HIPAA準拠のAPIアーキテクチャには以下が含まれます:
┌─────────────────────────────────────────────────────────────────┐
│ HIPAA-COMPLIANT API STACK │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ CLIENT │───▶│ API │───▶│ DATABASE │ │
│ │ (App) │ │ Gateway │ │ (Encrypted)│ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ OAuth 2.0 │ │ WAF + │ │ Audit │ │
│ │ + MFA │ │ Rate Limit│ │ Logging │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ All data encrypted: TLS 1.3+ in transit, AES-256 at rest │
│ │
└─────────────────────────────────────────────────────────────────┘
開始: コンプライアンスの基盤
ステップ1: ビジネスアソシエイト契約(BAA)を締結する
PHIを扱う前に:
- PHIにアクセスするすべてのベンダーを特定する
- 各ベンダーとBAAを締結する
- BAA内でサブプロセッサを文書化する
- 毎年見直し、必要に応じて更新する
BAAが必要な重要なベンダー:
- クラウドホスティング(AWS、GCP、Azure)
- データベースプロバイダー
- ロギングサービス
- バックアッププロバイダー
- APIゲートウェイ
- 監視ツール
BAAなしでこれらを使用してはならない:
- 標準のGoogle Analytics
- 無料枠のクラウドサービス
- 個人のメールアカウント
- 非ヘルスケア向けSlackチャンネル
ステップ2: データ分類
APIが処理するすべてのデータを分類します:
| データ型 | 分類 | 保護レベル |
|---|---|---|
| 患者名 + 生年月日 | PHI | 完全なHIPAA制御 |
| 医療記録番号 | PHI | 完全なHIPAA制御 |
| 診断コード(ICD-10) | PHI | 完全なHIPAA制御 |
| 治療記録 | PHI | 完全なHIPAA制御 |
| 予約時間(患者IDなし) | PHIではない | 標準的な制御 |
| 集計され、匿名化されたデータ | PHIではない | 標準的な制御 |
ステップ3: 最小必要限度基準
APIは、必要な最小限のデータのみを公開する必要があります:
// 悪い例: すべての患者データを返す
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
res.json(patient); // すべてを返す
});
// 良い例: フィールドレベルのフィルタリング
app.get('/api/patients/:id', async (req, res) => {
const fields = req.query.fields?.split(',') || ['id', 'name'];
const allowedFields = ['id', 'name', 'dateOfBirth']; // ホワイトリスト
const patient = await db.patients.findById(req.params.id);
const filtered = Object.fromEntries(
Object.entries(patient).filter(([key]) => allowedFields.includes(key))
);
res.json(filtered);
});
技術的保護措置の実装
アクセス制御: 認証
強力な認証を実装します:
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
// 多要素認証が必要
class HIPAAAuthService {
async authenticate(username, password, mfaCode) {
// 1. 認証情報を検証する
const user = await this.getUserByUsername(username);
if (!user) throw new Error('Invalid credentials');
const validPassword = await bcrypt.compare(password, user.passwordHash);
if (!validPassword) throw new Error('Invalid credentials');
// 2. MFA(TOTP)を検証する
const validMFA = this.verifyTOTP(user.mfaSecret, mfaCode);
if (!validMFA) throw new Error('Invalid MFA code');
// 3. 短寿命のJWTを生成する(PHIアクセスの場合、最大15分)
const token = jwt.sign(
{
sub: user.id,
role: user.role,
mfa_verified: true
},
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
// 4. 認証試行をログに記録する
await this.auditLog('AUTH_SUCCESS', { userId: user.id, ip: req.ip });
return { token, expiresIn: 900 };
}
verifyTOTP(secret, token) {
const period = 30;
const digits = 6;
const now = Math.floor(Date.now() / 1000);
const counter = Math.floor(now / period);
const buffer = Buffer.alloc(8);
buffer.writeUInt32BE(0, 0);
buffer.writeUInt32BE(counter, 4);
const hmac = crypto.createHmac('sha1', secret).update(buffer).digest();
const offset = hmac[hmac.length - 1] & 0xf;
const code = (
((hmac[offset] & 0x7f) << 24) |
((hmac[offset + 1] & 0xff) << 16) |
((hmac[offset + 2] & 0xff) << 8) |
(hmac[offset + 3] & 0xff)
) % Math.pow(10, digits);
return code.toString().padStart(digits, '0') === token;
}
}
アクセス制御: 認可
ロールベースのアクセス制御(RBAC)を実装します:
// ロールの定義
const ROLES = {
ADMIN: 'admin',
PROVIDER: 'provider',
NURSE: 'nurse',
BILLING: 'billing',
PATIENT: 'patient'
};
// 権限マトリックス
const PERMISSIONS = {
[ROLES.ADMIN]: ['read:all', 'write:all', 'delete:all'],
[ROLES.PROVIDER]: ['read:patients', 'write:patients', 'read:labs', 'write:orders'],
[ROLES.NURSE]: ['read:patients', 'write:vitals', 'read:labs'],
[ROLES.BILLING]: ['read:billing', 'read:patients:limited'],
[ROLES.PATIENT]: ['read:self', 'write:self']
};
// 認可ミドルウェア
const authorize = (...requiredPermissions) => {
return async (req, res, next) => {
const user = req.user; // JWTミドルウェアから
const userPermissions = PERMISSIONS[user.role] || [];
const hasPermission = requiredPermissions.every(
perm => userPermissions.includes(perm)
);
if (!hasPermission) {
await auditLog('AUTHZ_DENIED', {
userId: user.id,
action: req.method,
path: req.path,
required: requiredPermissions
});
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
};
// 使用法
app.get('/api/patients/:id/records',
authenticate,
authorize('read:patients'),
getPatientRecords
);
転送中の暗号化
すべてのAPI通信でTLS 1.3を強制します:
const https = require('https');
const fs = require('fs');
// サーバー設定
const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
ca: fs.readFileSync('ca-cert.pem'),
minVersion: 'TLSv1.3',
ciphers: [
'TLS_AES_256_GCM_SHA384',
'TLS_CHACHA20_POLY1305_SHA256',
'TLS_AES_128_GCM_SHA256'
].join(':'),
honorCipherOrder: true
};
const server = https.createServer(options, app);
// HTTPSリダイレクトを強制する
app.use((req, res, next) => {
if (!req.secure) {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});
// HSTSヘッダー
app.use((req, res, next) => {
res.setHeader(
'Strict-Transport-Security',
'max-age=31536000; includeSubDomains; preload'
);
next();
});
保存中の暗号化
すべての保存されたPHIを暗号化します:
const crypto = require('crypto');
class EncryptionService {
constructor(key) {
// キー管理にはAWS KMS、GCP KMS、またはAzure Key Vaultを使用する
this.key = crypto.scryptSync(key, 'salt', 32);
this.algorithm = 'aes-256-gcm';
}
encrypt(plaintext) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag().toString('hex');
return {
encryptedData: encrypted,
iv: iv.toString('hex'),
authTag: authTag
};
}
decrypt(encryptedData, iv, authTag) {
const decipher = crypto.createDecipheriv(
this.algorithm,
this.key,
Buffer.from(iv, 'hex')
);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
// 暗号化されたデータベースモデル
class PatientRecord {
constructor(db, encryptionService) {
this.db = db;
this.encryption = encryptionService;
}
async create(data) {
// 保存前にPHIフィールドを暗号化する
const encryptedData = {
...data,
ssn: this.encryption.encrypt(data.ssn),
diagnosis: this.encryption.encrypt(data.diagnosis),
treatmentNotes: this.encryption.encrypt(data.treatmentNotes)
};
await this.db.patients.insert(encryptedData);
await auditLog('PHI_CREATED', { recordType: 'patient' });
}
async findById(id) {
const record = await this.db.patients.findById(id);
// 読み込み時に復号化する
return {
...record,
ssn: this.encryption.decrypt(record.ssn.encryptedData, record.ssn.iv, record.ssn.authTag),
diagnosis: this.encryption.decrypt(record.diagnosis.encryptedData, record.diagnosis.iv, record.diagnosis.authTag),
treatmentNotes: this.encryption.decrypt(record.treatmentNotes.encryptedData, record.treatmentNotes.iv, record.treatmentNotes.authTag)
};
}
}
監査制御の実装
包括的な監査ロギング
PHIへのすべてのアクセスをログに記録します:
const winston = require('winston');
// 不変の監査ロガー
const auditLogger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
// 追記専用ストレージに書き込む
new winston.transports.File({
filename: '/var/log/hipaa-audit/audit.log',
maxsize: 52428800, // 50MB
maxFiles: 365
}),
// SIEMにも送信する
new winston.transports.Http({
host: 'siem.internal',
path: '/api/logs',
ssl: true
})
]
});
// 監査ロギングミドルウェア
const auditLog = async (event, details) => {
const logEntry = {
timestamp: new Date().toISOString(),
event: event,
actor: details.userId,
action: details.action,
resource: details.resource,
outcome: details.outcome || 'SUCCESS',
ipAddress: details.ip,
userAgent: details.userAgent,
details: details.metadata
};
auditLogger.info(logEntry);
// クエリのためにデータベースにも保存する
await db.auditLogs.insert(logEntry);
};
// 自動監査ミドルウェア
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', async () => {
const duration = Date.now() - start;
// すべてのPHIアクセスをログに記録する
if (req.path.includes('/patients') || req.path.includes('/records')) {
await auditLog('API_ACCESS', {
userId: req.user?.id || 'anonymous',
action: req.method,
resource: req.path,
outcome: res.statusCode < 400 ? 'SUCCESS' : 'FAILURE',
ip: req.ip,
userAgent: req.headers['user-agent'],
metadata: {
duration: duration,
statusCode: res.statusCode,
queryParams: Object.keys(req.query)
}
});
}
});
next();
});
必要な監査イベント
| イベントタイプ | ログに記録する内容 | 保持期間 |
|---|---|---|
| 認証 | 成功/失敗、MFAステータス、IP | 6年間 |
| 認可 | 拒否されたアクセス試行 | 6年間 |
| PHIアクセス | 誰が、いつ、何にアクセスしたか | 6年間 |
| PHI変更 | 変更前/変更後の値 | 6年間 |
| PHI削除 | 何が、誰によって削除されたか | 6年間 |
| システム変更 | 設定変更、新規ユーザー | 6年間 |
| セキュリティイベント | 失敗したリクエスト、レート制限 | 6年間 |
監査レポートの生成
コンプライアンスレポートを生成します:
const generateAuditReport = async (startDate, endDate, options = {}) => {
const query = {
timestamp: {
$gte: new Date(startDate),
$lte: new Date(endDate)
}
};
if (options.userId) {
query.actor = options.userId;
}
if (options.eventType) {
query.event = options.eventType;
}
const logs = await db.auditLogs.find(query).sort({ timestamp: 1 });
return {
reportPeriod: { start: startDate, end: endDate },
generatedAt: new Date().toISOString(),
summary: {
totalEvents: logs.length,
uniqueUsers: new Set(logs.map(l => l.actor)).size,
failures: logs.filter(l => l.outcome === 'FAILURE').length,
phiAccess: logs.filter(l => l.event === 'PHI_ACCESS').length
},
events: logs
};
};
// 定期的な週次レポート
cron.schedule('0 0 * * 1', async () => {
const end = new Date();
const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000);
const report = await generateAuditReport(start, end);
await sendToComplianceTeam(report);
});
APIセキュリティのベストプラクティス
入力検証
インジェクション攻撃を防止します:
const { body, param, query, validationResult } = require('express-validator');
// すべての入力に対する厳格な検証
const validatePatientRequest = [
body('firstName')
.trim()
.notEmpty()
.matches(/^[a-zA-Z\s'-]+$/)
.withMessage('Invalid first name format')
.isLength({ max: 50 }),
body('dateOfBirth')
.isISO8601()
.withMessage('Invalid date format')
.custom(value => new Date(value) < new Date())
.withMessage('Date of birth must be in the past'),
body('ssn')
.optional()
.matches(/^\d{3}-\d{2}-\d{4}$/)
.withMessage('Invalid SSN format'),
body('email')
.optional()
.isEmail()
.normalizeEmail(),
param('id')
.isUUID()
.withMessage('Invalid patient ID format'),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
error: 'Validation failed',
details: errors.array()
});
}
next();
}
];
レート制限
悪用とブルートフォースを防止します:
const rateLimit = require('express-rate-limit');
// 認証エンドポイントへの厳格な制限
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分
max: 5, // 1ウィンドウあたり5回まで
message: { error: 'Too many authentication attempts' },
standardHeaders: true,
legacyHeaders: false,
handler: async (req, res) => {
await auditLog('RATE_LIMIT_EXCEEDED', {
userId: req.body.username,
ip: req.ip,
endpoint: 'auth'
});
res.status(429).json({ error: 'Too many attempts' });
}
});
// 一般的なAPIの制限
const apiLimiter = rateLimit({
windowMs: 60 * 1000, // 1分
max: 100, // 1分あたり100リクエスト
message: { error: 'Rate limit exceeded' }
});
app.use('/api/auth', authLimiter);
app.use('/api', apiLimiter);
エラー処理
情報漏洩を防止します:
// 一般的なエラー応答
app.use((err, req, res, next) => {
// 内部で完全なエラーをログに記録する
console.error('Error:', {
message: err.message,
stack: err.stack,
path: req.path,
user: req.user?.id
});
// クライアントへの一般的な応答
res.status(err.status || 500).json({
error: 'An error occurred processing your request',
requestId: req.id
});
});
// エラーで公開してはならないもの:
// - スタックトレース
// - データベーススキーマ
// - 内部IP
// - ユーザー数
// - エラーメッセージ内のPHI
一般的なHIPAA API違反とその回避方法
違反: 不適切なアクセス制御
シナリオ: APIが認証されたすべてのユーザーに任意の患者記録へのアクセスを許可している。
修正: 適切な認可チェックを実装する:
// 悪い例: 認可チェックがない
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
res.json(patient);
});
// 良い例: ユーザーが患者との関係を持っていることを確認する
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
// ユーザーが患者自身であるかを確認
if (req.user.id === patient.userId) {
return res.json(patient);
}
// ユーザーが担当プロバイダーであるかを確認
const assignment = await db.providerAssignments.findOne({
providerId: req.user.id,
patientId: patient.id
});
if (assignment) {
return res.json(patient);
}
await auditLog('UNAUTHORIZED_ACCESS_ATTEMPT', {
userId: req.user.id,
patientId: patient.id
});
res.status(403).json({ error: 'Access denied' });
});
違反: 監査ログの欠如
シナリオ: 誰が患者データにアクセスしたかの記録がない。
修正: 上記の監査制御セクションに示すように、すべてのPHIアクセスをログに記録する。
違反: 暗号化されていないデータ転送
シナリオ: APIがHTTP接続を受け入れている。
修正: HSTSを使用してHTTPSを強制する:
app.use((req, res, next) => {
if (!req.secure && process.env.NODE_ENV === 'production') {
return res.status(403).json({
error: 'HTTPS required. Connect via https://' + req.headers.host
});
}
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
next();
});
違反: 過剰なデータ公開
シナリオ: 名前だけが必要なのに、APIが完全な患者記録を返している。
修正: フィールドレベルのフィルタリングを実装する:
app.get('/api/patients/:id', async (req, res) => {
const fields = req.query.fields?.split(',') || ['id', 'name'];
const projection = Object.fromEntries(fields.map(f => [f, 1]));
const patient = await db.patients.findById(req.params.id, projection);
res.json(patient);
});
本番環境展開チェックリスト
実際のPHIを扱う前に:
- [ ] すべてのベンダーとBAAを締結する
- [ ] すべてのユーザーにMFAを実装する
- [ ] すべてのエンドポイントでTLS 1.3を有効にする
- [ ] すべてのPHIを保存時に暗号化する (AES-256)
- [ ] 包括的な監査ログを実装する
- [ ] ログ保持期間を設定する (6年以上)
- [ ] アクセス制御を設定する (RBAC)
- [ ] レート制限を実装する
- [ ] インシデント対応計画を作成する
- [ ] すべてのセキュリティ制御を文書化する
- [ ] セキュリティリスク評価を実施する
- [ ] HIPAA要件についてスタッフを訓練する
- [ ] 定期的なセキュリティ監査をスケジュールする
セキュリティリスク評価テンプレート
## HIPAAセキュリティリスク評価
### システム概要
- システム名: [API名]
- 処理されるPHIの種類: [リスト]
- データフロー: [図]
### 脅威評価
| 脅威 | 可能性 | 影響 | 軽減策 |
|--------|------------|--------|------------|
| 不正アクセス | 中 | 高 | MFA、RBAC |
| データ侵害 | 低 | 致命的 | 暗号化 |
| 内部脅威 | 中 | 高 | 監査ログ |
### 制御テスト
- [ ] 認証バイパステスト
- [ ] 認可バイパステスト
- [ ] SQLインジェクションテスト
- [ ] XSSテスト
- [ ] 暗号化検証
### 承認
セキュリティ責任者: _______________ 日付: _______
CTO: _______________ 日付: _______
実世界のユースケース
遠隔医療プラットフォームAPI
テレヘルススタートアップがHIPAA準拠のビデオ診察を構築:
- 課題: 患者と医療提供者間のビデオ通話の安全な転送
- 解決策: HIPAA準拠のシグナリングAPIを使用したエンドツーエンド暗号化WebRTC
- 結果: SOC 2 Type II認定、50万件以上の診察で侵害なし
主要な実装:
- MFAによるJWT認証
- エフェメラルルームトークン(診察後に期限切れ)
- ログにPHIを保存しない
- ビデオインフラ用のTwilioとのBAA
患者ポータルAPI
病院システムが患者アクセスを近代化:
- 課題: セキュリティが不均一な20以上のレガシーシステム
- 解決策: 一元化された認証と監査を備えた統合APIゲートウェイ
- 結果: 単一の信頼できる情報源、簡素化されたコンプライアンス報告
主要な実装:
- SMART on FHIRを使用したOAuth 2.0
- 一元化された監査ログ
- フィールドレベルのアクセス制御
- 自動化された侵害検出
ヘルスデータ統合プラットフォーム
ヘルステック企業が複数のEHRからデータを集約:
- 課題: EHRベンダー間で異なるセキュリティモデル
- 解決策: 統一されたHIPAA制御を備えた抽象化レイヤー
- 結果: 100以上の病院統合、コンプライアンス違反なし
主要な実装:
- 一貫した暗号化によるデータ正規化
- テナントごとの監査証跡
- 自動化されたBAA追跡
- リアルタイムコンプライアンスダッシュボード
結論
APIのHIPAA準拠には、認証、暗号化、アクセス制御、監査ロギングに関する意図的なアーキテクチャ決定が必要です。主なポイント:
- PHIを扱う前にすべてのベンダーとBAAを締結する
- MFAとロールベースのアクセス制御を実装する
- 転送中(TLS 1.3)および保存中(AES-256)のデータを暗号化する
- すべてのPHIアクセスを6年間保持してログに記録する
- すべてのエンドポイントに最小必要限度基準を適用する
- ApidogはAPIドキュメントとコンプライアンスワークフローを効率化します。
FAQセクション
APIがHIPAAに準拠しているとはどういうことですか?
APIがHIPAAに準拠しているとは、ePHIを保護するためにHIPAAセキュリティ規則で義務付けられている技術的保護措置(暗号化、アクセス制御、監査ログ)、管理的保護措置(ポリシー、トレーニング、BAA)、物理的保護措置を実装している場合を指します。
私のAPIにBAAは必要ですか?
はい、あなたのAPIが対象事業体に代わってPHIを処理、保管、またはアクセスする場合、あなたはビジネスアソシエイトとなり、BAAに署名する必要があります。これはクラウドプロバイダー、APIサービス、およびサブプロセッサにも適用されます。
HIPAAで要求される暗号化とは何ですか?
HIPAAは「転送中」および「保存中」の暗号化を要求しています。API通信にはTLS 1.3、保存データにはAES-256を使用してください。暗号化はセキュリティ規則では技術的に「対応可能」とされていますが、実質的にはコンプライアンスに必須です。
HIPAA監査ログはどのくらいの期間保持する必要がありますか?
HIPAAは、監査ログを生成日または記録が最後に有効であった日のいずれか遅い方から6年間保持することを義務付けています。
HIPAA準拠の認証にJWTを使用できますか?
はい、適切に実装されていればJWTは許容されます。短寿命の有効期限(PHIアクセスの場合最大15分)、安全な保存、およびリフレッシュトークンのローテーションが必要です。本番システムでは常にMFAと組み合わせてください。
最小必要限度基準とは何ですか?
最小必要限度基準は、APIが意図された目的を達成するために必要な最小限のPHIのみを公開することを要求します。フィールドレベルのフィルタリングと目的ベースのアクセス制御を実装してください。
監査ログは暗号化する必要がありますか?
はい、PHIを含む監査ログは保存時に暗号化する必要があります。さらに、改ざんを防ぐために追記専用ストレージにログを保存してください。
侵害通知はどのように処理すればよいですか?
不正なPHIアクセスが発生した場合: 1) 侵害を封じ込める、2) 4要素テストを使用してリスクを評価する、3) 60日以内に影響を受ける個人に通知する、4) HHSに通知する(500人以上の場合は直ちに)、5) すべてを文書化する。
HIPAAワークロードにクラウドサービスを使用できますか?
はい、プロバイダーがBAAに署名すれば使用できます。AWS、GCP、AzureはすべてHIPAA準拠のサービスを提供しています。プロバイダーのHIPAA実装ガイドに従ってサービスを設定してください。
HIPAA違反に対する罰則はどのようなものですか?
民事罰は違反ごとに100ドルから50,000ドルで、違反カテゴリごとの年間最大額は150万ドルです。刑事罰には、最高250,000ドルの罰金と最高10年の懲役が含まれます。
