パスワード管理
このドキュメントの目的
ユーザー自身によるパスワード変更・パスワードリセット機能を実装することが目標です。
具体的には、/me/password/change と /me/password/reset APIを使用して、ログイン済みユーザーが自分のパスワードを管理できるフローを構築します。
学べること
✅ パスワード変更
- 現在のパスワードを検証して新しいパスワードに変更
- パスワードポリシーによる検証
- セキュリティイベントとの連携
✅ パスワードリセット
- パスワードを忘れた場合のリセットフロー
password:resetスコープによる認可- 代替認証方式(メール検証等)との組み合わせ
所要時間
⏱️ 約10分
このドキュメントの位置づけ
Phase 1: 最小構成で動作確認(Step 5/5)
前提ドキュメント:
- ユーザー登録 - ユーザー登録済み
次のドキュメント:
前提条件
- how-to-05でユーザー登録完了
- アクセストークン取得済み
- OAuth 2.0 / OIDC の基本的なフロー理解
パスワード管理の2つの方法
idp-serverでは、2つのパスワード管理APIを提供しています:
方法1: パスワード変更(Password Change)
現在のパスワードを知っている場合
ユーザーが定期的にパスワードを変更したい場合や、セキュリティ強化のためにパスワードを更新する場合に使用します。
ユースケース:
- ✅ 定期的なパスワード更新
- ✅ セキュリティ強化のための変更
- ✅ パスワード漏洩の疑いがある場合の予防的変更
必要な情報:
- 現在のパスワード(
current_password) - 新しいパスワード(
new_password)
方法2: パスワードリセット(Password Reset)
現在のパスワードを忘れた場合
ユーザーがパスワードを忘れてログインできない場合に、代替認証方式(メール検証等)で本人確認後、新しいパスワードを設定します。
ユースケース:
- ✅ パスワード忘れ
- ✅ アカウント復旧
必要な情報:
- 新しいパスワード(
new_password)のみ - ※ 事前に
password:resetスコープで認証済みであること
パスワード変更の実装
フロー概要
[ユーザー] ログイン済み(アクセストークン取得済み)
↓
[ユーザー] パスワード変更リクエスト
↓ POST /me/password/change
↓ current_password + new_password
[idp-server]
↓ 1. 現在のパスワード検証
↓ 2. 新パスワードのポリシー検証
↓ 3. パスワード更新
↓
[レスポンス] 成功 / エラー
API実行
# 接続先サーバーURL
IDP_SERVER_URL=http://localhost:8080
curl -X POST "${IDP_SERVER_URL}/${PUBLIC_TENANT_ID}/v1/me/password/change" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"current_password": "OldPassword123!",
"new_password": "NewSecurePass456!"
}' | jq .
パラメータ
| 項目 | 型 | 必須 | 説明 |
|---|---|---|---|
current_password | string | ✅ | 現在のパスワード |
new_password | string | ✅ | 新しいパスワード(テナントのパスワードポリシーで検証) |
成功レスポンス
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "Password changed successfully."
}
エラーレスポンス
現在のパスワードが間違っている場合
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_current_password",
"error_description": "Current password is incorrect."
}
新しいパスワードがポリシー違反の場合
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_new_password",
"error_description": "password minLength is 8"
}
必須パラメータが不足している場合
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_request",
"error_description": "Current password is required."
}
パスワードリセットの実装
フロー概要
パスワードリセットは、ユーザーがパスワードを忘れた場合に使用します。通常、以下のフローで実行されます:
[ユーザー] パスワードを忘れた
↓
[ユーザー] パスワードリセット開始
↓ Authorization Request (scope=password:reset)
[idp-server]
↓ メール検証等の代替認証
↓ アクセストークン発行(password:reset スコープ付き)
↓
[ユーザー] 新パスワード設定
↓ POST /me/password/reset
↓ new_password のみ
[idp-server]
↓ 1. スコープ検証(password:reset)
↓ 2. 新パスワードのポリシー検証
↓ 3. パスワード更新
↓
[レスポンス] 成功 / エ ラー
Step 1: パスワードリセット用トークン取得
パスワードリセットには、password:reset スコープを含むアクセストークンが必要です。
# Authorization Request(パスワードリセット用)
curl -v "${IDP_SERVER_URL}/${PUBLIC_TENANT_ID}/v1/authorizations?\
response_type=code&\
client_id=${WEB_CLIENT_ID}&\
redirect_uri=http://localhost:3000/callback&\
scope=openid+password:reset&\
state=random-state-123"
重要: このリクエストでは、パスワード認証以外の代替認証方式(メールOTP等)でユーザーを認証する必要があります。
Step 2: パスワードリセットAPI実行
curl -X POST "${IDP_SERVER_URL}/${PUBLIC_TENANT_ID}/v1/me/password/reset" \
-H "Authorization: Bearer ${RESET_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"new_password": "NewSecurePass456!"
}' | jq .
パラメータ
| 項目 | 型 | 必須 | 説明 |
|---|---|---|---|
new_password | string | ✅ | 新しいパスワード(テナントのパスワードポリシーで検証) |
注意: current_password は不要です。password:reset スコープで認証済みであることが 、本人確認の代わりになります。
成功レスポンス
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "Password changed successfully."
}
エラーレスポンス
スコープ不足の場合
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": "insufficient_scope",
"error_description": "The request requires higher privileges than provided by the access token."
}
パスワードポリシーとの連携
パスワード変更・リセット時には、テナントに設定されたパスワードポリシーで検証されます。
パスワードポリシーの設定フィールド
identity_policy_config.password_policy ブロックで、以下のフィールドを設定できます。
| フィールド | 型 | デフォルト値 | 説明 |
|---|---|---|---|
min_length | integer | 8 | 最小文字数 |
max_length | integer | 72 | 最大文字数(BCryptの制約により72が上限) |
require_uppercase | boolean | false | 大文字必須 |
require_lowercase | boolean | false | 小文字必須 |
require_number | boolean | false | 数字必須 |
require_special_char | boolean | false | 特殊文字必須 |
max_history | integer | 0 | パスワード履歴保持数(過去N件の再使用を防止)※未実装(将来対応予定) |
max_attempts | integer | 5 | アカウントロックまでの最大失敗回数 |
lockout_duration_seconds | integer | 900 | ロック期間(秒)。デフォルトは15分 |
パスワードポリシーの設定例
テナント作成・更新時に identity_policy_config.password_policy ブロックで設定します。
{
"identity_policy_config": {
"password_policy": {
"min_length": 12,
"max_length": 72,
"require_uppercase": true,
"require_lowercase": true,
"require_number": true,
"require_special_char": true,
"max_attempts": 5,
"lockout_duration_seconds": 900
}
}
}
設定内容の説明:
- パスワードは12文字以上72文字以下
- 大文字・小文字・数字・特殊文字を全て含む必要がある
- パスワード認証を5回連続で失敗するとアカウントがロックされる
- ロックは900秒(15分)経過後に自動解除される
パスワードポリシーの確認
curl "${IDP_SERVER_URL}/v1/management/organizations/${ORGANIZATION_ID}/tenants/${PUBLIC_TENANT_ID}" \
-H "Authorization: Bearer ${ORG_ADMIN_TOKEN}" | jq '.identity_policy.password_policy'
レスポンス例
{
"min_length": 8,
"max_length": 72
}
ポリシー違反時のエラー
新しいパスワードがポリシーを満たさない場合、具体的なエラーメッセージが返されます:
{
"error": "invalid_new_password",
"error_description": "password minLength is 8"
}
詳細は Concept: Password Policy を参照してください。
よくあるエラー
エラー1: アクセストークンなし/無効
エラー:
HTTP/1.1 401 Unauthorized
原因: Authorization ヘッダーがないか、トークンが無効/期限切れ
解決策:
# トークンを再取得
# Authorization Code フローでアクセストークンを取得
エラー2: 現在のパスワードが間違っている(パスワード変更時)
エラー:
{
"error": "invalid_current_password",
"error_description": "Current password is incorrect."
}
原因: 入力した現在のパスワードが間違っている
解決策: 正しいパスワードを入力するか、パスワードリセットフローを使用
エラー3: パスワードポリシー違反
エラー:
{
"error": "invalid_new_password",
"error_description": "password minLength is 8"
}
原因: 新しいパスワードがテナントのパスワードポリシーを満たしていない
解決策: ポリシーに準拠したパスワードを設定
# ❌ 間違い: 8文字未満
"new_password": "Pass1"
# ✅ 正しい: 8文字以上
"new_password": "SecurePass123!"