Blog

I write on blua.blue, dev.to and others

Rapidly build your own stateless REST-API with neoan3

Coding along should approx. take you 15 min

What we will be working on:

  • Setup
  • Adding a simple model
  • Writing authentication endpoints
  • Final thoughts

Setup

Since we don't want to spend a lot of time on addressing various environments, let's check out the official docker setup for neoan3:

git clone https://github.com/neoan3/docker.git

Our only constraint is the need for docker-compose, so be sure you have that installed (comes with Docker Desktop on Mac & Windows). In order to get started, we will run the following commands:

docker-compose up -d --build

docker-compose exec neoan3 sh

That's it! The hashtag you will see indicates you are executing the service's shell as root.

From here, let's finally get started and create a neoan3 project:

neoan3 new app

To verify everything works as expected, try visiting http://localhost:8090

https://blua.blue//asset/upload/0EC796EFBFBD7611EFBFBDEFBFBDEFBF/13fbdc2f7aff06f208e409.png

Adding a simple user model

The easiest way to get fast results is to use the basic email login.

neoan3 add model https://github.com/neoan3/email-password-auth.git

Later, it makes sense to look at the few lines of relevant code in the folder model/user , but for now we will jump over to migrating the model with our database that shipped with our docker setup. To do so, all you need it to run

neoan3 migrate models up and then choose neoan3_db as the credential key.

To verify the installation of our model has worked as expected, visit http://localhost:8090/migrate and see if you can find "user" in the dropdown.

NOTE: Don't worry about the security-warning you will see on that page. This is just a reminder that you shouldn't deploy this setup without taking the steps lined out in the README of the docker repo we started out with.

Writing authentication endpoints

Let's finally code something, right? Well, almost. Let's get us started with some boilerplate for our endpoints:

neoan3 new component auth -t:api -f:demo

This command will get us to a good starting point and within your project you should find a folder [app]/component/Auth with a file AuthController.php. And that's the file we will work with.

The plan

We want to have the following endpoints at our disposal

  • POST /auth (this is our login-endpoint)
  • POST /auth/register (this is, well, you guessed right)
  • GET /auth (this returns a logged in user or a 401 unauthorized response. We mainly want that for testing.)

FYI: the default api-endpoint behavior is using neoan3 api v1. Our endpoints will therefore be at http://localhost:8090/api.v1/auth

Let's first look at the method postAuth

Since we want both /auth and /auth/register to be handles by this method, our postAuth should look like this:

function postAuth(string $mode = 'Login', array $body=[]): array
{
    if($mode === 'Login'){
        // for endpoint /auth (or /auth/login)
    }
    if($mode === 'Register'){
        // for endpoint /auth/register
    }
    return [];
}

As you can see, the API converts kebab-case to PascalCase, so something like /auth/log-me-in would be interpreted as LogMeIn.

adding model transactions

We are using PHP8 in our docker setup. This makes it possible to load injections via Attribute My IDE does most of this for me, but be sure to have both use Neoan3\Provider\Model\InitModel; and use Neoan3\Model\User\UserModel; after the namespace of your file

// 1. Load our user model
#[InitModel(UserModel::class)]
function postAuth(string $mode = 'Login', array $body=[]): array
{
    // 2. pass the payload (body) to the corresponding model-method
    if($mode === 'Login'){
        // for endpoint /auth (or /auth/login): send the credentials to login
        $user = UserModel::login($body);
    }
    if($mode === 'Register'){
        // for endpoint /auth/register: send the credentials to register
        $user = UserModel::register($body);
    }
    // 3. create a JWT token
    $auth = $this->provider['auth']->assign($user['id'], ['user','self'], $user);
    return ['token' => $auth->getToken()];
}

GET /auth

In order to try this out without a front-end we can use neoan3's on-board helper located at http://localhost:8090/endpoint

But first, let's built our GET-method. The most basic usage would be to restrict access to our GET-endpoint unless authenticated:


// 1. Add the authorization Attribute
#[Authorization('restrict')]
function getAuth(): array
{
    // 2. read the JWT
    $auth = $this->provider['auth']->validate();
    // 3. return its content to the client without exposing the identifier
    return $auth->getPayload();
}

Now we can jump over to http://localhost:8090/endpoint and start with our test-scenario:

  1. Creating a user:

Set the endpoint to "auth/register" with the method POST, adding a JSON-payload like {"email":"test@example.com","password":"secure-me"}

