管理者パスワードリセット

概要説明

管理者パスワードリセット機能により、管理者はパスワードを忘れた場合にアカウントへのアクセスを回復することができます。このプロセスには、パスワードリセットリンクのリクエスト、安全なトークンを含むメールの受信、そのトークンを使用した新しいパスワードの設定が含まれます。システムは、期限付きトークンの生成、メール所有権の検証、およびシステム要件を満たす新しい安全なパスワードの作成を要求することにより、セキュリティを確保します。この機能は、特に昇格された権限を持つ管理者アカウント向けに特別に調整されています。

アクティビティ図

---
config:
  theme: base
  layout: dagre
  flowchart:
    curve: linear
    htmlLabels: true
  themeVariables:
    edgeLabelBackground: "transparent"
---
flowchart TD
    %% Main components
    AdminUser[管理者ユーザー]
    Firebase((Firebase認証))
    
    %% Process steps with numbering
    AdminUser --- Step1[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>1</span>
            <p style='margin-top: 8px'>リセット要求</p>
        </div>
    ]
    Step1 --> SubmitRequest[メールとURLを送信]
    
    SubmitRequest --- Step2[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>2</span>
            <p style='margin-top: 8px'>検証</p>
        </div>
    ]
    Step2 --> ValidateRequest[リクエスト検証]
    
    ValidateRequest --- Step3[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>3</span>
            <p style='margin-top: 8px'>データ確認</p>
        </div>
    ]
    Step3 --> DataCheck{有効なデータ?}
    
    DataCheck -->|いいえ| Step4A[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #cc6666 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4A</span>
            <p style='margin-top: 8px'>エラー返却</p>
        </div>
    ]
    Step4A --> ReturnError[エラー返却]
    
    DataCheck -->|はい| Step4B[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4B</span>
            <p style='margin-top: 8px'>処理</p>
        </div>
    ]
    Step4B --> ProcessRequest[リセットリクエスト処理]
    ProcessRequest --> Firebase
    
    Firebase --- Step5[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>5</span>
            <p style='margin-top: 8px'>メール送信</p>
        </div>
    ]
    Step5 --> SendEmail[リセットメール送信]
    
    SendEmail --- Step6[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>6</span>
            <p style='margin-top: 8px'>状態確認</p>
        </div>
    ]
    Step6 --> EmailCheck{メール送信?}
    
    EmailCheck -->|いいえ| Step7A[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #cc6666 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>7A</span>
            <p style='margin-top: 8px'>エラー返却</p>
        </div>
    ]
    Step7A --> ReturnError
    
    EmailCheck -->|はい| Step7B[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>7B</span>
            <p style='margin-top: 8px'>成功返却</p>
        </div>
    ]
    Step7B --> ReturnSuccess[成功返却]
    
    ReturnSuccess --- Step8[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>8</span>
            <p style='margin-top: 8px'>メール受信</p>
        </div>
    ]
    Step8 --> ReceiveEmail[管理者がメールを受信]
    
    ReceiveEmail --- Step9[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>9</span>
            <p style='margin-top: 8px'>リンククリック</p>
        </div>
    ]
    Step9 --> ClickLink[リセットリンクをクリック]
    
    ClickLink --- Step10[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>10</span>
            <p style='margin-top: 8px'>パスワード設定</p>
        </div>
    ]
    Step10 --> SetPassword[新しいパスワードを設定]
    
    SetPassword --- Step11[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>11</span>
            <p style='margin-top: 8px'>ログイン</p>
        </div>
    ]
    Step11 --> AdminLogin[管理者ログイン]
    
    %% Styling
    style AdminUser fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style SubmitRequest fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ValidateRequest fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style DataCheck fill:#f5f0ff,stroke:#9966cc,stroke-width:2px
    style ProcessRequest fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style SendEmail fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style EmailCheck fill:#f5f0ff,stroke:#9966cc,stroke-width:2px
    style ReturnSuccess fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ReceiveEmail fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ClickLink fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style SetPassword fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style AdminLogin fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ReturnError fill:#fcd9d9,stroke:#cc3333,stroke-width:2px
    style Firebase fill:#fcd9d9,stroke:#cc3333,stroke-width:2px
    
    style Step1 fill:transparent,stroke:transparent,stroke-width:1px
    style Step2 fill:transparent,stroke:transparent,stroke-width:1px
    style Step3 fill:transparent,stroke:transparent,stroke-width:1px
    style Step4A fill:transparent,stroke:transparent,stroke-width:1px
    style Step4B fill:transparent,stroke:transparent,stroke-width:1px
    style Step5 fill:transparent,stroke:transparent,stroke-width:1px
    style Step6 fill:transparent,stroke:transparent,stroke-width:1px
    style Step7A fill:transparent,stroke:transparent,stroke-width:1px
    style Step7B fill:transparent,stroke:transparent,stroke-width:1px
    style Step8 fill:transparent,stroke:transparent,stroke-width:1px
    style Step9 fill:transparent,stroke:transparent,stroke-width:1px
    style Step10 fill:transparent,stroke:transparent,stroke-width:1px
    style Step11 fill:transparent,stroke:transparent,stroke-width:1px

API: 管理者パスワードリセットAPI

ケースドキュメント

ケース1: パスワードリセット要求

説明

管理者がメールアドレスを提供してパスワードリセットリンクをリクエストします。

シーケンス図

