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.