string, 'refresh_token' => string, 'expires_in' => int, 'expires_at' => string] */ public static function issueTokens(User $user): array { // 기존 리프레시 토큰 삭제 (한 사용자당 하나의 리프레시 토큰만 유지) $user->tokens()->where('name', 'refresh-token')->delete(); // 액세스 토큰 만료 시간 (분 단위, null이면 무제한) $accessExpiration = Config::get('sanctum.access_token_expiration'); $accessExpiration = $accessExpiration ? (int) $accessExpiration : null; $accessExpiresAt = $accessExpiration ? now()->addMinutes($accessExpiration) : null; // 리프레시 토큰 만료 시간 (분 단위, null이면 무제한) $refreshExpiration = Config::get('sanctum.refresh_token_expiration'); $refreshExpiration = $refreshExpiration ? (int) $refreshExpiration : null; $refreshExpiresAt = $refreshExpiration ? now()->addMinutes($refreshExpiration) : null; // 액세스 토큰 생성 $accessToken = $user->createToken( 'access-token', ['*'], $accessExpiresAt ); // 리프레시 토큰 생성 $refreshToken = $user->createToken( 'refresh-token', ['refresh'], $refreshExpiresAt ); return [ 'access_token' => $accessToken->plainTextToken, 'refresh_token' => $refreshToken->plainTextToken, 'token_type' => 'Bearer', 'expires_in' => $accessExpiration ? $accessExpiration * 60 : null, // 초 단위 'expires_at' => $accessExpiresAt ? $accessExpiresAt->toDateTimeString() : null, ]; } /** * 리프레시 토큰으로 새로운 액세스 토큰을 발급합니다. * 리프레시 토큰도 함께 갱신됩니다. * * @param string $refreshToken 리프레시 토큰 * @return array|null ['access_token' => string, 'refresh_token' => string, ...] or null if invalid */ public static function refreshTokens(string $refreshToken): ?array { // 리프레시 토큰 검증 $token = \Laravel\Sanctum\PersonalAccessToken::findToken($refreshToken); if (! $token) { return null; } // 토큰 타입 확인 if ($token->name !== 'refresh-token') { return null; } // 만료 확인 if ($token->expires_at && $token->expires_at->isPast()) { $token->delete(); return null; } // 사용자 조회 $user = $token->tokenable; if (! $user) { return null; } // 기존 리프레시 토큰 삭제 (사용 후 폐기) $token->delete(); // 새로운 액세스 + 리프레시 토큰 발급 return self::issueTokens($user); } /** * 사용자의 모든 토큰을 삭제합니다 (로그아웃). * * @param User $user 사용자 모델 * @return void */ public static function revokeAllTokens(User $user): void { $user->tokens()->delete(); } /** * 특정 액세스 토큰만 삭제합니다. * * @param User $user 사용자 모델 * @param string $tokenId 토큰 ID * @return void */ public static function revokeToken(User $user, string $tokenId): void { $user->tokens()->where('id', $tokenId)->delete(); } }