認証フロー設計
1. 概要
本プラットフォームの認証は GitLab OAuth 2.0 によるシングルサインオン(SSO)を採用する。認証後は JWT(JSON Web Token) によるステートレスなセッション管理を行う。
認証方式の選定理由
- GitLab(gitlab.ethan-tech.jp)を開発基盤として使用するため、GitLab アカウントとの統合が必須
- OAuth 2.0 Authorization Code Flow を採用し、セキュリティを担保
- JWT により API サーバーのスケーラビリティを確保
2. GitLab OAuth 認証フロー
2.1 シーケンス図
┌──────────┐ ┌──────────────┐ ┌───────────────┐ ┌─────────────────────┐
│ ブラウザ │ │ フロントエンド │ │ バックエンド │ │ GitLab OAuth Server │
│ │ │ (SPA) │ │ (API) │ │ gitlab.ethan-tech.jp│
└────┬─────┘ └──────┬───────┘ └───────┬────────┘ └──────────┬──────────┘
│ │ │ │
│ 1. ログインボタン押下 │ │
│─────────────────>│ │ │
│ │ │ │
│ │ 2. GET /auth/gitlab │ │
│ │─────────────────────>│ │
│ │ │ │
│ │ 3. リダイレクトURL返却│ │
│ │<─────────────────────│ │
│ │ │ │
│ 4. GitLab 認証画面へリダイレクト │ │
│<─────────────────│ │ │
│ │ │ │
│ 5. GitLab ログイン・認可同意 │ │
│──────────────────────────────────────────────────────────────────>│
│ │ │ │
│ 6. コールバック (authorization_code) │ │
│<─────────────────────────────────────────────────────────────────│
│ │ │ │
│ 7. コールバックURL転送 │ │
│─────────────────>│ │ │
│ │ │ │
│ │ 8. POST /auth/callback (code) │
│ │─────────────────────>│ │
│ │ │ │
│ │ │ 9. POST /oauth/token │
│ │ │ (code → access_token) │
│ │ │─────────────────────────>│
│ │ │ │
│ │ │ 10. access_token 返却 │
│ │ │<─────────────────────────│
│ │ │ │
│ │ │ 11. GET /api/v4/user │
│ │ │ (GitLabユーザー情報取得) │
│ │ │─────────────────────────>│
│ │ │ │
│ │ │ 12. ユーザー情報返却 │
│ │ │<─────────────────────────│
│ │ │ │
│ │ │ 13. ユーザー作成/更新 │
│ │ │ + JWT 発行 │
│ │ │ │
│ │ 14. JWT トークン返却 │ │
│ │<─────────────────────│ │
│ │ │ │
│ 15. ログイン完了 │ │ │
│<─────────────────│ │ │2.2 OAuth アプリケーション設定
GitLab 側に OAuth Application を登録する。
| 項目 | 値 |
|---|---|
| Name | Issue Outsource Platform |
| Redirect URI | https://<app-domain>/auth/callback |
| Scopes | read_user, read_api, openid, profile, email |
| Confidential | Yes |
2.3 取得する GitLab ユーザー情報
json
{
"id": 1,
"username": "example_user",
"name": "Example User",
"email": "user@example.com",
"avatar_url": "https://gitlab.ethan-tech.jp/uploads/-/system/user/avatar/1/avatar.png",
"web_url": "https://gitlab.ethan-tech.jp/example_user"
}3. JWT トークン設計
3.1 トークン構成
| 項目 | 説明 |
|---|---|
| Access Token | API アクセス用。短寿命。 |
| Refresh Token | Access Token 更新用。長寿命。 |
3.2 Access Token ペイロード
json
{
"sub": "user_uuid",
"gitlab_id": 1,
"username": "example_user",
"role": "engineer",
"iat": 1711600000,
"exp": 1711603600
}| フィールド | 型 | 説明 |
|---|---|---|
sub | string (UUID) | プラットフォーム内部のユーザー ID |
gitlab_id | integer | GitLab ユーザー ID |
username | string | GitLab ユーザー名 |
role | string | ロール(manager, reviewer, engineer) |
iat | integer | 発行日時(Unix timestamp) |
exp | integer | 有効期限(Unix timestamp) |
3.3 トークンライフサイクル
| トークン | 有効期限 | 保存場所 |
|---|---|---|
| Access Token | 1 時間 | メモリ(JavaScript 変数) |
| Refresh Token | 7 日間 | HttpOnly Secure Cookie |
3.4 トークンリフレッシュフロー
┌──────────┐ ┌──────────────┐ ┌───────────────┐
│ ブラウザ │ │ フロントエンド │ │ バックエンド │
└────┬─────┘ └──────┬───────┘ └───────┬────────┘
│ │ │
│ 1. API リクエスト(期限切れ Access Token)│
│─────────────────>│ │
│ │─────────────────────>│
│ │ 2. 401 Unauthorized │
│ │<─────────────────────│
│ │ │
│ │ 3. POST /auth/refresh│
│ │ (Refresh Token Cookie)│
│ │─────────────────────>│
│ │ │
│ │ 4. 新 Access Token │
│ │ + 新 Refresh Token │
│ │<─────────────────────│
│ │ │
│ │ 5. 元の API リクエスト再送│
│ │─────────────────────>│
│ │ │
│ │ 6. 正常レスポンス │
│ │<─────────────────────│
│ │ │
│ 7. 画面更新 │ │
│<─────────────────│ │3.5 Refresh Token のローテーション
- Refresh Token は使用するたびに新しいトークンを発行(ローテーション)
- 使用済み Refresh Token は無効化し、再利用を検知した場合は全トークンを無効化(トークン盗用対策)
4. セッション管理
4.1 セッション設計方針
- ステートレス: JWT ベースでサーバー側にセッションストアを持たない(基本方針)
- トークン無効化: Refresh Token のブラックリストを Redis で管理
4.2 セッション無効化(ログアウト)
- フロントエンドがメモリ上の Access Token を破棄
- バックエンドに
POST /auth/logoutを送信 - バックエンドが Refresh Token を Redis ブラックリストに追加
- Refresh Token Cookie を削除
4.3 強制セッション終了
以下のケースでは管理者が強制的にセッションを無効化する。
- ユーザーのロール変更時
- セキュリティインシデント発生時
- ユーザーアカウントの無効化時
実装: 該当ユーザーの全 Refresh Token を Redis ブラックリストに追加する。
4.4 Cookie 設定
Set-Cookie: refresh_token=<token>;
HttpOnly;
Secure;
SameSite=Strict;
Path=/auth/refresh;
Max-Age=6048005. ロール付与フロー
本プラットフォームは 招待制 を採用し、自由登録は許可しない。
5.1 招待〜ロール付与シーケンス
┌──────────────┐ ┌───────────────┐ ┌─────────────────────┐ ┌─────────────┐
│ PM/マネージャー│ │ バックエンド │ │ GitLab OAuth Server │ │ 招待された │
│ │ │ (API) │ │ │ │ ユーザー │
└──────┬───────┘ └───────┬────────┘ └──────────┬──────────┘ └──────┬──────┘
│ │ │ │
│ 1. ユーザー招待 │ │ │
│ (email, role) │ │ │
│─────────────────────>│ │ │
│ │ │ │
│ │ 2. 招待レコード作成 │ │
│ │ + 招待メール送信 │ │
│ │─────────────────────────────────────────────────>│
│ │ │ │
│ 3. 招待完了 │ │ │
│<─────────────────────│ │ │
│ │ │ │
│ │ │ 4. 招待リンク │
│ │ │ クリック │
│ │<────────────────────────────────────────────────│
│ │ │ │
│ │ 5. GitLab OAuth フロー開始 │
│ │─────────────────────────>│ │
│ │ │ │
│ │ │ 6. GitLab ログイン │
│ │ │<──────────────────────│
│ │ │ │
│ │ 7. OAuth コールバック │ │
│ │<─────────────────────────│ │
│ │ │ │
│ │ 8. ユーザー作成 │ │
│ │ (招待のロールを付与) │ │
│ │ │ │
│ │ 9. 初回ログインフラグ設定 │ │
│ │─────────────────────────────────────────────────>│
│ │ │ │
│ │ │ 10. プロフィール │
│ │ │ 設定画面へ │
│ │ │──────────────────────>│5.2 招待の有効期限と制約
| 項目 | 値 |
|---|---|
| 招待リンク有効期限 | 7 日間 |
| 再招待 | 期限切れ後に PM が再招待可能 |
| 招待キャンセル | PM が招待済み・未登録のユーザーをキャンセル可能 |
| 同一メールアドレス | 重複招待不可(既存ユーザーの場合はエラー) |
6. 初回ログイン時のプロフィール設定フロー
6.1 フロー
┌──────────┐ ┌──────────────┐ ┌───────────────┐
│ ブラウザ │ │ フロントエンド │ │ バックエンド │
└────┬─────┘ └──────┬───────┘ └───────┬────────┘
│ │ │
│ 1. 初回ログイン後 │ │
│ (is_profile_complete = false) │
│─────────────────>│ │
│ │ │
│ 2. プロフィール設定画面表示 │
│<─────────────────│ │
│ │ │
│ 3. プロフィール入力・送信 │
│─────────────────>│ │
│ │ 4. PUT /users/me/profile│
│ │─────────────────────>│
│ │ │
│ │ 5. バリデーション │
│ │ + プロフィール保存 │
│ │ + is_profile_complete = true│
│ │ │
│ │ 6. 更新完了 │
│ │<─────────────────────│
│ │ │
│ 7. メイン画面へ遷移│ │
│<─────────────────│ │6.2 必須プロフィール項目
| 項目 | 必須 | 説明 |
|---|---|---|
| 表示名 | O | プラットフォーム上の表示名(GitLab 名で初期値設定) |
| メールアドレス | O | 連絡用(GitLab のメールで初期値設定) |
| スキルタグ | △ | エンジニアのみ必須。対応可能な技術領域 |
| 銀行口座情報 | △ | エンジニアのみ必須。報酬振込先 |
| 自己紹介 | - | 任意 |
7. セキュリティ考慮事項
7.1 CSRF 対策
- SameSite=Strict Cookie による CSRF 防止
- state パラメータによる OAuth CSRF 防止
7.2 XSS 対策
- Access Token はメモリ保持(localStorage 不使用)
- Refresh Token は HttpOnly Cookie(JavaScript からアクセス不可)
7.3 レート制限
| エンドポイント | 制限 |
|---|---|
POST /auth/gitlab | 10 回/分/IP |
POST /auth/refresh | 30 回/時/ユーザー |
POST /auth/logout | 10 回/分/ユーザー |
7.4 監査ログ
以下のイベントを監査ログに記録する。
- ログイン成功/失敗
- ログアウト
- ロール変更
- 招待の作成/キャンセル
- トークンリフレッシュ
- 強制セッション終了