CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

CakeDC API plugin - Authentication and Authorization

This article covers new changes for CakePHP 4 version of plugin. So it covers versions starting from 8.x (8.0) and later.

 

Permissions system. RBAC

By default, the plugin uses CakeDC Users and CakeDC Auth plugins for authentication. For RBAC it uses the same style as defined in the Auth plugin RBAC system with minor changes required for the API plugin.

First, let's consider the case when we want public api without any authorization.

In this case the most simple way would be is to define in config/api_permissions.php next rule

 

return [

    'CakeDC/Auth.api_permissions' => [

        [

            'role' => '*',

            'service' => '*',

            'action' => '*',

            'method' => '*',

            'bypassAuth' => true,

        ], 

    ],

];

 

Now, consider the case we want to use users plugin authentication.

Since Api is supposed to be used from another domain, we should allow all requests with OPTIONS type.

To do this we should add this rule as first on in config/api_permissions.php

 

    [

        'role' => '*',

        'service' => '*',

        'action' => '*',

        'method' => 'OPTIONS',

        'bypassAuth' => true,

    ], 

 

Here, method define OPTIONS and bypassAuth means that such actions should work for any users, including not authenticated.

Now we should allow Auth service methods

 

    [

        'role' => '*',

        'service' => '*',

        'action' => ['login', 'jwt_login', 'register', 'jwt_refresh',],

        'method' => ['POST'],

        'bypassAuth' => true,

    ], 

 

All other services/actions should be declared in api_permissions file to define what user roles are allowed to access them.

Imagine we want to allow the admin role to access the add/edit/delete posts and make index and view public.

We can do it based on method or based on action names.

 

    [

        'role' => 'admin',

        'service' => 'posts',

        'action' => '*',

        'method' => ['POST', 'PUT', 'DELETE'],

    ],

     [

        'role' => 'admin',

        'service' => 'posts',

        'action' => ['index', 'view'],

        'method' => '*',

        'bypassAuth' => true,

    ], 

 

 Routers and Middlewares

Starting from the 8.x version, API Plugin uses router middlewares. This gives great abilities to configure the plugin. So now it is possible to have separate authentication and authorization configuration for website and for api. Also, It is possible to have more then one api prefix, and as result provide more then single api for website with different configuration.

Let’s take a look on the default configuration for middlewares

 

'Middleware' => [

    'authentication' => [

        'class' => AuthenticationMiddleware::class,

        'request' => ApiInitializer::class,

        'method' => 'getAuthenticationService',

    ],

    'bodyParser' => [

        'class' => BodyParserMiddleware::class,

    ],

    'apiParser' => [

        'class' => ParseApiRequestMiddleware::class,

    ],

    'apiAuthorize' => [

        'class' => AuthorizationMiddleware::class,

        'request' => ApiInitializer::class,

        'params' => [

            'unauthorizedHandler' => 'CakeDC/Api.ApiException',

        ],

    ],

    'apiAuthorizeRequest' => [

        'class' => RequestAuthorizationMiddleware::class,

    ],

    'apiProcessor' => [

        'class' => ProcessApiRequestMiddleware::class,

    ],

],

 

First we see the order of middlewares that proceed api request.

It passes through AuthenticationMiddleware, AuthorizationMiddleware, and RequestAuthorizationMiddleware to perform generic auth tasks.

It passes through BodyParserMiddleware to unpack the json request.

And finally ParseApiRequestMiddleware does initial service analysis and ProcessApiRequestMiddleware performs the request.

Also we can note CakeDC\Api\ApiInitializer class used to define Authentication and Authorization configuration. It can be redefined in the application layer to provide needed Identifiers and  Authenticators.

 

 Jwt authentication - Refreshing tokens

New plugin feature is embedded jwt_login action which allows the user to get access_token and refresh_token included into the login response.

Tokens should be passed in the Authorization header with bearer prefix.

Access token is supposed to be used as default token and refresh token needed to get a new access token when it's expired. So for refreshing provided additional jwt_refresh action which should be used in this case.

 

 Configuration