When hitting send you should get an answer with a token

  1. Test authentication

Copy the content of the token and paste it into the input field at the authorization-tab, then switch the method to GET after setting the endpoint to auth.

You should now receive your user back.

https://blua.blue//asset/upload/0EC796EFBFBD7611EFBFBDEFBFBDEFBF/83ac85093251abd59d2213.png

Final thoughts

First of all: did you run in any kind of issues? Let me know. Otherwise, I hope you are able to derive how easy it is to work with persistent data with neoan3 beyond a user model. Lastly, let's talk about CORS. I don't know what your plans for the frontend are. Whenever you get into a scenario where you run your application outside of the docker container (e.g. while developing a VueJS app), you will likely have a development server with a port (e.g. 8080). In order to work with cross-origin requests, please find the file default.php and adjust the allowed_origins accordingly (wildcard works, but be aware of the implications)

Happy coding

image

Stop learning what you think is relevant

Still learning react, laravel & co? You better plan ahead!

image

How to use JWT in the neoan3 PHP framework

Many things have changed since I last addressed implementing JWT & stateless authentication & authorization.

image

Rapidly build your own stateless REST-API with neoan3

One of the most common tasks for a web-developer is interacting with an authenticated backend. While a plethora of possibilities are available, the way neoan3 handles things is not only convenient, but also fast and reliable.

image

Generating Phaser Game assets: Planet spritesheet generator

Ever needed to automate a process and all of a sudden you built a tool?

image

Do you even write?

Using the blua.blue webhook in order to track your writing.

Install PHP 8 on Ubuntu

PHP8 has finally been released and it is FAAAAST! Time to update.

image

6 Technologies to look at in 2021

2020 wasn't the best year humans can look back to. but what does 2021 bring for coders?

image

CSS Grid or CSS framework - are they really exclusive?

Grid-based or framework - there are many articles about this choice. But why is that even a thing?

image

Scaffolding REST APIs with JWT authentication

Ever had the need for your own backend while developing your web-app?

image

What is composer?

Composer has become PHP's package & dependency manager. Why you should use it.

image

MySQL: ERROR1364 fix

The painful realization of why people use containers.

image

Cyber wars: Defending your server

Maintaining your own server can be a thrill. High security standards can protect you from data leakage, injection attacks and DDoS attempts. But what about adaptive brute force?

Git: globally change GitHub-remotes from git@ to https

Does your IDE or composer set remote repositories to ssh rather than https? Or are repositories you are using set up that way? You are not alone. Let's fix it once and for all!

VueJS & neoan3: a love story.

Setting up neoan3 to play nice with Vue isn't hard. Here is how the two frameworks are combined to support fast, dynamic and rapid development.

image

MySQL in PHP - how to deal with databases

How I handle MYSQL database transactions in PHP

Install PHP 7.4 on Ubuntu

Finally PHP 7.4 is out! You have read about the new features, you have followed externals, you have gathered ideas on how new capabilities will save time. Let's get it running.

How to install global npm packages without sudo on Ubuntu

Running npm on a server can be painful. Privileges are there for a reason, and so is sudo. Running npm with sudo is not the solution.

image

Static content pages - still the fastest web-experience

Tutorial: How to utilize blua.blue to generate static content for your website.

image

Cross publishing to dev.to

How to publish your content to dev.to from blua.blue - hopefully

The Uselessness of Pre-Assessment

After almost two decades in the industry, new jobs will still ask you for "assessment tests". A little rant...

image

SEO strategies for blua.blue

How to get your content listed where you want it to.

image

How to Build an Express App in Node That Reads From a Headless CMS

A headless CMS lets you design your own front-end, sometimes your own back-end. Let's set up a small application to get us started. Beginner friendly. Approx. 20 min. to reproduce / follow along

Transformer - falling in love with PHP's magic methods all over again

PHP's magic functions have been around for a long time. But there were always good reasons to avoid them. Transformer is a practical and reliable way to make use of the most common operations we program: CRUD operations.

image

Help us document neoan3

Over 4000 brave developers are exploring the framework on their own.

image

When politics kill innovation

How misunderstood diversity killed the PHP Central Europe Conference for good.

image

blua.blue PHP SDK

Create your own blog.

image

dev.to plugin for headless CMS blua.blue (part 2)

A solution to supplying plugins to blua.blue