]>
Commit | Line | Data |
---|---|---|
f320efd6 | 1 | ## Usage and Prerequisites |
53ed6d7d | 2 | |
f320efd6 V |
3 | See the [REST API documentation](http://shaarli.github.io/api-documentation/) |
4 | for a list of available endpoints and parameters. | |
5 | ||
87f14312 V |
6 | Please ensure that your server meets the |
7 | [requirements](Server-configuration#prerequisites) and is properly | |
8 | [configured](Server-configuration): | |
f320efd6 V |
9 | |
10 | - URL rewriting is enabled (see specific Apache and Nginx sections) | |
11 | - the server's timezone is properly defined | |
12 | - the server's clock is synchronized with | |
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). | |
53ed6d7d | 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 | ||
43ad7c8e V |
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 | |
53ed6d7d | 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 | ||
f320efd6 | 59 | **Token expiration** |
53ed6d7d | 60 | |
f320efd6 V |
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**. | |
53ed6d7d | 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 | ||
74 | #### Signature | |
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 | ||
85 | ||
61f63d10 V |
86 | ## 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 | ||
57c628e1 V |
92 | ### Javascript, NodeJS |
93 | ||
94 | - [shaarli-client](https://www.npmjs.com/package/shaarli-client) | |
95 | ([source code](https://github.com/laBecasse/shaarli-client)) | |
96 | by [laBecasse](https://github.com/laBecasse) | |
53ed6d7d | 97 | |
e62486dd V |
98 | ### PHP |
99 | ||
100 | This example uses the [PHP cURL](http://php.net/manual/en/book.curl.php) library. | |
53ed6d7d | 101 | |
102 | ```php | |
e62486dd V |
103 | <?php |
104 | $baseUrl = 'https://shaarli.mydomain.net'; | |
105 | $secret = 'thats_my_api_secret'; | |
106 | ||
107 | function base64url_encode($data) { | |
108 | return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); | |
109 | } | |
110 | ||
53ed6d7d | 111 | function generateToken($secret) { |
e62486dd | 112 | $header = base64url_encode('{ |
53ed6d7d | 113 | "typ": "JWT", |
114 | "alg": "HS512" | |
115 | }'); | |
e62486dd | 116 | $payload = base64url_encode('{ |
53ed6d7d | 117 | "iat": '. time() .' |
118 | }'); | |
e62486dd V |
119 | $signature = base64url_encode(hash_hmac('sha512', $header .'.'. $payload , $secret, true)); |
120 | return $header . '.' . $payload . '.' . $signature; | |
53ed6d7d | 121 | } |
122 | ||
53ed6d7d | 123 | |
e62486dd V |
124 | function getInfo($baseUrl, $secret) { |
125 | $token = generateToken($secret); | |
126 | $endpoint = rtrim($baseUrl, '/') . '/api/v1/info'; | |
53ed6d7d | 127 | |
e62486dd V |
128 | $headers = [ |
129 | 'Content-Type: text/plain; charset=UTF-8', | |
130 | 'Authorization: Bearer ' . $token, | |
131 | ]; | |
132 | ||
133 | $ch = curl_init($endpoint); | |
134 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); | |
135 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
136 | curl_setopt($ch, CURLOPT_AUTOREFERER, 1); | |
137 | curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1); | |
138 | ||
139 | $result = curl_exec($ch); | |
140 | curl_close($ch); | |
141 | ||
142 | return $result; | |
143 | } | |
144 | ||
145 | var_dump(getInfo($baseUrl, $secret)); | |
53ed6d7d | 146 | ``` |
61f63d10 V |
147 | |
148 | ||
149 | ### Python | |
150 | ||
151 | See the reference API client: | |
152 | ||
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 | |
40f0ff22 A |
155 | |
156 | ## Troubleshooting | |
157 | ||
158 | ### Debug mode | |
159 | ||
160 | > This should never be used in a production environment. | |
161 | ||
162 | For security reasons, authentication issues will always return an `HTTP 401` error code without any detail. | |
163 | ||
164 | It is possible to enable the debug mode in `config.json.php` | |
165 | to get the actual error message in the HTTP response body with: | |
166 | ||
167 | ```json | |
168 | { | |
169 | "dev": { | |
170 | "debug": true | |
171 | } | |
172 | } | |
173 | ``` |