Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 16 additions & 24 deletions docs/book/v4/core-features/authentication.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,43 @@
# Authentication

Authentication is the process by which an identity is presented to the application. It ensures that the entity
making the request has the proper credentials to access the API.
Authentication is the process by which an identity is presented to the application.
It ensures that the entity making the request has the proper credentials to access the API.

**Dotkernel API** identities are delivered to the application from the client through the `Authorization` request.
If it is present, the application tries to find and assign the identity to the application. If it is not presented,
Dotkernel API assigns a default `guest` identity, represented by an instance of the class
`Mezzio\Authentication\UserInterface`.
If it is present, the application tries to find and assign the identity to the application.
If it is not presented, Dotkernel API assigns a default `guest` identity, represented by an instance of the class `Mezzio\Authentication\UserInterface`.

## Configuration

Authentication in Dotkernel API is built around the `mezzio/mezzio-authentication-oauth2` component and is already
configured out of the box. But if you want to dig more, the configuration is stored in
`config/autoload/local.php` under the `authentication` key.
Authentication in Dotkernel API is built around the `mezzio/mezzio-authentication-oauth2` component and is already configured out of the box.
But if you want to dig more, the configuration is stored in `config/autoload/local.php` under the `authentication` key.

> You can check the
> [mezzio/mezzio-authentication-oauth2](https://docs.mezzio.dev/mezzio-authentication-oauth2/v1/intro/#configuration)
> configuration part for more info.
> You can check the [mezzio/mezzio-authentication-oauth2](https://docs.mezzio.dev/mezzio-authentication-oauth2/v1/intro/#configuration) configuration part for more info.

## How it works

Dotkernels API authentication system can be used for SPAs (single-page applications), mobile applications, and
simple, token-based APIs. It allows each user of your application to generate API tokens for their accounts.
Dotkernels API authentication system can be used for SPAs (single-page applications), mobile applications, and simple, token-based APIs.
It allows each user of your application to generate API tokens for their accounts.

The authentication happens through the middleware in the `Api\App\Middleware\AuthenticationMiddleware`.

## Database

When you install **Dotkernel API** for the first time, you need to run the migrations and seeders. All the tables
required for authentication are automatically created and populated.
When you install **Dotkernel API** for the first time, you need to run the migrations and seeders.
All the tables required for authentication are automatically created and populated.

In Dotkernel API, authenticated users come from either the `admin` or the `user` table. We choose to keep the admin
table separated from the users to prevent users of the application from accessing sensitive data, which only the
administrators of the application should access.
In Dotkernel API, authenticated users come from either the `admin` or the `user` table.
We choose to keep the admin table separated from the users to prevent users of the application from accessing sensitive data, which only the administrators of the application should access.

The `oauth_clients` table is pre-populated with the default `admin` and `frontend` clients with the same password as
their names (**we recommend you change the default passwords**).
The `oauth_clients` table is pre-populated with the default `admin` and `frontend` clients with the same password as their names (**we recommend you change the default passwords**).

As you guessed each client serves to authenticate `admin` or `user`.

Another table that is pre-populated is the `oauth_scopes` table, with the `api` scope.

### Issuing API Tokens

Token generation in Dotkernel API is done using the `password` `grant_type` scenario, which in this case allows
authentication to an API using the user's credentials (generally a username and password).
Token generation in Dotkernel API is done using the `password` `grant_type` scenario, which in this case allows authentication to an API using the user's credentials (generally a username and password).

The client sends a POST request to the `/security/generate-token` with the following parameters:

Expand Down Expand Up @@ -80,8 +73,7 @@ The server responds with a JSON as follows:
}
```

Next time when you make a request to the server to an authenticated endpoint, the client should use
the `Authorization` header request.
Next time when you make a request to the server to an authenticated endpoint, the client should use the `Authorization` header request.

```shell
GET /users/1 HTTP/1.1
Expand Down
26 changes: 10 additions & 16 deletions docs/book/v4/core-features/authorization.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
# Authorization

Authorization is the process by which a system takes a validated identity and checks if that identity has access to a
given resource.
Authorization is the process by which a system takes a validated identity and checks if that identity has access to a given resource.

**Dotkernel API**'s implementation of authorization uses `Mezzio\Authorization\Rbac\LaminasRbac` as a model of
Role-Based Access Control (RBAC).
**Dotkernel API**'s implementation of authorization uses `Mezzio\Authorization\Rbac\LaminasRbac` as a model of Role-Based Access Control (RBAC).

## How it works

In Dotkernel API each authenticatable entity (admin/user) comes with their roles table where you can define
roles for each entity. RBAC comes in to ensure that each entity has the appropriate role and permission to access a
resource.
In Dotkernel API each authenticatable entity (admin/user) comes with their roles table where you can define roles for each entity.
RBAC comes in to ensure that each entity has the appropriate role and permission to access a resource.

The authorization happens through the `Api\App\Middleware\AuthorizationMiddleware` middleware.

Expand Down Expand Up @@ -53,13 +50,11 @@ The configuration file for the role and permission definitions is `config/autolo
],
```

> See [mezzio-authorization-rbac](https://docs.mezzio.dev/mezzio-authorization-rbac/v1/basic-usage/)
> for more information.
> See [mezzio-authorization-rbac](https://docs.mezzio.dev/mezzio-authorization-rbac/v1/basic-usage/) for more information.

## Usage

Based on the configuration file above, we have 2 admins roles (`superuser`, `admin`) and 2 users
roles (`user`, `guest`).
Based on the configuration file above, we have 2 admins roles (`superuser`, `admin`) and 2 users roles (`user`, `guest`).

Roles inherit the permissions from their parents:

Expand All @@ -68,10 +63,9 @@ Roles inherit the permissions from their parents:
- `user` has no parent
- `guest` has `user` as a parent which means `user` also has `guest` permissions

For each role we defined an array of permissions. A permission in Dotkernel API is basically a route name.
For each role we defined an array of permissions.
A permission in Dotkernel API is basically a route name.

As you can see, the `superuser` does not have its own permissions, because it gains all the permissions
from `admin`, no need to define explicit permissions.
As you can see, the `superuser` does not have its own permissions, because it gains all the permissions from `admin`, no need to define explicit permissions.

The `user` role, gains all the permission from `guest` so no need to define that `user` can access `home` route, but
`guest` cannot access user-specific routes.
The `user` role, gains all the permission from `guest` so no need to define that `user` can access `home` route, but `guest` cannot access user-specific routes.
58 changes: 20 additions & 38 deletions docs/book/v4/core-features/content-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,15 @@
application can deliver.
- To determine the `Content-Type` of incoming data and deserialize it so the application can utilize it.

Essentially, content negotiation is the *client* telling the server what it is sending and what it wants in return, and
the server determining if it can do what the client requests.
Essentially, content negotiation is the *client* telling the server what it is sending and what it wants in return, and the server determining if it can do what the client requests.

Content negotiation validation in **Dotkernel API** happens through middleware, and it ensures that the incoming
request and the outgoing response conform to the content types specified in the config file for all routes or for a
specific route.
Content negotiation validation in **Dotkernel API** happens through middleware, and it ensures that the incoming request and the outgoing response conform to the content types specified in the config file for all routes or for a specific route.

It performs validation on the `Accept` and `Content-Type` headers of the request and response and returning appropriate
errors responses when necessary.
It performs validation on the `Accept` and `Content-Type` headers of the request and response and returning appropriate errors responses when necessary.

## Configuration

In Dotkernel API the configuration file for content negotiation is held
in `config/autoload/content-negotiation.global.php`
and the array looks like this:
In Dotkernel API the configuration file for content negotiation is held in `config/autoload/content-negotiation.global.php` and the array looks like this:

```php
return [
Expand All @@ -43,39 +37,32 @@ return [
];
```

Except the `default` key, all your keys must match the route name, for example in Dotkernel API we have the route to
list all admins, which name is `admin.list`.
Except the `default` key, all your keys must match the route name, for example in Dotkernel API we have the route to list all admins, which name is `admin.list`.

If you did not specify a route name to configure your specifications about content negotiation, the `default` one will
be in place. The `default` key is `mandatory`.
If you did not specify a route name to configure your specifications about content negotiation, the `default` one will be in place.
The `default` key is `mandatory`.

Every route configuration must come with `Accept` and `Content-Type` keys, basically this will be the keys that the
request headers will be validated against.
Every route configuration must come with `Accept` and `Content-Type` keys, basically this will be the keys that the request headers will be validated against.

## Accept Negotiation

This specifies that your server can return that representation, or at least one of the representation sent by the
client.
This specifies that your server can return that representation, or at least one of the representation sent by the client.

```shell
GET /admin HTTP/1.1
Accept: application/json
```

This request indicates the client wants `application/json` in return. Now the server, through the config file will try
to validate if that representation can be returned, basically if `application/json` is presented in the `Accept` key.
This request indicates the client wants `application/json` in return.
Now the server, through the config file will try to validate if that representation can be returned, basically if `application/json` is presented in the `Accept` key.

If the representation cannot be returned, a status code `406 - Not Acceptable` will be returned.

If the representation can be returned, the server should report the media type through `Content-Type` header of the
response.
If the representation can be returned, the server should report the media type through `Content-Type` header of the response.

> Due to how these validations are made, for a `json` media type, the server can return a more generic media type,
> for example, if the clients send `Accept: application/vnd.api+json` and you configured your `Accept` key
> as `application/json` the representation will still be returned as `json`.
> Due to how these validations are made, for a `json` media type, the server can return a more generic media type, for example, if the clients send `Accept: application/vnd.api+json` and you configured your `Accept` key as `application/json` the representation will still be returned as `json`.

> If the `Accept` header of the request contains `*/*` it means that whatever the server can return it is OK, so it can
> return anything.
> If the `Accept` header of the request contains `*/*` it means that whatever the server can return it is OK, so it can return anything.

## Content-Type Negotiation

Expand All @@ -90,23 +77,18 @@ Content-Type: application/json
}
```

The server will try to validate the `Content-Type` header against your configured `Content-Type` key from the config
file, and if the format is not supported, a status code `415 - Unsupported Media Type` will be returned.
The server will try to validate the `Content-Type` header against your configured `Content-Type` key from the config file, and if the format is not supported, a status code `415 - Unsupported Media Type` will be returned.

For example, if you have a route that needs a file to be uploaded , normally you will configure the `Content-Type` of
that route to be `multipart/form-data`. The above request will fail as the client send `application/json` as
`Content-Type`.
For example, if you have a route that needs a file to be uploaded , normally you will configure the `Content-Type` of that route to be `multipart/form-data`.
The above request will fail as the client send `application/json` as `Content-Type`.

> If the request does not contain "Content-Type" header, that means that the server will try to deserialize the data as
> it can.
> If the request does not contain "Content-Type" header, that means that the server will try to deserialize the data as it can.

## The `Request <-> Response` validation

In addition to the validation described above, a third one is happening and is the last one: the server will check if
the request `Accept` header can really be returned by the response.
In addition to the validation described above, a third one is happening and is the last one: the server will check if the request `Accept` header can really be returned by the response.

Through the way **Dotkernel API** is returning a response in handler, a content type is always set.

This cannot be the case in any custom response but in any case the server will check what `Content-Type` the response is
returning and will try to validate that against the `Accept` header of the request.
This cannot be the case in any custom response but in any case the server will check what `Content-Type` the response is returning and will try to validate that against the `Accept` header of the request.
If the validation fails, a status code `406 - Not Acceptable` will be returned.
9 changes: 3 additions & 6 deletions docs/book/v4/core-features/cors.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

## What is CORS?

**Cross-Origin Resource Sharing** or _CORS_ is an HTTP-header based mechanism that allows a server to indicate any other
origins (domain, scheme, or port) than its own from which a browser should permit loading of resources.
**Cross-Origin Resource Sharing** or _CORS_ is an HTTP-header based mechanism that allows a server to indicate any other origins (domain, scheme, or port) than its own from which a browser should permit loading of resources.

## Why do we need CORS?

When integrating an API, most developers have encountered the following error message:

> Access to fetch at _RESOURCE_URL_ from origin _ORIGIN_URL_ has been blocked by CORS policy:
> No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
> Access to fetch at _RESOURCE_URL_ from origin _ORIGIN_URL_ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

This happens because the API (_RESOURCE_URL_) is not configured to accept requests from the client (_ORIGIN_URL_).

Expand Down Expand Up @@ -86,7 +84,6 @@ This list explains the above configuration values:

Save and close the file.

> On the **production** environment, make sure you allow only specific origins by adding them to the `allowed_origins`
> array and removing the current value of `ConfigurationInterface::ANY_ORIGIN`.
> On the **production** environment, make sure you allow only specific origins by adding them to the `allowed_origins` array and removing the current value of `ConfigurationInterface::ANY_ORIGIN`.

For more info, see [mezzio/mezzio-cors documentation](https://docs.mezzio.dev/mezzio-cors/v1/middleware/#configuration).
19 changes: 6 additions & 13 deletions docs/book/v4/core-features/exceptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@

## What are exceptions?

Exceptions are a powerful mechanism for handling errors and other exceptional conditions that may occur during the
execution of a script.
They provide a way to manage errors in a structured and controlled manner, separating error-handling code from regular
code.
Exceptions are a powerful mechanism for handling errors and other exceptional conditions that may occur during the execution of a script.
They provide a way to manage errors in a structured and controlled manner, separating error-handling code from regular code.

## How we use exceptions?

When it comes to handling exceptions, **Dotkernel API** relies on the usage of easy-to-understand, problem-specific
exceptions.
When it comes to handling exceptions, **Dotkernel API** relies on the usage of easy-to-understand, problem-specific exceptions.

Out-of-the-box we provide the following custom exceptions:

Expand Down Expand Up @@ -53,8 +50,7 @@ Out-of-the-box we provide the following custom exceptions:

## How it works?

During a request, if there is no uncaught exception **Dotkernel API** will return a JSON response with the data provided
by the handler that handled the request.
During a request, if there is no uncaught exception **Dotkernel API** will return a JSON response with the data provided by the handler that handled the request.

Else, it will build and send a response based on the exception thrown:

Expand All @@ -69,9 +65,7 @@ Else, it will build and send a response based on the exception thrown:

## How to extend?

In this example we will create a custom exception called `CustomException`, place it next to the already existing custom
exceptions (you can use your preferred location) and finally return a custom HTTP status code when `CustomException` is
encountered.
In this example we will create a custom exception called `CustomException`, place it next to the already existing custom exceptions (you can use your preferred location) and finally return a custom HTTP status code when `CustomException` is encountered.

### Step 1: Create exception file

Expand Down Expand Up @@ -106,8 +100,7 @@ Save and close the file.

### Step 3: Test for failure

Access your API's home page URL and make sure it returns `500 Internal Server Error` HTTP status code and the following
content:
Access your API's home page URL and make sure it returns `500 Internal Server Error` HTTP status code and the following content:

```json
{
Expand Down
5 changes: 4 additions & 1 deletion docs/book/v4/installation/doctrine-orm.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ php vendor/bin/doctrine-migrations migrate

This command will prompt you to confirm that you want to run it.

> WARNING! You are about to execute a migration in database "..." that could result in schema changes and data loss. Are you sure you wish to continue? (yes/no) [yes]:
> WARNING!
> You are about to execute a migration in database "..." that could result in schema changes and data loss.
> Are you sure you wish to continue?
> (yes/no) [yes]:

Hit `Enter` to confirm the operation.

Expand Down
5 changes: 3 additions & 2 deletions docs/book/v4/installation/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
> If you are using Windows as OS on your machine, you can use WSL2 as development environment.
> Read more here: [PHP-Mariadb-on-WLS2](https://www.dotkernel.com/php-development/almalinux-9-in-wsl2-install-php-apache-mariadb-composer-phpmyadmin/)

Using your terminal, navigate inside the directory you want to download the project files into. Make sure that the
directory is empty before proceeding to the download process. Once there, run the following command:
Using your terminal, navigate inside the directory you want to download the project files into.
Make sure that the directory is empty before proceeding to the download process.
Once there, run the following command:

```shell
git clone https://github.com/dotkernel/api.git .
Expand Down
Loading