Skip to content

Commit 8c1874e

Browse files
committed
Issue #32: CreateD token authentication page.
Signed-off-by: alexmerlin <alex.merlin.1985@gmail.com>
1 parent ee2ca79 commit 8c1874e

2 files changed

Lines changed: 355 additions & 0 deletions

File tree

Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
# Token authentication
2+
3+
## What is token authentication?
4+
5+
Token authentication means making a request to an API endpoint while also sending a special header that contains an
6+
access token. The access token was previously generated by (usually) the same API as the one you are sending requests to
7+
and it consists of an alphanumeric string.
8+
9+
## How does it work?
10+
11+
In order to protect specific resources, clients need to be authenticated with user/admin roles. These roles are
12+
identified from the access token sent via the `Authorization` header.
13+
14+
When DotKernel API receives a request, it tries to read the access token:
15+
16+
- if it does not find an access token, client has `guest` role:
17+
- if the requested endpoint needs no authentication, the requested resource is returned
18+
- else, a `403 Forbidden` response is returned
19+
- else, client's account is identified and client has `admin`/`user` role (the one assigned in their account)
20+
- if the requested endpoint is accessible to the client, the requested resource is returned
21+
- else, a `403 Forbidden` response is returned
22+
23+
DotKernel API provides out-of-the-box both:
24+
25+
- an account with **role** set to both `superuser` and `admin` with the following credentials:
26+
- **identity**: `admin`
27+
- **password**: `dotkernel`
28+
- an account with **role** set to both `user` and `guest` with the following credentials:
29+
- **identify**: `test@dotkernel.com`
30+
- **password**: `dotkernel`
31+
32+
## Flow
33+
34+
- client sends API request with credentials
35+
- API returns a JSON object containing a new access and refresh token
36+
- client sends API request using `Authentication` header containing the previously generated access token
37+
- API returns requested resource
38+
39+
### Note
40+
41+
> The first two steps need to executed only once.
42+
> Access token should be stored and reused for all upcoming requests.
43+
> Refresh token should be stored and used to refresh expired access token.
44+
45+
For a better overview of the flow, see the below image:
46+
47+
![](https://docs.dotkernel.org/img/api/token-authentication.png "Token authentication flow")
48+
49+
## Generate admin access token
50+
51+
Send a `POST` request to the `/security/generate-token` endpoint with `Content-Type` header set to `application/json`.
52+
53+
Set request body to:
54+
55+
```json
56+
{
57+
"grant_type": "password",
58+
"client_id": "admin",
59+
"client_secret": "admin",
60+
"scope": "api",
61+
"username": "<identity>",
62+
"password": "<password>"
63+
}
64+
```
65+
66+
### Note
67+
68+
> Replace `<identity>` with your admin account's `identity` and `<password>` with your admin account's `password`.
69+
> Both fields come from table `admin`.
70+
71+
### Test using curl
72+
73+
Execute the below command:
74+
75+
```shell
76+
curl --location 'https://api.dotkernel.net/security/generate-token' \
77+
--header 'Content-Type: application/json' \
78+
--data-raw '{
79+
"grant_type": "password",
80+
"client_id": "admin",
81+
"client_secret": "admin",
82+
"scope": "api",
83+
"username": "admin",
84+
"password": "dotkernel"
85+
}'
86+
```
87+
88+
## Generate user access token
89+
90+
Send a `POST` request to the `/security/generate-token` endpoint with `Content-Type` header set to `application/json`.
91+
92+
Set request body to:
93+
94+
```json
95+
{
96+
"grant_type": "password",
97+
"client_id": "frontend",
98+
"client_secret": "frontend",
99+
"scope": "api",
100+
"username": "<identity>",
101+
"password": "<password>"
102+
}
103+
```
104+
105+
### Note
106+
107+
> Replace `<identity>` with your user account's `identity` and `<password>` with your user account's `password`.
108+
> Both fields come from table `user`.
109+
110+
### Test using curl
111+
112+
Execute the below command:
113+
114+
```shell
115+
curl --location 'https://api.dotkernel.net/security/generate-token' \
116+
--header 'Content-Type: application/json' \
117+
--data-raw '{
118+
"grant_type": "password",
119+
"client_id": "frontend",
120+
"client_secret": "frontend",
121+
"scope": "api",
122+
"username": "test@dotkernel.com",
123+
"password": "dotkernel"
124+
}'
125+
```
126+
127+
### Response on success
128+
129+
You should see a `200 OK` response with the following JSON body:
130+
131+
```json
132+
{
133+
"token_type": "Bearer",
134+
"expires_in": 86400,
135+
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.e...wuE39ON1mS5mnTKfA_dSpSWxOmNQdny_AKIbc1qZjMfS24qSUV8HIoOw",
136+
"refresh_token": "def502005a035c8dfe5456d27e85069813a4f8...0b844e843cd62865662a0e723165752dfd7012491502d3d819c2a61d"
137+
}
138+
```
139+
140+
Field description:
141+
142+
- `token_type`: token type to be set when sending the `Authorization` header (example: `Authorization: Bearer eyJ0e...`)
143+
- `expires_in`: access token lifetime (modify in: `config/autoload/local.php` > `authentication`.`access_token_expire`)
144+
- `access_token`: generated access token (store it for later use)
145+
- `refresh_token`: generated refresh token (store it for regenerating expired access token)
146+
147+
### Response on failure
148+
149+
You should see a `400 Bad Request` response with the following JSON body:
150+
151+
```json
152+
{
153+
"error": "Invalid credentials.",
154+
"error_description": "Invalid credentials.",
155+
"message": "Invalid credentials."
156+
}
157+
```
158+
159+
## Refresh admin access token
160+
161+
Send a `POST` request to the `/security/refresh-token` endpoint with `Content-Type` header set to `application/json`.
162+
163+
Set request body to:
164+
165+
```json
166+
{
167+
"grant_type": "refresh_token",
168+
"client_id": "admin",
169+
"client_secret": "admin",
170+
"scope": "api",
171+
"refresh_token": "<refresh-token>"
172+
}
173+
```
174+
175+
### Test using curl
176+
177+
Execute the below command:
178+
179+
```shell
180+
curl --location 'https://api.dotkernel.net/security/refresh-token' \
181+
--header 'Content-Type: application/json' \
182+
--data-raw '{
183+
"grant_type": "refresh_token",
184+
"client_id": "admin",
185+
"client_secret": "admin",
186+
"scope": "api",
187+
"refresh_token": "<refresh-token>"
188+
}'
189+
```
190+
191+
### Note
192+
193+
> Make sure you replace `<refresh-token>` with the refresh token generated with the access token.
194+
195+
## Refresh user access token
196+
197+
Send a `POST` request to the `/security/refresh-token` endpoint with `Content-Type` header set to `application/json`.
198+
199+
Set request body to:
200+
201+
```json
202+
{
203+
"grant_type": "refresh_token",
204+
"client_id": "frontend",
205+
"client_secret": "frontend",
206+
"scope": "api",
207+
"refresh_token": "<refresh-token>"
208+
}
209+
```
210+
211+
### Test using curl
212+
213+
Execute the below command:
214+
215+
```shell
216+
curl --location 'https://api.dotkernel.net/security/refresh-token' \
217+
--header 'Content-Type: application/json' \
218+
--data-raw '{
219+
"grant_type": "refresh_token",
220+
"client_id": "frontend",
221+
"client_secret": "frontend",
222+
"scope": "api",
223+
"refresh_token": "<refresh-token>"
224+
}'
225+
```
226+
227+
### Note
228+
229+
> Make sure you replace `<refresh-token>` with the refresh token generated with the access token.
230+
231+
### Response on success
232+
233+
You should see a `200 OK` response with the following JSON body:
234+
235+
```json
236+
{
237+
"token_type": "Bearer",
238+
"expires_in": 86400,
239+
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.e...wuE39ON1mS5mnTKfA_dSpSWxOmNQdny_AKIbc1qZjMfS24qSUV8HIoOw",
240+
"refresh_token": "def502005a035c8dfe5456d27e85069813a4f8...0b844e843cd62865662a0e723165752dfd7012491502d3d819c2a61d"
241+
}
242+
```
243+
244+
Field description:
245+
246+
- `token_type`: token type to be set when sending the `Authorization` header (example: `Authorization: Bearer eyJ0e...`)
247+
- `expires_in`: access token lifetime (change here: `config/autoload/local.php` `authentication`->`access_token_expire`)
248+
- `access_token`: generated access token (store it for later use)
249+
- `refresh_token`: generated refresh token (store it for regenerating expired access token)
250+
251+
### Response on failure
252+
253+
You should see a `401 Unauthorized` response with the following JSON body:
254+
255+
```json
256+
{
257+
"error": "invalid_request",
258+
"error_description": "The refresh token is invalid.",
259+
"hint": "Cannot decrypt the refresh token",
260+
"message": "The refresh token is invalid."
261+
}
262+
```
263+
264+
## Test admin authentication flow
265+
266+
### Step 1: Fail to fetch protected API content
267+
268+
Try to view your admin account by executing:
269+
270+
```shell
271+
curl --location 'https://api.dotkernel.net/admin/my-account'
272+
```
273+
274+
You should get a `403 Forbidden` JSON response.
275+
276+
### Step 2: Generate access token
277+
278+
Generate admin access token by executing:
279+
280+
```shell
281+
curl --location 'https://api.dotkernel.net/security/generate-token' \
282+
--header 'Content-Type: application/json' \
283+
--data-raw '{
284+
"grant_type": "password",
285+
"client_id": "admin",
286+
"client_secret": "admin",
287+
"scope": "api",
288+
"username": "admin",
289+
"password": "dotkernel"
290+
}'
291+
```
292+
293+
You should get a `200 OK` JSON response.
294+
295+
Store the value of `access_token` for later use.
296+
297+
### Step 3: Successfully fetch protected API content
298+
299+
Try again viewing your admin account by executing:
300+
301+
```shell
302+
curl --location 'https://api.dotkernel.net/admin/my-account' \
303+
--header 'Authorization: Bearer <access_token>'
304+
```
305+
306+
Replace `<access_token>` with the previously stored access token.
307+
308+
You should get a `200 OK` JSON response with the requested resource in the body.
309+
310+
## Test user authentication flow
311+
312+
### Step 1: Fail to fetch protected API content
313+
314+
Try to view your admin account by executing:
315+
316+
```shell
317+
curl --location 'https://api.dotkernel.net/user/my-account'
318+
```
319+
320+
You should get a `403 Forbidden` JSON response.
321+
322+
### Step 2: Generate access token
323+
324+
Generate admin access token by executing:
325+
326+
```shell
327+
curl --location 'https://api.dotkernel.net/security/generate-token' \
328+
--header 'Content-Type: application/json' \
329+
--data-raw '{
330+
"grant_type": "password",
331+
"client_id": "frontend",
332+
"client_secret": "frontend",
333+
"scope": "api",
334+
"username": "test@dotkernel.com",
335+
"password": "dotkernel"
336+
}'
337+
```
338+
339+
You should get a `200 OK` JSON response.
340+
341+
Store the value of `access_token` for later use.
342+
343+
### Step 3: Successfully fetch protected API content
344+
345+
Try again viewing your admin account by executing:
346+
347+
```shell
348+
curl --location 'https://api.dotkernel.net/user/my-account' \
349+
--header 'Authorization: Bearer <access_token>'
350+
```
351+
352+
Replace `<access_token>` with the previously stored access token.
353+
354+
You should get a `200 OK` JSON response with the requested resource in the body.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ nav:
3737
- "Generate tokens": v4/commands/generate-tokens.md
3838
- Tutorials:
3939
- "Creating a book module": v4/tutorials/create-book-module.md
40+
- "Creating a book module": v4/tutorials/token-authentication.md
4041
- Transition from API Tools:
4142
- "Laminas API Tools vs DotKernel API": v4/transition-from-api-tools/api-tools-vs-dotkernel-api.md
4243
- "Transition Approach": v4/transition-from-api-tools/transition-approach.md

0 commit comments

Comments
 (0)