認証設計
JWT ベースのセッション認証とロールベースアクセス制御 (RBAC) の設計です。
認証フロー
mermaid
sequenceDiagram
participant User as ユーザー
participant Browser as ブラウザ
participant MW as ミドルウェア
participant Auth as 認証API
participant DB as SQLite
User->>Browser: ログインページ
Browser->>Auth: POST /api/auth/login<br/>{email, password}
Auth->>DB: ユーザー検索
DB-->>Auth: User レコード
Auth->>Auth: bcrypt.compare(password, hash)
alt 認証成功
Auth->>Auth: JWT 生成 (HS256)
Auth-->>Browser: Set-Cookie: token=jwt (httpOnly, secure)
Browser->>MW: 以降のリクエスト (Cookie 自動送信)
MW->>MW: JWT 検証
MW-->>Browser: 200 OK
else 認証失敗
Auth-->>Browser: 401 Unauthorized
endJWT トークン設計
ペイロード
json
{
"sub": "user_id",
"email": "user@example.com",
"role": "admin",
"iat": 1700000000,
"exp": 1700086400
}設定
| 項目 | 値 |
|---|---|
| アルゴリズム | HS256 |
| 有効期限 | 24時間 |
| 署名キー | OS Keychain の JWT_SECRET |
| 送信方法 | httpOnly Cookie |
Cookie 属性
Set-Cookie: token=eyJhbGci...;
HttpOnly;
Secure;
SameSite=Strict;
Path=/;
Max-Age=86400ロールベースアクセス制御
ロール定義
| ロール | 説明 | 権限 |
|---|---|---|
admin | 管理者 | 全操作 + ユーザー管理 + 設定変更 |
member | メンバー | ブックマーク閲覧 + 検索 + エクスポート |
viewer | 閲覧者 | ブックマーク閲覧のみ |
エンドポイント別アクセス権限
mermaid
graph TD
subgraph Public["認証不要"]
Login["POST /api/auth/login"]
Register["POST /api/auth/register\n(招待コード必須)"]
end
subgraph Viewer["viewer 以上"]
GetBookmarks["GET /api/bookmarks"]
GetStats["GET /api/stats"]
GetMindmap["GET /api/mindmap"]
end
subgraph Member["member 以上"]
Search["GET /api/search/ai"]
Export["GET /api/export"]
Categorize["POST /api/categorize"]
end
subgraph Admin["admin のみ"]
Settings["*/api/settings/*"]
Users["*/api/users/*"]
Import["POST /api/import/*"]
end| エンドポイント | viewer | member | admin |
|---|---|---|---|
GET /api/bookmarks | o | o | o |
GET /api/stats | o | o | o |
GET /api/mindmap | o | o | o |
GET /api/search/ai | - | o | o |
GET /api/export | - | o | o |
POST /api/categorize | - | o | o |
POST /api/import/* | - | - | o |
*/api/settings/* | - | - | o |
*/api/users/* | - | - | o |
招待コード方式
新規ユーザーの登録は招待コード方式です。
mermaid
sequenceDiagram
participant Admin as 管理者
participant API as API
participant NewUser as 新規ユーザー
Admin->>API: POST /api/users/invite<br/>{role: "member"}
API-->>Admin: {inviteCode: "abc123"}
Admin->>NewUser: 招待コードを共有
NewUser->>API: POST /api/auth/register<br/>{name, email, password, inviteCode: "abc123"}
API->>API: 招待コード検証
API->>API: パスワードハッシュ化 (bcrypt, rounds=12)
API-->>NewUser: 201 Created + JWT Cookieミドルウェア実装
mermaid
flowchart TD
Request["リクエスト"] --> CheckPath{パスが\n公開エンドポイント?}
CheckPath -->|Yes| Handler["APIハンドラー"]
CheckPath -->|No| CheckToken{Cookie に\ntoken あり?}
CheckToken -->|No| Reject401["401 Unauthorized"]
CheckToken -->|Yes| Verify{JWT 検証}
Verify -->|無効/期限切れ| Reject401
Verify -->|有効| CheckRole{ロール\n権限チェック}
CheckRole -->|権限あり| Handler
CheckRole -->|権限なし| Reject403["403 Forbidden"]セキュリティ対策
パスワード
- ハッシュ: bcrypt (cost factor: 12)
- 比較: 定数時間比較 (
crypto.timingSafeEqual) - ポリシー: 最低8文字(将来的に強化予定)
CSRF 対策
SameSite=StrictCookie 属性- カスタムヘッダー検証(API リクエスト)
レート制限
| エンドポイント | 制限 |
|---|---|
POST /api/auth/login | 5回/分 |
POST /api/auth/register | 3回/時 |
| その他 API | 60回/分 |