Skip to content

Building a Basic API Tutorial Part 3 Security

Craig Smith edited this page Dec 19, 2019 · 4 revisions

Securing your api need not be a nightmare:

  1. Lets lock this down to your authenticated users only: edit the api.php routes file and alter
Route::group(['namespace' => 'Api',]

to

Route::group([
'namespace' => 'Api',
'middleware' => ['auth:api'],
]

Now try hit your list endpoint again -- you should see:

{
    "message": "Unauthenticated."
}

if you get a bad error stating login endpoint not found, make sure to add Accept: application/json to your request headers.

No in order to authenticate we should pass our bearer token (from the login in the first part) in the header Authorization: Bearer TOKEN.... And once again -- happy times your response works as expected.

Now we can further secure using Policies

A basic example:

  1. run php artisan make:policy UserPolicy --model=User

Hitting your list endpoint once again returns unauthorized .... Why?

Edit App\Policies\UserPolicy.php and you will find empty methods for viewAny, view, create, update, delete, restore & forceDelete

These methods need to return true to allow the request through.

see https://laravel.com/docs/6.x/authorization#writing-policies for a more indepth overview:

Validation

Your requests can be validated by using Laravel Requests - https://laravel.com/docs/6.x/validation#form-request-validation

run php artisan make:request StoreUserRequest Update your store endpoint in the Api/UserController to read public function store(StoreUserRequest $request) (remember to add use App\Http\Requests\StoreUserRequest; at the top of the file aswell.`

Now try store the user: you will end up with yet again an unauthorized response: if you look at the StoreUserRequest file you will find 2 methods: authorize and rules for rules around the authorize method see https://laravel.com/docs/6.x/validation#authorizing-form-requests for the purposes of our example - we will for now simply return true.

next set the rules to return:

return [
            'name' => 'required|max:55|min:5',
            'email' => 'required|email|unique:users',
            'password' => [
                'min:8', 
                'regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\X])(?=.*[!$#%]).*$/', 
            ]
        ];

Trying to save a new user now will return

{
    "message": "The given data was invalid.",
    "errors": {
        "email": [
            "The email must be a valid email address."
        ],
        "password": [
            "The password must be at least 8 characters.",
            "The password format is invalid."
        ]
    }
}

lets fix up the password messages: add a new method to the StoreUserRequest class as follows:

    public function messages()
    {
        return [
            'password.regex' => 'Please enter a password of at least 8 characters with one upper, one lower, 1 number and 1 special char.'
        ];
    }

And you will be honoured with a better validation error message.

Next: Resource Usage / Manipulation