sequenceDiagram
    participant Admin as 管理者
    participant API as パスワード忘れコントローラー
    participant Service as 認証サービス
    participant Firebase as Firebaseサービス

    Note over Admin,API: ステップ1: リセットリクエスト送信
    Admin->>API: POST /api/v1/admin/auth/forgot (メールとURL付き)
    
    Note over API,Service: ステップ2: 抽出と検証
    API->>API: メールとURLを抽出
    
    Note over API,Service: ステップ3: リセットメール送信
    API->>Service: sendResetPassEmail(email, url)
    Service->>Service: ユーザーの存在とステータスの確認
    Service->>Firebase: sendMailWithActionLink(email, url)
    Firebase-->>Service: メール送信状態
    
    Note over API,Admin: ステップ4: レスポンス返却
    API-->>Admin: 200 OK (成功メッセージ付き)

ステップ

ステップ1: リセットリクエスト送信

  • 説明: 管理者がパスワードリセット用のメールアドレスを送信
  • リクエスト: POST /api/v1/admin/auth/forgot
  • ボディパラメータ:
    • email: 管理者の登録メールアドレス
    • url: パスワードリセットフォーム用のクライアントサイドURL
  • 検証:
    • メールフォーマット検証
    • 必須フィールド検証

ステップ2: 抽出と検証

  • 説明: コントローラーがリクエストデータを抽出して検証
  • アクション:
    • メールフォーマットの検証
    • URLフォーマットとセキュリティの検証
    • 処理用の値の抽出

ステップ3: リセットメール送信

  • 説明: システムがリセットリクエストを処理しメールを送信
  • アクション:
    • ユーザーが存在しアクティブであることを確認
    • リセットメールを送信するFirebaseサービスを呼び出し
    • プロセス中のエラーを処理

ステップ4: レスポンス返却

  • 説明: メール配信状態を管理者に通知
  • レスポンス:
    • 成功: 成功メッセージ付きの200 OK
    • エラー: 適切なエラーコードとメッセージ

関連するデータベーステーブルとフィールド

erDiagram
    users {
        id bigint "主キー"
        name string "ユーザーのフルネーム"
        email string "ユーザーのメールアドレス (ユニーク)"
        uid string "Firebase UID (ユニーク)"
        payment_provider_customer_id string "決済プロバイダーの顧客ID (nullable)"
        status int "アカウントステータス (0: 非アクティブ, 1: アクティブ)"
        is_first_login int "初回ログインフラグ (0: まだ, 1: ログイン済)"
        remember_token string "記憶トークン"
        created_at timestamp "レコード作成タイムスタンプ"
        updated_at timestamp "レコード最終更新タイムスタンプ"
        deleted_at timestamp "ソフト削除タイムスタンプ"
    }
    admin_roles {
        id bigint "主キー"
        name string "ロール名"
        slug string "ロールスラッグ"
        created_at timestamp "レコード作成タイムスタンプ"
        updated_at timestamp "レコード最終更新タイムスタンプ"
    }
    admin_role_user {
        admin_role_id bigint "admin_rolesテーブルへの参照"
        user_id bigint "usersテーブルへの参照"
        created_at timestamp "レコード作成タイムスタンプ"
        updated_at timestamp "レコード最終更新タイムスタンプ"
    }

    users ||--o{ admin_role_user : has
    admin_roles ||--o{ admin_role_user : has

エラー処理

  • ログ

    • メール送信失敗をログに記録
    • ユーザー検証の問題を記録
  • エラー詳細:

    ステータスコード エラーメッセージ 説明
    400 "メールアドレスが見つかりません。" メールが見つからない場合
    400 "メールの送信に失敗しました。" メール送信が失敗した場合
    400 "問題が発生しました。申し訳ございませんが、もう一度お試しください。" 予期しないエラーが発生した場合

ケース2: トークンを使用したパスワードリセット

説明

管理者がメールで受信したトークンを使用してパスワードをリセットします。

シーケンス図

sequenceDiagram
    participant Admin as 管理者
    participant API as リセットパスワードコントローラー
    participant Service as 認証サービス
    participant Firebase

    Admin->>API: POST /api/v1/admin/auth/reset-password
    API->>Service: resetPassword(token, email, password)
    Service->>Firebase: updatePassword(email, password)
    Firebase-->>Service: パスワード更新状態
    Service-->>API: リセット結果
    API-->>Admin: 200 OK (成功メッセージ付き)

ステップ

ステップ1: リセットフォーム送信

  • 説明: 管理者がリセットトークンと新しいパスワードを送信
  • リクエスト: POST /api/v1/admin/auth/reset-password
  • ボディパラメータ:
    • token: メールからのリセットトークン
    • email: 管理者のメールアドレス
    • password: 新しいパスワード
    • password_confirmation: パスワード確認
  • 検証:
    • トークンの存在とフォーマット
    • パスワードの強度と確認
    • トークンとメールの一致

ステップ2: パスワード更新

  • 説明: 新しい管理者パスワードを設定
  • アクション:
    • Firebase認証でパスワードを更新
    • セキュリティ基準に従ったパスワードハッシュの適用

ステップ3: レスポンス返却

  • 説明: パスワードリセット成功を管理者に通知
  • レスポンス:
    • 成功: 成功メッセージ付きの200 OK
    • エラー: 詳細なメッセージ付きの適切なエラーコード

追加事項

  • リセットトークンは設定可能な時間(通常は60分)後に期限切れになります
  • システムは成功したパスワードリセット後にトークンを削除することでトークンの再利用を防止します
  • 管理者アカウントのパスワード要件は通常のユーザーよりも厳しい場合があります
  • リセットURLはクライアントアプリケーションによって提供され、異なるフロントエンド実装を可能にします
  • 通常のユーザーと比較して、管理者のパスワードリセットには追加のセキュリティ対策が実施される場合があります