Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mobiosolutions/laravel-rest-api-with-passport

A step by step example of how to Create Rest API in Laravel 6 Using Passport?
https://github.com/mobiosolutions/laravel-rest-api-with-passport

laravel laravel-framework laravel-passport passport-authentication

Last synced: 2 days ago
JSON representation

A step by step example of how to Create Rest API in Laravel 6 Using Passport?

Awesome Lists containing this project

README

        

## **Laravel REST API with Passport**

Here, we are going to implement REST API with Passport authentication.
We will build a CRUD for Blog's API using Laravel Passport Authentication.

#### **What is REST API?**
Rest API (Representational State Transfer) api's are web standards-based architecture and uses HTTP Protocol for exchanging data between applications or systems.
In RESTFUL web service HTTP methods like GET, POST, PUT and DELETE can be used to perform CRUD operations.

#### **What is Passport?**
Laravel makes API authentication a breeze using Laravel Passport. APIs typically use tokens to authenticate users and do not maintain session state between requests.
you can use passport for user authentication for api's.

#### **Why should we use Passport?**
Passport provides a full OAuth2 server implementation for your Laravel application in a matter of minutes.
It was built to make it easy to apply authentication over an API for laravel based web applications.
The passport package will register its own database migrations. This command will create the encryption keys needed to generate secure access tokens.

#### **How to implement Passport in REST API?**
In below example, we will create CRUD operation for Blog's API using passport authentication.

**1) Create laravel project.**

composer create-project --prefer-dist laravel/laravel laraRestApi

**2) Install Passport**

Go to your project path in terminal and run below command for passport authentication.

composer require laravel/passport

After the successful installation of a package, we required to get default migration for creating new passport tables in our database. let's run below command:

php artisan migrate

Next, we need to install the Passport using command, and it will create token keys for security. let's run bellow command:

php artisan passport:install

**3) Configure project for passport.**

In user model, use HasApiTokens trait class of passport.

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
use Notifiable,HasApiTokens;

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];

/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];

/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}

Add "Passport::routes()" In AuthServiceProvider.

namespace App\Providers;

use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;


class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];


/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();


Passport::routes();
}
}

Change config/auth.php file.

return [
.....
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
.....
]

**4) Create Blog table and model**

Create migration file and model for the Blog table by below command.

php artisan make:migration create_blogs_table

php artisan make:model Blog

Now open your database/migration/'your blog migration file'. and add your code here

increments('id');
$table->string('name');
$table->text('description');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('blogs');
}
}

Update below code to your Blog model file.

group( function () {

});

**6) Create Controller files**

Create two controller files. One for Register and another for Blog. Use below commands to create files.

php artisan make:controller RegisterController

php artisan make:controller BlogController

Update below code to register Controller.

all(), [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'c_password' => 'required|same:password',
]);


if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}


$input = $request->all();
$input['password'] = bcrypt($input['password']);
$user = User::create($input);
$response['token'] = $user->createToken('laraRestApi')->accessToken;
$response['name'] = $user->name;
$response['success'] = true;
$response['message'] = "User registered successfully.";
return $response;
}
}

Update below code to BlogController

response($status, $blogs, $message);
return $response;
}

/**
* Store a newly created blog in database.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//Get request data
$input = $request->all();

//Validate requested data
$validator = Validator::make($input, [
'name' => 'required',
'description' => 'required'
]);
if ($validator->fails()) {
return $this->sendError('Validation Error.', $validator->errors());
}
$blog = Blog::create($input);
$message = 'Blog created successfully.';
$status = true;

//Call function for response data
$response = $this->response($status, $blog, $message);
return $response;
}

/**
* Update the specified blog in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//Get request data
$input = $request->all();

//Validate requested data
$validator = Validator::make($input, [
'name' => 'required',
'description' => 'required'
]);
if ($validator->fails()) {
$message = $validator->errors();
$blog = [];
$status = 'fail';
$response = $this->response($status, $blog, $message);
return $response;
}

//Update blog
$blog = Blog::find($id)->update(['name' => $input['name'], 'description' => $input['description']]);
$message = 'Blog updated successfully.';
$status = true;

//Call function for response data
$response = $this->response($status, $blog, $message);
return $response;
}

/**
* Display the specified blog.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$blog = Blog::find($id);

//Check if the blog found or not.
if (is_null($blog)) {
$message = 'Blog not found.';
$status = false;
$response = $this->response($status, $blog, $message);
return $response;
}
$message = 'Blog retrieved successfully.';
$status = true;

//Call function for response data
$response = $this->response($status, $blog, $message);
return $response;
}

/**
* Remove the specified blog from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//Delete blog
$blog = Blog::findOrFail($id);
$blog->delete();
$message = 'Blog deleted successfully.';
$status = true;

//Call function for response data
$response = $this->response($status, $blog, $message);
return $response;
}

/**
* Response data
*
* @param $status
* @param $blog
* @param $message
* @return \Illuminate\Http\Response
*/
public function response($status, $blog, $message)
{
//Response data structure
$return['success'] = $status;
$return['data'] = $blog;
$return['message'] = $message;
return $return;
}
}

**7) Add routes**

Now add routes to `routes/api.php` file like below:

Route::middleware('auth:api')->group( function () {
Route::get('blogs', 'API\BlogController@index');
Route::post('storeBlog', 'API\BlogController@store');
Route::put('updateBlog/{id}', 'API\BlogController@update');
Route::get('showBlog/{id}', 'API\BlogController@show');
Route::delete('deleteBlog/{id}', 'API\BlogController@destroy');
});

Now run below command in terminal:

php artisan serve

**8) Run APIs**

Let's run API through postman.

Run authentication API to get passport access token & copy the token and use the same in Header of other CRUD APIs.
Follow all screenshots to understand how to generate a token and use it in APIs to authenticate a user.

