Skip to content

Commit 7fdd476

Browse files
authored
Merge pull request #33 from dotkernel/issue-32
Issue #32: Created token authentication page
2 parents 7664d92 + 47c51d0 commit 7fdd476

File tree

2 files changed

+361
-0
lines changed

2 files changed

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