diff options
Diffstat (limited to 'doc/md/REST-API.md')
-rw-r--r-- | doc/md/REST-API.md | 159 |
1 files changed, 68 insertions, 91 deletions
diff --git a/doc/md/REST-API.md b/doc/md/REST-API.md index 11bd1cd2..01071d8e 100644 --- a/doc/md/REST-API.md +++ b/doc/md/REST-API.md | |||
@@ -1,101 +1,24 @@ | |||
1 | ## Usage and Prerequisites | 1 | # REST API |
2 | 2 | ||
3 | See the [REST API documentation](http://shaarli.github.io/api-documentation/) | 3 | ## Server requirements |
4 | for a list of available endpoints and parameters. | ||
5 | 4 | ||
6 | Please ensure that your server meets the | 5 | See the **[REST API documentation](http://shaarli.github.io/api-documentation/)** for a list of available endpoints and parameters. |
7 | [requirements](Server-configuration#prerequisites) and is properly | 6 | |
8 | [configured](Server-configuration): | 7 | Please ensure that your server meets the requirements and is properly [configured](Server-configuration): |
9 | 8 | ||
10 | - URL rewriting is enabled (see specific Apache and Nginx sections) | 9 | - URL rewriting is enabled (see specific Apache and Nginx sections) |
11 | - the server's timezone is properly defined | 10 | - the server's timezone is properly defined |
12 | - the server's clock is synchronized with | 11 | - the server's clock is synchronized with [NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol) |
13 | [NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol) | ||
14 | |||
15 | The host where the API client is invoked should also be synchronized with NTP, | ||
16 | see [token expiration](#payload). | ||
17 | |||
18 | ## Authentication | ||
19 | |||
20 | All requests to Shaarli's API must include a JWT token to verify their authenticity. | ||
21 | |||
22 | This token has to be included as an HTTP header called `Authentication: Bearer <jwt token>`. | ||
23 | |||
24 | JWT resources : | ||
25 | |||
26 | - [jwt.io](https://jwt.io) (including a list of client per language). | ||
27 | - RFC : https://tools.ietf.org/html/rfc7519 | ||
28 | - https://float-middle.com/json-web-tokens-jwt-vs-sessions/ | ||
29 | - HackerNews thread: https://news.ycombinator.com/item?id=11929267 | ||
30 | |||
31 | |||
32 | ### Shaarli JWT Token | ||
33 | |||
34 | JWT tokens are composed by three parts, separated by a dot `.` and encoded in base64: | ||
35 | |||
36 | ``` | ||
37 | [header].[payload].[signature] | ||
38 | ``` | ||
39 | |||
40 | #### Header | ||
41 | |||
42 | Shaarli only allow one hash algorithm, so the header will always be the same: | ||
43 | |||
44 | ```json | ||
45 | { | ||
46 | "typ": "JWT", | ||
47 | "alg": "HS512" | ||
48 | } | ||
49 | ``` | ||
50 | |||
51 | Encoded in base64, it gives: | ||
52 | |||
53 | ``` | ||
54 | ewogICAgICAgICJ0eXAiOiAiSldUIiwKICAgICAgICAiYWxnIjogIkhTNTEyIgogICAgfQ== | ||
55 | ``` | ||
56 | |||
57 | #### Payload | ||
58 | |||
59 | **Token expiration** | ||
60 | |||
61 | To avoid infinite token validity, JWT tokens must include their creation date | ||
62 | in UNIX timestamp format (timezone independent - UTC) under the key `iat` (issued at). | ||
63 | This token will be valid during **9 minutes**. | ||
64 | |||
65 | ```json | ||
66 | { | ||
67 | "iat": 1468663519 | ||
68 | } | ||
69 | ``` | ||
70 | |||
71 | See [RFC reference](https://tools.ietf.org/html/rfc7519#section-4.1.6). | ||
72 | |||
73 | 12 | ||
74 | #### Signature | 13 | The host where the API client is invoked should also be synchronized with NTP, see _payload/token expiration_ |
75 | |||
76 | The signature authenticate the token validity. It contains the base64 of the header and the body, separated by a dot `.`, hashed in SHA512 with the API secret available in Shaarli administration page. | ||
77 | |||
78 | Signature example with PHP: | ||
79 | |||
80 | ```php | ||
81 | $content = base64_encode($header) . '.' . base64_encode($payload); | ||
82 | $signature = hash_hmac('sha512', $content, $secret); | ||
83 | ``` | ||
84 | 14 | ||
85 | 15 | ||
86 | ## Clients and examples | 16 | ## Clients and examples |
87 | ### Android, Java, Kotlin | ||
88 | |||
89 | - [Android client example with Kotlin](https://gitlab.com/snippets/1665808) | ||
90 | by [Braincoke](https://github.com/Braincoke) | ||
91 | |||
92 | ### Javascript, NodeJS | ||
93 | 17 | ||
94 | - [shaarli-client](https://www.npmjs.com/package/shaarli-client) | 18 | - **[python-shaarli-client](https://github.com/shaarli/python-shaarli-client)** - the reference API client ([Documentation](http://python-shaarli-client.readthedocs.io/en/latest/)) |
95 | ([source code](https://github.com/laBecasse/shaarli-client)) | 19 | - [shaarli-client](https://www.npmjs.com/package/shaarli-client) - NodeJs client ([source code](https://github.com/laBecasse/shaarli-client)) by [laBecasse](https://github.com/laBecasse) |
96 | by [laBecasse](https://github.com/laBecasse) | 20 | - [Android client example with Kotlin](https://gitlab.com/snippets/1665808) by [Braincoke](https://github.com/Braincoke) |
97 | 21 | ||
98 | ### PHP | ||
99 | 22 | ||
100 | This example uses the [PHP cURL](http://php.net/manual/en/book.curl.php) library. | 23 | This example uses the [PHP cURL](http://php.net/manual/en/book.curl.php) library. |
101 | 24 | ||
@@ -145,13 +68,57 @@ function getInfo($baseUrl, $secret) { | |||
145 | var_dump(getInfo($baseUrl, $secret)); | 68 | var_dump(getInfo($baseUrl, $secret)); |
146 | ``` | 69 | ``` |
147 | 70 | ||
71 | ## Implementation | ||
72 | |||
73 | ### Authentication | ||
74 | |||
75 | - All requests to Shaarli's API must include a **JWT token** to verify their authenticity. | ||
76 | - This token must be included as an HTTP header called `Authentication: Bearer <jwt token>`. | ||
77 | - JWT tokens are composed by three parts, separated by a dot `.` and encoded in base64: | ||
78 | |||
79 | ``` | ||
80 | [header].[payload].[signature] | ||
81 | ``` | ||
82 | |||
83 | ##### Header | ||
84 | |||
85 | Shaarli only allow one hash algorithm, so the header will always be the same: | ||
86 | |||
87 | ```json | ||
88 | { | ||
89 | "typ": "JWT", | ||
90 | "alg": "HS512" | ||
91 | } | ||
92 | ``` | ||
93 | |||
94 | Encoded in base64, it gives: | ||
148 | 95 | ||
149 | ### Python | 96 | ``` |
97 | ewogICAgICAgICJ0eXAiOiAiSldUIiwKICAgICAgICAiYWxnIjogIkhTNTEyIgogICAgfQ== | ||
98 | ``` | ||
99 | |||
100 | ##### Payload | ||
101 | |||
102 | Token expiration: To avoid infinite token validity, JWT tokens must include their creation date in UNIX timestamp format (timezone independent - UTC) under the key `iat` (issued at) field ([1](https://tools.ietf.org/html/rfc7519#section-4.1.6)). This token will be valid during **9 minutes**. | ||
103 | |||
104 | ```json | ||
105 | { | ||
106 | "iat": 1468663519 | ||
107 | } | ||
108 | ``` | ||
109 | |||
110 | ##### Signature | ||
111 | |||
112 | The signature authenticates the token validity. It contains the base64 of the header and the body, separated by a dot `.`, hashed in SHA512 with the API secret available in Shaarli administration page. | ||
113 | |||
114 | Example signature with PHP: | ||
115 | |||
116 | ```php | ||
117 | $content = base64_encode($header) . '.' . base64_encode($payload); | ||
118 | $signature = hash_hmac('sha512', $content, $secret); | ||
119 | ``` | ||
150 | 120 | ||
151 | See the reference API client: | ||
152 | 121 | ||
153 | - [Documentation](http://python-shaarli-client.readthedocs.io/en/latest/) on ReadTheDocs | ||
154 | - [python-shaarli-client](https://github.com/shaarli/python-shaarli-client) on Github | ||
155 | 122 | ||
156 | ## Troubleshooting | 123 | ## Troubleshooting |
157 | 124 | ||
@@ -171,3 +138,13 @@ to get the actual error message in the HTTP response body with: | |||
171 | } | 138 | } |
172 | } | 139 | } |
173 | ``` | 140 | ``` |
141 | |||
142 | ## References | ||
143 | |||
144 | - [jwt.io](https://jwt.io) (including a list of client per language). | ||
145 | - [RFC - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) | ||
146 | - [JSON Web Tokens (JWT) vs Sessions](https://float-middle.com/json-web-tokens-jwt-vs-sessions/), [HackerNews thread](https://news.ycombinator.com/item?id=11929267) | ||
147 | |||
148 | |||
149 | |||
150 | |||