Test Register API:

![picture](img/register.png)

![picture](img/headers.png)

Add Blog:

![picture](img/addBLog.png)

List Blogs:

![picture](img/listBlogs.png)

Update Blog:

![picture](img/updateBlog.png)

View perticular blog:

![picture](img/viewBlog.png)

Delete Blog:

![picture](img/deleteBlog.png)

Writing test cases for the register and CRUD APIs.

Commands to create test case file :

php artisan make:test RegisterTest

php artisan make:test BlogTest

Update below code to `tests/Feature/RegisterTest.php` file.

createPersonalAccessClient(
null, 'Test Personal Access Client', 'http://localhost'
);

//add test access token to database.
DB::table('oauth_personal_access_clients')->insert([
'client_id' => $client->id,
'created_at' => new DateTime,
'updated_at' => new DateTime,
]);

//Create test data with faker.
$faker = $this->faker;
$password = $faker->password;
$request = [
'name' => $faker->name,
'email' => $faker->email,
'password' => $password,
'c_password' => $password,
];
$response = $this->post('api/register', $request);
$response->assertStatus(200);
}
}

Update below code to `tests/Feature/BlogTest.php` file.

createPersonalAccessClient(
null, 'Test Personal Access Client', 'http://localhost'
);

//add test access token to database.
DB::table('oauth_personal_access_clients')->insert([
'client_id' => $client->id,
'created_at' => new DateTime,
'updated_at' => new DateTime,
]);

$user = factory(User::class)->create(['email' => '[email protected]']);
$token = $user->createToken('Personal Access Token')->accessToken;

$headers = ['Authorization' => "Bearer $token"];
$response = $this->get('api/blogs', $headers);
$response->assertStatus(200);
}

/**
* Test add blogs.
*
* @return void
*/
public function testStoreBlog()
{
//Need to create test personal access token for authentication
$clientRepository = new ClientRepository();
$client = $clientRepository->createPersonalAccessClient(
null, 'Test Personal Access Client', 'http://localhost'
);

//add test access token to database.
DB::table('oauth_personal_access_clients')->insert([
'client_id' => $client->id,
'created_at' => new DateTime,
'updated_at' => new DateTime,
]);

$faker = $this->faker;
$user = factory(User::class)->create(['email' => '[email protected]']);
$token = $user->createToken('Personal Access Token')->accessToken;

$headers = ['Authorization' => "Bearer $token"];

//Create test data with faker.
$request = [
'name' => $faker->name,
'description' => $faker->paragraph
];
$response = $this->post('api/storeBlog', $request, $headers);
$response->assertStatus(200);
}

/**
* Test Update blogs.
*
* @return void
*/
public function testUpdateBlog()
{
//Need to create test personal access token for authentication
$clientRepository = new ClientRepository();
$client = $clientRepository->createPersonalAccessClient(
null, 'Test Personal Access Client', 'http://localhost'
);

//add test access token to database.
DB::table('oauth_personal_access_clients')->insert([
'client_id' => $client->id,
'created_at' => new DateTime,
'updated_at' => new DateTime,
]);
$faker = $this->faker;
$user = factory(User::class)->create(['email' => '[email protected]']);
$token = $user->createToken('Personal Access Token')->accessToken;

$headers = ['Authorization' => "Bearer $token"];

//Create test data with faker.
$request = [
'name' => $faker->name,
'description' => $faker->paragraph,
'id' => $faker->randomNumber()
];

//Add test data to blogs table.
DB::table('blogs')->insert($request);
$response = $this->put("api/updateBlog/" . $request['id'], $request, $headers);
$response->assertStatus(200);
}

/**
* Test display the specified blog.
*
* @return void
*/
public function testBlogShow()
{
//Need to create test personal access token for authentication
$clientRepository = new ClientRepository();
$client = $clientRepository->createPersonalAccessClient(
null, 'Test Personal Access Client', 'http://localhost'
);

//add test access token to database.
DB::table('oauth_personal_access_clients')->insert([
'client_id' => $client->id,
'created_at' => new DateTime,
'updated_at' => new DateTime,
]);
$user = factory(User::class)->create(['email' => '[email protected]']);
$token = $user->createToken('Personal Access Token')->accessToken;

$headers = ['Authorization' => "Bearer $token"];
$response = $this->get('api/showBlog/1', $headers);
$response->assertStatus(200);
}

/**
* Test remove the specified blog from storage.
*
* @return \Illuminate\Http\Response
*/
public function testDestroyBlog()
{
//Need to create test personal access token for authentication
$clientRepository = new ClientRepository();
$client = $clientRepository->createPersonalAccessClient(
null, 'Test Personal Access Client', 'http://localhost'
);

//add test access token to database.
DB::table('oauth_personal_access_clients')->insert(['client_id' => $client->id,
'created_at' => new DateTime,
'updated_at' => new DateTime,]);
$faker = $this->faker;
$user = factory(User::class)->create(['email' => '[email protected]']);
$token = $user->createToken('Personal Access Token')->accessToken;

$headers = ['Authorization' => "Bearer $token"];

//Create test data with faker.
$request = ['name' => $faker->name,
'description' => $faker->paragraph,
'id' => $faker->randomNumber()
];

//Add test data to blogs table.
DB::table('blogs')->insert($request);
$response = $this->delete("api/deleteBlog/" . $request['id'],$request, $headers);
$response->assertStatus(200);
}
}

Run the test cases to terminal by below command:

php vendor/bin/phpunit /tests/Feature/RegisterTest.php

php vendor/bin/phpunit /tests/Feature/BlogTest.php

That’s it. Happy Coding :)

Hope this blog helps to understand how to use a passport package with laravel to create secure APIs.