Configuration should be defined on application level in config/api.php. Need to note that it is important to enable this file to load by the Api plugin. It could be done in config/bootstrap_app.php using global configuration: Configure::write('Api.config', ['api']);

 

    'Api' => [ 

        ...

        

        'Jwt' => [

            'enabled' => true,

            'AccessToken' => [

                'lifetime' => 600,

                'secret' => 'accesssecret',

            ],

            'RefreshToken' => [

                'lifetime' => 2 * WEEK,

                'secret' => 'refreshsecret',

            ],

        ], 

 

Hopefully, this was helpful. Our team is always working on adding new features and plugins. You can check out more available plugins HERE.

Latest articles

CakePHP 4 - First Look

Last december, the CakePHP team announced the immediate availability of 4.0.0. This release begins a new chapter for CakePHP, as 4.0 is now API stable. With this release, Cake 3.x moves into maintenance mode, while 2.x moves into security release mode. The promise of the version is: cleaner, faster and still tasty as usual. I had the opportunity to bake a new application from scratch and I will give my feedback about my process.  

Skeleton Design

The new version refreshes the skeleton design of the application. Now we have 2 new folders on root:
  • Templates

The templates folder has presentational files placed here: elements, error pages, layouts, and view template files. Pay attention for subfolders: 
  • Core templates are lowercase: cell, element, email, layout
  • App templates still uppercase: Error, Pages
  • Resources

The resources folder has subfolders for various types of resource files.  The locales* sub folder stores string files for internationalization.   If you are familiar with i18n, you will see the difference:
  • src/Locale/pt_BR/default.po (3.x)
  • resources/locales/pt_BR/default.po (4.x)
  Another important change was the .ctp files. They are moved for .php. CakePHP template files have a default extension of .php now. We have a new config/app_local.php file, which contains the configuration data that varies between environments and should be managed by configuration management, or your deployment tooling.  

PHP Strict Type Mode

In PHP the declare (strict_types = 1); directive enables strict mode. In strict mode, only a variable of exact type of the “type declaration” will be accepted, or a TypeError will be thrown. The only exception to this rule is that an integer may be given to a function expecting a float. This is a feature from PHP 7 - which we strongly recommended. All codebase from the skeleton and files generated by bake will include the function.  

Entities

The preferred way of getting new entities is using the newEmptyEntity() method: $product = $this->Products->newEmptyEntity();  

Authentication

After 10 years baking, that's a really big change for me. I’m not usually use plugins for authentication, I really like the Auth Component. I think many bakers would agree, as I remember on the first international meetup, the co-host shared the same opinion.   The Auth Component is deprecated, so it's better move on and save the good memories. The new way for implementing Authentication is more verbose. It requires a few steps, I don’t will detail that,  because you can easily check on book:
  • Install Authentication Plugin
  • Load the Plugin
  • Apply the Middleware
  • Load the Component
  My first look is like I said,  too verbose, for me anyway. We need to write a lot of code. Also it is not included on the skeleton of CakePHP applications, you need include by your own. https://book.cakephp.org/authentication/2/en/index.html  

HTTPS Enforcer Middleware

Contrary to the Authentication, I was really surprised how easy it was to force my Application to use HTTPS. If you are familiar with CakePHP, you will use the Security Component for that: class AppController extends Controller {      public function initialize()    {        parent::initialize();        $this->loadComponent('Security', [            'blackHoleCallback' => 'forceSSL',        ]);    }      public function beforeFilter(Event $event)    {        if (!Configure::read('debug')) {            $this->Security->requireSecure();        }    }      public function forceSSL()    {        return $this->redirect(            'https://' .            env('SERVER_NAME') .            Router::url($this->request->getRequestTarget())        );    }   }
  The implementation on version 4 is less verbose and easy, kudos for the new version:    public function middleware(MiddlewareQueue $middlewareQueue)    {        $middlewareQueue            ->add(new HttpsEnforcerMiddleware([                'redirect' => true,                'statusCode' => 302,                'disableOnDebug' => true,            ]));          return $middlewareQueue;    }   What I know is a drop, what I don’t know is an ocean. The new version is here to stay, and this article it's a just one overview of basic usage of the new version. * Version 4.1.0 is released already with more improvements and features.  

Links 

[1] Book https://book.cakephp.org/4/en/contents.html [2] Migration Guide https://book.cakephp.org/4/en/appendices/migration-guides.html  

CakePHP Meetup: Unit Test Fixtures, Queue Plugin, PPM Bridge

Developers are used to living in a virtual world, so adjusting has been easier than expected. Recently, we’ve been holding virtual meetups, and we are so happy with the feedback. Digital training sessions allow bakers from all over the world to come together and enjoy. Our plan is to host one each month, and coordinate time zones so that everyone gets a chance to attend. Our latest one was based around a good time for our Japanese community.  If you missed the meetup, no problem. We always post the recording for playback, and I’ll even give you a quick rundown of the topics covered. Let’s jump in:

CakePHP Fixture Factory Plugin

by Juan Pablo Ramirez CakePHP Fixture Factory Plugin https://github.com/pakacuda/cakephp-fixture-factories  helps to improve the way fixtures are generated, when having a big database writing fixtures can get so complicated. This plugin provides Fixture Factories in replacement of the fixtures found out of the box in CakePHP.
Generating fixtures can be done in a few code lines reducing the effort of writing and maintaining tests. There are some other plugins to manage fixtures: 

CakePHP Queue Plugin

By Mark Scherer @dereuromark CakePHP Queue Plugin https://github.com/dereuromark/cakephp-queue is a simple Queue solution, it can be used for small applications and it’s a good one to get started with Job Queues, having something easy to maintain at the beginning is a good starting point.
Queues are a good option for functionalities like: image processing, email sending, PDF generation; to improve the response-time for heavy-processing tasks. For more robust solutions can be used:
  • CakePHP Queuesadilla  https://github.com/josegonzalez/cakephp-queuesadilla This plugin is a simple wrapper around the Queuesadilla queuing library, providing tighter integration with the CakePHP framework. We have used this plugin in CakeDC in several projects, we also had to build  a Mongo Engine for a specific client.

CakePHP PHP PM Bridge

By Jorge Gonzalez @steinkel CakePHP Bridge https://github.com/CakeDC/cakephp-phppm  to use with PHP-PM project.
PPM is a process manager, supercharger and load balancer for modern PHP applications. PHP PM It's based on ReactPHP, the approach of this is to kill the expensive bootstrap of PHP (declaring symbols, loading/parsing files) and the bootstrap of feature-rich frameworks.
It’s a good option If you want to significantly improve the responsiveness of an application that could have spikes. PM works as PHP FPM, it’s a replacement for it.  Below some benchmark:  50 Concurrent threads in 10 seconds
  • FPM 83 transactions per second, Failed 0,  Concurrency 6.58.
  • PPM 90.30 transactions per second, Failed 0, Concurrency 3.86.
200 Concurrent threads in 10 seconds
  • FPM 116,49 transactions per second, Failed 142,  Concurrency 116.64.
  • PPM 207.35 transactions per second, Failed 0, Concurrency 85.59.
1000 Concurrent threads in 10 seconds
  • FPM 109,88 transactions per second, Failed 1759, Concurrency 187.49.
  • PPM 214.91 transactions per second, Failed 0,  Concurrency 302.39.
PPM is able to handle a lot of concurrency connections coming in spike to the server  in a better way than PHP FPM.
For watching the Meetup visit the following link https://www.youtube.com/watch?v=POI0IwyqULo Stay up to date on all virtual meetups here  https://cakephp.org/pages/meetups      

Working From Home - A Developer's View

Long before COVID-19, I (and my team) started working from home. Even before working at CakeDC, between 2007 and 2010, I worked for a company where you were able to split your time between home and office.    Maybe that's why I actually feel comfortable working remotely and I would never change it for an in office position anymore.     Anyway, I am not going to talk about remote work because these days there are thousands of articles about it (even in  one of our previous posts). I want to focus today on writing about our experience with different communication tools and the pros and cons for each of them.   Back in 2011 when I started working at CakeDC, we had an IRC server in place with a couple of plugins to retain messages for our day-to-day communication. Everyone used different clients like Colloquy on mac or Pidgin on Linux. Additionally, we used Skype for peer/team calls and also for client communication. In my opinion, the linux experience was awful until they improved the client a few years later. This setup was implemented in 2007 when the company was started, and in 2012, we decided to shut it down because it was easier just using Skype for everything, messages and calls.     After several years using - suffering - Skype, with new options in the market, we decided to move away to a more reliable and modern approach. The main reason was the lack of updates for Skype linux client, and the message retention limits. In 2016 we started utilizing the more than popular Slack and its open source alternative, Rocket Chat; always keeping Skype for client communication.    Some months later the team concluded that Rocket Chat was the right choice, mainly because we wanted to have control over the messages and the information transmitted. Since the features we were using were available in both solutions, we installed our own Rocket Chat server. At this point I have to say that we did try the calls solution (Jitsy) inside Rocket Chat, but the experience was not good at all, issues with missing calls, poor call quality, etc, made us keep Skype for calls.   On the other hand CakePHP training was provided using Join.me and even when it worked very well in most situations; our trainer Jorge, always had to use a Windows machine instead of his usual Linux one. And then, Zoom emerged.     The year was 2018, when Zoom became so popular even though it started back in 2011 (yes, Zoom existed before COVID-19 crisis). We started using it and it quickly replaced Skype for our team calls. It allowed multiple people calls, screen share, etc. I must say, however, the Zoom chat is one of the worst things I have ever seen.   Going back to Jorge, as you can imagine he was very happy when he saw Zoom had a good Linux client. Unfortunately, he was quickly disappointed because the client screen crashed randomly, went black, and the computer ran out of memory when he tried to share his screen to more than 10 attendees. Happily he didn't throw his windows machine out of the window yet so he could continue giving the training with that machine.   It's 2020, COVID-19 is around us, and Zoom is probably the most popular telecommuting tool. For both adults and children, it is an essential tool to keep working and studying. However, fame never comes alone and threats, rumors and comments are making us move away (again) from Zoom to Google Meet. Also, it didn't make sense to pay for Zoom if we were already paying for GSuite.    I didn't mention it before, but we have been using GSuite (former Google Apps) since the beginning. Google - late as usual - detected a market niche and decided to pump out its meeting tool. In my opinion, I am a standalone app person. This means that I will always prefer having 20 apps instead of 20 browser tabs. So, I don't like Google Meet a lot because of this, but I must say the call quality is superb.    I am not sure how or when we will move to other tools, but right now we are very happy with our Rocket Chat installation and we are still getting used to Google Meet, but it fits our needs.    As a side note we are still using skype to communicate with clients because it is the app everyone has, and sometimes people simply don't want to install something else or use something they are not used to.     To conclude I must say that each team and person should try all of these different tools before choosing one, because one tool that may fits my needs may not fit yours.     

Links

Rocket Chat - https://rocket.chat/ Google Meet - https://meet.google.com Zoom - https://www.zoom.us Skype - https://www.skype.com Colloquy - https://colloquy.app/ Pidgin - https://pidgin.im/

We Bake with CakePHP