Learn how to secure your Laravel Task Manager by associating tasks with users and filtering data so users can only view and manage their own personal tasks.
Previously in this course, we explored Introduction to Authentication: Securing Your Laravel Application to handle logins and session management. Now that your users can sign in, we need to ensure they aren't seeing or editing each other's work.
In this lesson, we will implement user-scoped data. This is the final step in moving from a shared, public list to a private, secure Task Manager.
Right now, our tasks table is agnostic—any task exists for anyone. To fix this, we need to establish a relationship between our User model and our Task model.
First, we need to add a user_id column to our tasks table. If you've been following along with Task Manager: Displaying Real Database Records, you already have a migration file. Create a new migration to add the column:
Bashphp artisan make:migration add_user_id_to_tasks_table --table=tasks
In the new migration file, add the column:
PHPpublic function up() { Schema::table('tasks', function (Blueprint $table) { $table->foreignId('user_id')->constrained()->onDelete('cascade'); }); }
Running php artisan migrate updates our schema. By using constrained(), Laravel automatically assumes a foreign key relationship to the users table. The onDelete('cascade') ensures that if a user deletes their account, their tasks are automatically removed as well.
When creating a new task, we must capture the current user's ID. In your TasksController, you shouldn't rely on hidden form inputs (which can be spoofed). Instead, use the auth() helper.
PHPpublic function store(Request $request) { $validated = $request->validate([ 'title' => 'required|max:255', ]); #6A9955">// Associate the task with the logged-in user $request->user()->tasks()->create($validated); return redirect('/tasks'); }
By calling $request->user()->tasks()->create(...), Laravel automatically assigns the user_id of the authenticated user to the new record.
Now that our database records have owners, we must update our index logic to hide data that doesn't belong to the current user.
In your TasksController@index method, instead of Task::all(), we filter by the authenticated user:
PHPpublic function index() { #6A9955">// Retrieve only tasks belonging to the authenticated user $tasks = auth()->user()->tasks; return view('tasks.index', ['tasks' => $tasks]); }
If a user tries to access a task ID that doesn't belong to them (e.g., via a direct URL), they shouldn't see it. We will cover how to prevent unauthorized access to specific records using policies and route model binding in the next few lessons, but filtering the collection is the essential first step.
user_id column.user_id, update them in the database or truncate the table so you can start fresh with associated tasks.user_id to the $fillable array in your Task model if you are using mass assignment. However, when using the $user->tasks()->create() pattern, Laravel handles the user_id assignment safely for you.constrained() in migrations. It ensures database integrity, preventing "orphaned" tasks that point to non-existent users.We have successfully secured our application by:
user_id column to our tasks table.auth()->user() helper to associate new tasks with the logged-in user.auth()->user()->tasks so that data is private to the user.Your Task Manager is now a truly personal application.
Up next: We'll dive into Route Model Binding to simplify how we retrieve and protect specific task records.
Learn how to use Laravel middleware to secure your routes. We'll cover applying the auth middleware, protecting route groups, and managing redirects.
Read moreLearn how to display database data in your Laravel Task Manager. We'll connect your Eloquent models to your Blade views to render real, dynamic tasks.
Task Manager: Securing the Application
Task Manager: Completing CRUD Functionality
Introduction to Database Relationships
Querying Related Data
Handling File Uploads
Using Flash Messages for User Feedback
Task Manager: Adding Status and Priorities
Introduction to Artisan Commands
Debugging with Laravel Tinker
Understanding Service Providers
Using View Composers
Task Manager: Refactoring for Clean Code
Introduction to Testing
Testing Forms and Validation
Using Database Transactions
Handling Global Exceptions
Preparing for Production
Environment Security Best Practices
Managing Assets in Production
Task Manager: Deployment Preparation