Skip to content

Commit 5ec9bdc

Browse files
committed
updated introduction, authentication pages
Signed-off-by: bidi <bidi@apidemia.com>
1 parent 77853ca commit 5ec9bdc

File tree

7 files changed

+680
-79
lines changed

7 files changed

+680
-79
lines changed

docs/book/v7/core-features/authentication.md

Lines changed: 94 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@ It ensures that the entity making the request has the proper credentials to acce
66
**Dotkernel API** identities are delivered to the application from the client through the `Authorization` request.
77
If it is present, the application tries to find and assign the identity to the application.
88
If it is not presented, Dotkernel API assigns a default `guest` identity, represented by an instance of the class `Mezzio\Authentication\UserInterface`.
9+
Guests can access public endpoints but cannot access protected resources (those requiring user or admin roles).
10+
Check out the Authorization page for more details on role-based access.
911

1012
## Configuration
1113

14+
Dotkernel API uses the **OAuth2 password grant flow** for authentication.
15+
This allows users to exchange their credentials (username/password) for access tokens.
16+
These tokens are then used for later requests instead of repeatedly sending credentials.
17+
1218
Authentication in Dotkernel API is built around the `mezzio/mezzio-authentication-oauth2` component and is already configured out of the box.
13-
But if you want to dig more, the configuration is stored in `config/autoload/local.php` under the `authentication` key.
19+
To customize authentication behavior (token lifetimes, algorithms, etc.), edit `config/autoload/local.php` under the `authentication` key.
20+
See the [Mezzio OAuth2 documentation](https://docs.mezzio.dev/mezzio-authentication-oauth2/v1/intro/#configuration) for all available options.
1421

1522
> You can check the
1623
> [mezzio/mezzio-authentication-oauth2](https://docs.mezzio.dev/mezzio-authentication-oauth2/v1/intro/#configuration)
@@ -23,32 +30,46 @@ It allows each user of your application to generate API tokens for their account
2330

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

26-
## Database
33+
### Database
2734

28-
When you install **Dotkernel API** for the first time, you need to run the migrations and seeders.
35+
When you install **Dotkernel API** for the first time, you need to run the migrations and seeders (fixtures).
2936
All the tables required for authentication are automatically created and populated.
3037

31-
In Dotkernel API, authenticated users come from either the `admin` or the `user` table.
32-
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.
38+
```shell
39+
php ./vendor/bin/doctrine-migrations migrate
40+
php ./bin/doctrine fixtures:execute
41+
```
42+
43+
The commands above create OAuth tables (oauth_clients, oauth_scopes, oauth_*) and seed the initial credentials:
44+
45+
- **Admin**: identity=admin, password=dotadmin
46+
- **User**: identity=test@dotkernel.com, password=dotkernel
3347

34-
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**).
48+
Check out the [Installation Guide](https://docs.dotkernel.org/api-documentation/v7/installation/doctrine-orm/) for more details.
3549

36-
As you guessed each client serves to authenticate `admin` or `user`.
50+
In Dotkernel API, authenticated users come from either the `admin` or the `user` tables.
51+
We chose to keep the admin and user tables separate to prevent users of the application from accessing sensitive data that only administrators should access.
3752

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

4055
### Issuing API Tokens
4156

4257
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).
4358

44-
The client sends a POST request to the `/security/generate-token` with the following parameters:
59+
The `POST /security/generate-token` endpoint accepts OAuth2 credentials and returns both an access token (for making API calls) and a refresh token (for refreshing expired access tokens).
60+
61+
The client requires the following parameters:
4562

46-
- `grant_type` = password.
47-
- `client_id` = column `name` from the `oauth_clients` table
48-
- `client_secret` = column `secret` from the `oauth_clients` table
49-
- `scope` = column `scope` from the `oauth_scopes` table
50-
- `username` = column `identity` from table `admin`/`user`
51-
- `password` = column `password` from table `admin`/`user`
63+
| Field | Type | Purpose | Example |
64+
|-----------------|--------|----------------------------------------------------------|------------------------|
65+
| `grant_type` | string | OAuth2 flow type | `"password"` |
66+
| `client_id` | string | OAuth client identifier from the `oauth_clients` table | `"frontend"` |
67+
| `client_secret` | string | OAuth client credential from the `oauth_clients` table | `"frontend"` |
68+
| `scope` | string | Permission scope from the `oauth_scopes` table | `"api"` |
69+
| `username` | string | User identity (email/username) from table `admin`/`user` | `"test@dotkernel.com"` |
70+
| `password` | string | User password | `"dotkernel"` |
71+
72+
This is what the call should look like:
5273

5374
```shell
5475
POST /security/generate-token HTTP/1.1
@@ -75,7 +96,14 @@ The server responds with a JSON as follows:
7596
}
7697
```
7798

78-
Next time when you make a request to the server to an authenticated endpoint, the client should use the `Authorization` header request.
99+
| Field | Type | Lifetime | Purpose |
100+
|-----------------|---------|--------------------------------------|---------------------------------------|
101+
| `token_type` | string | N/A | Header value type |
102+
| `expires_in` | integer | N/A | Seconds until access token expires |
103+
| `access_token` | string | 86400 seconds = 1 day (configurable) | Used in `Authorization` header |
104+
| `refresh_token` | string | 1 month (configurable) | Used to refresh expired access tokens |
105+
106+
On later requests to the server for an authenticated endpoint, the client should use the `Authorization` header request.
79107

80108
```shell
81109
GET /users/1 HTTP/1.1
@@ -85,24 +113,22 @@ Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...
85113

86114
### Refreshing tokens
87115

88-
Dotkernel API can refresh the access token, based on the expired access token's `refresh_token`.
89-
90-
The clients need to send a `POST` request to the `/security/refresh-token` with the following request:
116+
When an access token expires, use the refresh token (received during token generation) to obtain a new access token without re-entering credentials:
91117

92118
```shell
93-
POST /security/refresh-token HTTP/1.1
119+
POST /security/refresh-token
94120
Accept: application/json
95121
Content-Type: application/json
96122
{
97123
"grant_type": "refresh_token",
98124
"client_id": "frontend",
99125
"client_secret": "frontend",
100126
"scope": "api",
101-
"refresh_token" : "def5020087199939a49d0f2f818..."
127+
"refresh_token": "def5020087199939a49d0f2f818..."
102128
}
103129
```
104130

105-
The server responds with a JSON as follows:
131+
The response contains a new `access_token` and `refresh_token`:
106132

107133
```json
108134
{
@@ -112,3 +138,50 @@ The server responds with a JSON as follows:
112138
"refresh_token": "def5020087199939a49d0f2f818..."
113139
}
114140
```
141+
142+
## Common Issues
143+
144+
**"Invalid credentials" error**
145+
146+
- Check username/password are correct.
147+
- Verify client_id and client_secret match OAuth client in the database.
148+
- Confirm the user account exists and is active.
149+
150+
**"Token has expired" error**
151+
152+
- Use refresh_token to get a new access_token.
153+
- If refresh_token is expired, re-authenticate with credentials.
154+
155+
**"Invalid scope" error**
156+
157+
- Verify `scope` field is set to `"api"` (the only configured scope)
158+
159+
## Flow Diagram
160+
161+
```quote
162+
User Credentials
163+
164+
POST /security/generate-token
165+
166+
Access Token + Refresh Token
167+
168+
Store tokens securely ←─────────────────────────┐
169+
↓ |
170+
Include Access Token in Authorization header |
171+
↓ |
172+
Make API requests |
173+
↓ |
174+
Token expires? |
175+
↓ (yes) |
176+
POST /security/refresh-token with refresh_token |
177+
↓ |
178+
Get new Access Token ───────────────────────────┘
179+
```
180+
181+
## Security Best Practices
182+
183+
- **Store tokens securely**: Never commit tokens to version control. Use environment variables or secure storage.
184+
- **Use HTTPS only**: OAuth2 tokens should only be transmitted over HTTPS in production.
185+
- **Rotate credentials**: Change default OAuth client secrets in production.
186+
- **Token expiration**: Access tokens expire (default 1 day). Implement refresh logic in clients.
187+
- **Never expose refresh tokens**: Refresh tokens should only be stored client-side, never in logs or public code.

0 commit comments

Comments
 (0)