管理者パスワードリセット
概要説明
管理者パスワードリセット機能により、管理者はパスワードを忘れた場合にアカウントへのアクセスを回復することができます。このプロセスには、パスワードリセットリンクのリクエスト、安全なトークンを含むメールの受信、そのトークンを使用した新しいパスワードの設定が含まれます。システムは、期限付きトークンの生成、メール所有権の検証、およびシステム要件を満たす新しい安全なパスワードの作成を要求することにより、セキュリティを確保します。この機能は、特に昇格された権限を持つ管理者アカウント向けに特別に調整されています。
アクティビティ図
---
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はクライアントアプリケーションによって提供され、異なるフロントエンド実装を可能にします
- 通常のユーザーと比較して、管理者のパスワードリセットには追加のセキュリティ対策が実施される場合があります