Creating a Lumen API with OAuth for Google Authentication

Lumen is the younger brother of Laravel. It is supposed to be faster and it is especially designed for building APIs. With this project, we aim to create a JSON API which will also provide OAuth support, mainly for using the visitor’s Google account for authentication.

Decisions, assumptions and hints

  • The app might be used on shared hosting as well;
  • The lumen version is 5.8.*;
  • The root of the project is ./app – for commands and paths, we assume we have it as root;
  • The prefix for our app is lao (from “Lumen API OAuth”);
  • nano is a code editor and cat is a read and write utility, both specific to unix like systems;
  • Please note that some commands (e.g. composer) are available inside the container.

Setup the base of the project

As structure, we will separate docker from the lumen source code. Depending on the project you are working on, the needs might vary. We will also add some helper files.

Some helper files are the .gitignore files. Other such file is .editorconfig, which is a great help for keeping the code in order, regardless of the operating system where it is edited or the code editor used:

./src contains the lumen source code.

./docker contains the docker and docker-compose related code. This is intended to be used for development purposes, thus the configuration is specified inside the docker-compose.yml file.

A repo with the code is available at: https://gitlab.com/cristidraghici/lumen-api-with-oauth-support.

Docker and docker-compose

Create a basic ./docker/docker-compose.yml file:

A special mention about the .yml content above: :delegated and :cached help with performance. More information here:
https://docs.docker.com/docker-for-mac/osxfs-caching/

Lumen

Due to the fact that there are special requirements for the application, we will define a ./docker/lumen/Dockerfile for it:

The configuration for nginx will be stored in ./docker/lumen/nginx.conf:

The ./docker/lumen/entrypoint.sh file will be run when the container starts:

Database

We use mariadb as database. For the sake of consistency, the Dockerfile is inside a dedicated folder, ./docker/database/Dockerfile:

Start the project

In order to execute commands inside the container, the containers need to be started. To do that, the following commands are necessary:

  • cd ./docker
  • docker network create lao-network
  • docker-compose up --build -d

lumen setup

Please note that the docker-compose.yml we defined earlier contains the default mysql settings defined by laravel/lumen. We will setup the lumen project inside the dedicated container – this way we will avoid installing composer on the host machine and also have a consistent version for it in all the develoment envs.

Commands to run:

  • docker exec -it lao-lumen bash
  • composer create-project --prefer-dist laravel/lumen .
  • cp .env.example .env
  • update .env with a random value for APP_KEY, which can be generated with:
    ./cli.sh exec date | md5
  • update .env with http://localhost:9000 for APP_URL;
  • update .env with database (the name of the container set in the docker-compose.yml file) for DB_HOST.

cli.sh

We aim to simplify our tasks as much as possible. Thus, command line helpers are always handy. In this project, the ./cli.sh will offer the following options:

  • cli.sh start
  • cli.sh stop
  • cli.sh build
    Will start the project, but also rebuild the containers;
  • cli.sh exec <command>
    This will execute a command on the lumen container. A quite useful value for <command> could be bash

It will also create the docker network automatically, if needed.

Working on the API

With the basic setup done, the following steps will turn the basic lumen project into a reliable JSON api.

We aim to create an API following the guidelines found at:
https://jsonapi.org/

A note on debugging

As any respectable framework / microframework, Lumen has very good error logging using Monolog. You will find detail on errors by checking the folder: ./src/storage/logs/.

Always return a JSON

Edit ./src/app/Exceptios/Handler.php and replace the render() function with:

At the top of the file, use Illuminate\Http\JsonResponse; is needed. Otherwise, you need to replace every occurrence of JsonResponse with \Illuminate\Http\JsonResponse.

Also, the main route should return a JSON. As a general idea, you should return as little information as possible about the package versions you are using in your application or information about your server, to prevent unnecessary exposure. But for now, just edit the main route in ./src/app/routes/web.php to:

More here:
https://stackoverflow.com/questions/37296654/laravel-lumen-ensure-json-response

Add lumen-passport

Now, connect to the container and install lumen-passport:

./cli.sh exec composer require dusterio/lumen-passport

Create a migration for the users table

Create a users migration, using our cli tool (./cli.sh exec php artisan make:migration create_users_table) with the following content:

Create ./src/app/Http/Controllers/UsersController.php

Alter ./src/app/User.php

Create ./src/app/config/auth.php

Alter ./src/bootstrap/app.php

Uncomment the following two lines:

  • $app->withFacades();
  • $app->withEloquent();

And before $app->router->group([... add:

Alter ./src/routes/web.php

Migrations and passport

The following commands will be executed inside the container and will handle running the migrations for the database structure and also install passport:

  • ./cli.sh exec php artisan migrate
  • ./cli.sh exec php artisan passport:install
  • ./cli.sh exec php artisan passport:client --personal

More information here: