Rest API Development with Lumen(5.4) – Part 4 (OAuth2 Authentication, Seeding Databse)

In the last part of Rest API Development with Lumen, we covered validation, transforming and paginating data with Fractal package. In this part, we are going to cover database seeding and authentication.

You can see the finished version of this series in Github.

Using Fake Data for Testing
Sometimes, it’s good to have fake data for testing an API. Lumen includes a simple method of seeding database with test data using seed classes. All seed classes are stored in the database/seeds directory.

Seeding With Model Factories
Factories are useful to create and insert fake data for each Eloquent Model.
Lumen uses Faker package for generating fake data. Create a factory for the User model.

UserFactory.php

<?php // database/factories/UserFactory.php $factory->define(App\Models\User::class, function (Faker\Generator $faker) {
    return [
        'uid'                   => str_random(32),
        'firstName'             => $faker->firstName,
        'lastName'              => $faker->lastName,
        'email'                 => $faker->email,
        'middleName'            => $faker->lastName,
        'password'              => \Illuminate\Support\Facades\Hash::make('test-password'),
        'address'               => $faker->address,
        'zipCode'               => $faker->postcode,
        'username'              => $faker->userName,
        'city'                  => $faker->city,
        'state'                 => $faker->state,
        'country'               => 'USA',
        'phone'                 => $faker->phoneNumber,
        'mobile'                => $faker->phoneNumber,
        'type'                  => 'USER',
        'isActive'              => rand(0,1)
    ];
});

Generating SeedClass
Run the Artisan make:seeder command to create a SeedClass.

php artisan make:seeder UsersTableSeeder

A seeder class contains only one method name run. Let’s update that method to use newly created User factory.

    // database/seeds/UsersTableSeeder.php

    public function run()
    {
        factory(App\Models\User::class, 5)->create();
    }

Running Seeders
Now, we can run the db:seed Artisan command to seed our database.

php artisan db:seed

After we run the command we should see five new records in our users table.

Authentication
Authentication is the most important piece for REST API. Without authentication, anyone can access your API data. There are several types of authentication available. They are HTTP basic, OAuth and OAuth2. For this project, we are going to use OAuth2. If you are not familiar with OAuth2 please visit this page: https://oauth.net/2/

Even though Laravel has an official OAuth2 package name Passport. But as of now, it’s not supported by Lumen out of the box. Luckily Denis Mysenko created a simple passport wrapper for Lumen name lumen-passport.

Let’s use composer to install the package

# Install lumen-passport
composer require dusterio/lumen-passport

After the package installation, we need to run these two commands below to create OAuth2 specific tables and oauth-private, oauth-public key.

# Create new tables for Passport
php artisan migrate

# Install encryption keys and other necessary stuff for Passport
php artisan passport:install

Then, We need to enable both Laravel Passport provider and Lumen-specific provider.

 //bootstrap/app.php

 $app->routeMiddleware([
     'auth' => App\Http\Middleware\Authenticate::class,
 ]);

$app->register(Laravel\Passport\PassportServiceProvider::class);
$app->register(Dusterio\LumenPassport\PassportServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);

OAuth2 Configuration
Lumen doesn’t come with config directory. Let’s create config directory and create auth.php file.

<?php //config/auth.php return [ 'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    'guards' => [
        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => \App\Models\User::class
        ]
    ]
];

User Model Change
Add HasApiTokens trait in User Model.

class User extends Model implements AuthenticatableContract, AuthorizableContract
{
    use Authenticatable, Authorizable, SoftDeletes, HasApiTokens;

    /* rest of the model */
}

Defining Scopes
Scopes allow your API clients to request a specific set of permissions when requesting authorization to access an account. We can define API’s scopes using the Passport::tokensCan method in the boot method of AuthServiceProvider

      
    // app/Providers/AuthServiceProvider.php

        Passport::tokensCan([
            'admin' => 'Admin user scope',
            'basic' => 'Basic user scope',
        ]);

Protecting Routes
We’ve implemented OAuth2 authentication. But we haven’t used that in our route yet. Passport includes an authentication guard that will validate access tokens on incoming requests. Let’s refactor our users resource and add auth:api middleware.

//routes/web.php

$app->group(['middleware' => 'auth:api'], function () use ($app) {
    $app->post('users', '[email protected]');
    $app->get('users', '[email protected]');
    $app->get('users/{id}', '[email protected]');
    $app->put('users/{id}', '[email protected]');
    $app->delete('users/{id}', '[email protected]');
});

Congratulations! We have successfully implemented OAuth2 authentication in our API. If you want to access http://restapi.app/users you will get 401 error.

{
  "status": 401,
  "message": "Unauthorized"
}

Lets create access token for the api using http://restapi.app/oauth/token resource.

accessTokenCreatin

Now, copy and paste the access_token in Authorization header like this:

authHeader

Adding CORS Support

Cross Origin Resource Sharing (CORS) allows us to define which domain can access our API. We’re going to use this package barryvdh/laravel-cors to add CORS support in our api.

Installing barryvdh/laravel-cors package

Let’s use composer require command to install the package.

composer require barryvdh/laravel-cors

We need to create a configuration file for the package. Add the following code in cors.php file

<?php
// config/cors.php

return [
    'supportsCredentials' => true,
    'allowedOrigins' => ['*'],
    'allowedHeaders' => ['*'],
    'allowedMethods' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    'exposedHeaders' => [],
    'maxAge' => 0,
    'hosts' => [],
];

Update app.php
Load the configuration file manually and register the service provider. Also, add CORS into global middleware to apply all routes.

// load cors configurations
$app->configure('cors');

 $app->middleware([
     \Barryvdh\Cors\HandleCors::class,
 ]);

$app->register(Barryvdh\Cors\LumenServiceProvider::class);

Hurray! we’ve successfully added CORS support into our API. You can see all the changes for adding CORS in Github.

Leave a Reply

Your email address will not be published. Required fields are marked *