-
-
Notifications
You must be signed in to change notification settings - Fork 18
Building a Basic API Tutorial Part 3 Security
- 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:
- 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:
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.
Making use of Collections / Resources we can next manipulate our response: https://laravel.com/docs/6.x/eloquent-resources
Lets setup one for our User Model:
-
php artisan make:resource UserResourceandphp artisan make:resource UserCollectionto generate our resource and collection. At the top of the controller:
/**
* Resource for item.
*
* @var mixed instance of \Illuminate\Http\Resources\Json\JsonResource
*/
protected $resourceSingle = UserResource::class;
/**
* Resource for collection.
*
* @var mixed instance of \Illuminate\Http\Resources\Json\ResourceCollection
*/
protected $resourceCollection = UserCollection::class;Next lets setup these resources to extend our ApiResources: Open the UserResource and change the definition to
use Phpsa\LaravelApiController\Http\Resources\ApiResource;
class UserResource extends ApiResourceand the UserCollection change definition to
use Phpsa\LaravelApiController\Http\Resources\ApiResource;
class UserCollection extends ApiResource-- Optionally -- api headers middleware ? 5. Seed admin User 6. Oauth + Secrets 7. Setup in postman (optionally extra postman package to get initial api points) 8. Install api-controller package.
---- End Part 1
--- start Part 2
-
- setup Users Endpoint to map to users model
-
- add Policy for security
-
- Add Resource for response
-
- Add Request for Validation
-
- Add Scope for extra scope
- by this point should have a basic CRUD group.
- -- Custom Endpoint -- Me - for own profile
--- end Part 2
--- start part 3 (advanced extras)
- -- joins