Securing Your Laravel API: Hiding Sensitive Attributes from JSON Output
When building APIs with Laravel, it's crucial to control what data is exposed to the client. Laravel's Eloquent ORM provides an elegant way to hide sensitive attributes when converting models to arrays or JSON. Let's explore how to implement this feature effectively.
The $hidden Property
The simplest way to hide attributes is by using the $hidden
property in your Eloquent model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
}
In this example, the password
and remember_token
fields will be excluded from the model's array and JSON representations.
Hiding Relationships
You can also hide entire relationships by adding the relationship's method name to the $hidden
array:
protected $hidden = ['password', 'remember_token', 'secretDocuments'];
The $visible Property
Alternatively, you can use the $visible
property to define an "allow list" of attributes that should be included in the model's array and JSON representation:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The attributes that should be visible in arrays.
*
* @var array
*/
protected $visible = ['first_name', 'last_name', 'email'];
}
This approach is particularly useful when you want to expose only a few attributes and hide everything else.
Dynamic Attribute Visibility
Sometimes you might need to change the visibility of attributes dynamically. Laravel provides methods to do this:
// Hide attributes
$user->makeHidden(['attribute', 'another_attribute']);
// Make attributes visible
$user->makeVisible(['attribute', 'another_attribute']);
These methods are useful when you need different attribute visibility in different contexts.
Practical Example
Let's consider a scenario where we have a User
model with some sensitive information:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $hidden = ['password', 'credit_card_number'];
protected $visible = ['id', 'name', 'email'];
public function getPublicProfileAttribute()
{
return $this->only($this->visible);
}
public function getAdminProfileAttribute()
{
return $this->makeVisible(['created_at', 'updated_at'])->toArray();
}
}
In this example, we've defined a basic set of hidden and visible attributes. We've also added two accessor methods that provide different views of the user data based on the context.
When using this model:
$user = User::find(1);
// For public API
return response()->json($user->public_profile);
// For admin panel
return response()->json($user->admin_profile);
This approach allows you to maintain fine-grained control over your data exposure while keeping your controller logic clean.
By leveraging Laravel's attribute hiding features, you can ensure that sensitive data is never accidentally exposed through your API. This not only enhances the security of your application but also helps in creating cleaner, more focused API responses.
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!