Skip to content

認証設計

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
    end

JWT トークン設計

ペイロード

json
{
  "sub": "user_id",
  "email": "user@example.com",
  "role": "admin",
  "iat": 1700000000,
  "exp": 1700086400
}

設定

項目
アルゴリズムHS256
有効期限24時間
署名キーOS Keychain の JWT_SECRET
送信方法httpOnly 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
エンドポイントviewermemberadmin
GET /api/bookmarksooo
GET /api/statsooo
GET /api/mindmapooo
GET /api/search/ai-oo
GET /api/export-oo
POST /api/categorize-oo
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=Strict Cookie 属性
  • カスタムヘッダー検証(API リクエスト)

レート制限

エンドポイント制限
POST /api/auth/login5回/分
POST /api/auth/register3回/時
その他 API60回/分