Authorization
Remove a field, a fieldset, or the whole form for users who shouldn't see it.
TextInput::make('salary')
->number()
->authorize(fn () => auth()->user()->can('manage-salaries'));When to use: admin-only fields, role-based sections, or forms that only some users may submit.
Authorization is different from visibility. Visibility depends on what the user types and is checked in the browser. Authorization is decided on the server, and unauthorized items never reach the browser at all.
Examples
Each example is a live form built from the PHP below it. The checks use plain booleans so the result is fixed; in your app they would come from the current user, as the comments show.
Basic
salary fails its check, so it is missing from the preview and from the submitted data. notes passes because authorizedUnless() gets false.
use Erag\InertiaForms\Fields\Textarea;
use Erag\InertiaForms\Fields\TextInput;
[
TextInput::make('name')->required(),
TextInput::make('email')->email()->required(),
// In your app: ->authorizedWhen($user->can('manage-salaries'))
TextInput::make('salary')->number()->prefix('€')->authorizedWhen(false),
// In your app: ->authorizedUnless($user->isGuest())
Textarea::make('notes')->rows(2)->authorizedUnless(false),
];A whole fieldset
One check on the fieldset removes every field inside it. Only the Profile section is rendered.
use Erag\InertiaForms\Fields\Combobox;
use Erag\InertiaForms\Fields\Fieldset;
use Erag\InertiaForms\Fields\TextInput;
use Erag\InertiaForms\Fields\Toggle;
[
Fieldset::make('Profile')->columns(2)->fields([
TextInput::make('name')->required(),
TextInput::make('email')->email()->required(),
]),
// In your app: ->authorize(fn () => auth()->user()->isAdmin())
Fieldset::make('Admin')->authorize(false)->fields([
Toggle::make('is_verified'),
Combobox::make('plan')->options(['free' => 'Free', 'pro' => 'Pro']),
]),
];Advanced: role-based sections
The role is passed to the constructor, and the checks read it. The preview is built for an HR user: Compensation is shown, but bonus_eligible is removed because it also needs the admin role. Every check on an item must pass.
use Erag\InertiaForms\Fields\Combobox;
use Erag\InertiaForms\Fields\Fieldset;
use Erag\InertiaForms\Fields\Submit;
use Erag\InertiaForms\Fields\Textarea;
use Erag\InertiaForms\Fields\TextInput;
use Erag\InertiaForms\Fields\Toggle;
use Erag\InertiaForms\Form;
class EmployeeForm extends Form
{
protected ?string $actionUrl = '/employees';
public function __construct(private string $role = 'viewer', private bool $isOwnRecord = false) {}
public function fields(): array
{
return [
Fieldset::make('Profile')->columns(2)->fields([
TextInput::make('name')->required(),
TextInput::make('job_title'),
]),
Fieldset::make('Compensation')
->description('Only HR and admins get this section.')
->authorize(fn () => in_array($this->role, ['hr', 'admin'], true))
->columns(2)
->fields([
TextInput::make('salary')->number()->prefix('€')->required(),
Combobox::make('pay_band')->options(['A', 'B', 'C']),
Toggle::make('bonus_eligible')
->authorize($this->role === 'admin')
->authorizedUnless($this->isOwnRecord)
->columnSpan(2),
]),
Textarea::make('internal_notes')->rows(2)->authorizedUnless($this->role === 'viewer'),
Submit::make('Save employee'),
];
}
}
// In your app: EmployeeForm::make($request->user()->role, $employee->is($request->user()))
EmployeeForm::make('hr');Methods
All three methods accept a bool or a Closure. They are available on fields, fieldsets, and the form.
| Method | Passes when |
|---|---|
authorize($check) | the check is truthy |
authorizedWhen($check) | the check is truthy (alias of authorize()) |
authorizedUnless($check) | the check is falsy |
TextInput::make('internal_notes')->authorizedWhen($user->isStaff());
Toggle::make('featured')->authorizedUnless(fn () => $user->isGuest());A closure receives the item it belongs to (the field, fieldset, or form) and is evaluated when the form is serialized or validated.
You can call these methods more than once. Every check must pass.
Combobox::make('owner_id')
->authorize(fn () => auth()->check())
->authorize(fn () => auth()->user()->can('reassign', Post::class));Fields and fieldsets
An unauthorized field or fieldset is removed everywhere:
- it is not in the serialized schema,
- it has no initial value in
data(), - it gets no validation rules, so any submitted value is ignored by
validated(), getField('name')returnsnull.
Fieldset::make('Admin')
->authorize(fn () => auth()->user()->isAdmin())
->fields([
Toggle::make('is_verified'),
Combobox::make('plan')->options(Plan::class),
]);The whole form
Call the methods on the form instance, or inside your class (for example in the constructor):
return Inertia::render('Settings/Billing', [
'form' => BillingForm::make()->authorize($request->user()->can('update-billing')),
]);When the whole form is unauthorized:
- Serialization returns an empty form: no fieldsets, no data, and
actionset tonull. The frontend renders nothing but the default submit button, and submitting does nothing because there is no action. - Validation with
validate()or#[Validate]throws anAuthorizationException(HTTP 403).
To throw instead of returning an empty form during serialization, enable throw_on_unauthorized in the config:
// config/inertia-forms.php
'throw_on_unauthorized' => true,Authorizing inside the class
Because the check is evaluated late, you can keep authorization inside fields():
class PostForm extends Form
{
public function fields(): array
{
return [
TextInput::make('title')->required(),
Toggle::make('pinned')->authorize(fn () => auth()->user()?->can('pin', Post::class) ?? false),
Submit::make('Save'),
];
}
}