بنقرة واحدة
authentication-authorization
JWT auth, OAuth, OTP verification, session management, RBAC for SE104_VLEAGUE
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
JWT auth, OAuth, OTP verification, session management, RBAC for SE104_VLEAGUE
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Swagger/OpenAPI setup and documentation patterns for SE104_VLEAGUE
Complete guide for the SE104_VLEAGUE React frontend — pages, services, components, auth flow, i18n, and patterns
Complete guide for testing patterns, test structure, CI pipeline, and development workflow for SE104_VLEAGUE
Complete guide for the SE104_VLEAGUE NestJS backend — modules, endpoints, Prisma schema, guards, interceptors, and patterns
All business rules, state machines, scoring, regulations, and domain constraints for SE104_VLEAGUE
Prisma schema, migrations, seeding, and database operations for SE104_VLEAGUE
| name | Authentication & Authorization |
| description | JWT auth, OAuth, OTP verification, session management, RBAC for SE104_VLEAGUE |
| Token | Storage | Lifetime | Purpose |
|---|---|---|---|
| Access Token (JWT) | In-memory (frontend) | 15min | API authorization |
| Refresh Token | localStorage (frontend), sha256-hashed in DB | 7d (30d with "remember me") | Token renewal |
{
"sub": "user-uuid",
"email": "user@email.com",
"role": "ADMIN",
"name": "User Name",
"iat": 1234567890,
"exp": 1234568790
}
| Role | Description |
|---|---|
ADMIN | Full system access, user management |
TEAM_MANAGER | Manage own team roster, players |
REFEREE | Add/remove match events |
SUPERVISOR | Read-only oversight |
PUBLIC | Basic authenticated access |
Roles are stored in two places (for flexibility):
role enum field on User model — used by guardsroleId FK to roles table — future extensibility| Method | Endpoint | Rate Limit | Description |
|---|---|---|---|
| POST | /auth/register | 5/min | Register + send verification OTP |
| POST | /auth/verify-email | 5/10s | Verify email with 6-digit OTP |
| POST | /auth/resend-otp | 3/min | Resend verification OTP (60s cooldown) |
| POST | /auth/forgot-password | 3/min | Request password reset OTP |
| POST | /auth/reset-password | 5/10s | Reset password with OTP |
| POST | /auth/login | 5/min | Login → access + refresh tokens |
| POST | /auth/refresh | SkipThrottle | Refresh access token |
| POST | /auth/logout | SkipThrottle | Revoke refresh token |
| Method | Endpoint | Description |
|---|---|---|
| GET | /auth/me | Current user profile |
| POST | /auth/change-password | Change password (validates current) |
| POST | /auth/logout-all | Revoke all sessions |
| PATCH | /auth/profile | Update name/avatarUrl |
| GET | /auth/sessions | List active sessions |
| DELETE | /auth/sessions/:sessionId | Revoke specific session |
| POST | /auth/set-password | Set password for OAuth-only users |
| Method | Endpoint | Description |
|---|---|---|
| GET | /auth/google | Start Google OAuth flow |
| GET | /auth/google/callback | Google callback → redirect frontend |
| GET | /auth/facebook | Start Facebook OAuth flow |
| GET | /auth/facebook/callback | Facebook callback → redirect frontend |
AUTH_EMAIL_EXISTS checkotp_codes tableMailService.sendEmailVerificationOtp()emailVerified = trueMAIL_SKIP_SEND=true logs OTP to consoleGET /api/auth/google → Google consent screen
→ GET /api/auth/google/callback → generate tokens
→ Redirect: {FRONTEND_URL}/auth/oauth-callback?accessToken=...&refreshToken=...
Same flow as Google, different strategy.
googleId/facebookId)model RefreshToken {
id String @id @default(uuid()) @db.Uuid
tokenHash String @map("token_hash") // sha256 hash
userId String @map("user_id") @db.Uuid
userAgent String? @map("user_agent")
ipAddress String? @map("ip_address")
deviceName String? @map("device_name") // Parsed from UA
lastUsedAt DateTime @default(now()) @map("last_used_at")
revokedAt DateTime? @map("revoked_at")
expiresAt DateTime @map("expires_at")
}
GET /auth/sessions shows all active sessionsDELETE /auth/sessions/:idPOST /auth/logout-allexpiresAt| Guard | Purpose |
|---|---|
JwtAuthGuard (global) | Validates JWT; skips @Public() routes |
RolesGuard (global) | Checks @Roles() metadata vs req.user.role |
GoogleAuthGuard | Passport Google OAuth strategy |
FacebookAuthGuard | Passport Facebook OAuth strategy |
@Public() // Skip JWT auth
@Roles(UserRole.ADMIN) // Require ADMIN role
@Roles(UserRole.ADMIN, UserRole.TEAM_MANAGER) // Multiple roles (OR)
@CurrentUser() // Extract user from request
| Strategy | Config Key |
|---|---|
JwtStrategy | JWT_SECRET |
GoogleStrategy | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_CALLBACK_URL |
FacebookStrategy | FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, FACEBOOK_CALLBACK_URL |
src/auth/AuthContext.tsx)App mount → attempt silent refresh (stored RT)
├── Success → decode JWT → set user, isAuthed=true
└── Fail → isAuthed=false, show login
Login → POST /auth/login → store AT (memory) + RT (localStorage)
→ decode JWT → set user
OAuth → /auth/oauth-callback → applyOAuthTokens(at, rt) → decode JWT
Logout → POST /auth/logout → clear tokens → redirect /login
lib/api.ts)auth:expired custom event → AuthContext clears stateapi:rate-limited custom event<RequireAuth> // Redirects to /login if !isAuthed, preserves location
<RequireRole allow={['ADMIN']}> // Redirects to /403 if wrong role
<ProtectedPage />
</RequireRole>
</RequireAuth>
# Backend
JWT_SECRET=your-jwt-secret
JWT_REFRESH_SECRET=your-refresh-secret
JWT_EXPIRATION=15m
JWT_REFRESH_EXPIRATION=7d
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GOOGLE_CALLBACK_URL=http://localhost:8080/api/auth/google/callback
FACEBOOK_APP_ID=...
FACEBOOK_APP_SECRET=...
FACEBOOK_CALLBACK_URL=http://localhost:8080/api/auth/facebook/callback
FRONTEND_URL=http://localhost:5173
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USER=...
MAIL_PASS=...
MAIL_FROM=noreply@vleague.local
MAIL_SKIP_SEND=true