2547cee9acc6144bb9129c29c91166a114b13baf
[src/app-framework-binder.git] / doc / afb-application-writing.html
1 <html>
2 <head>
3   <link rel="stylesheet" type="text/css" href="doc.css">
4   <meta charset="UTF-8">
5 </head>
6 <body>
7 <a name="HOWTO.WRITE.an.APPLICATION.above.AGL.FRAMEWORK"></a>
8 <h1>HOWTO WRITE an APPLICATION above AGL FRAMEWORK</h1>
9
10 <pre><code>version: 1
11 Date:    30 mai 2016
12 Author:  José Bollo
13 </code></pre>
14
15 <p><ul>
16  <li><a href="#HOWTO.WRITE.an.APPLICATION.above.AGL.FRAMEWORK">HOWTO WRITE an APPLICATION above AGL FRAMEWORK</a>
17  <ul>
18   <li><a href="#Languages.for.writing.Applications">Languages for writing Applications</a>
19   <ul>
20    <li><a href="#Writing.an.HTML5.application">Writing an HTML5 application</a></li>
21    <li><a href="#Writing.a.Qt.application">Writing a Qt application</a></li>
22    <li><a href="#Writing.a.C.application">Writing a C application</a></li>
23   </ul>
24   </li>
25   <li><a href="#Handling.sessions.within.applications">Handling sessions within applications</a>
26   <ul>
27    <li><a href="#Handling.sessions">Handling sessions</a></li>
28    <li><a href="#Exchanging.tokens">Exchanging tokens</a></li>
29    <li><a href="#Example.of.session.management">Example of session management</a>
30    <ul>
31     <li><a href="#Using.curl">Using curl</a></li>
32     <li><a href="#Using.afb-client-demo">Using afb-client-demo</a>
33 </li>
34    </ul>
35    </li>
36   </ul>
37   </li>
38   <li><a href="#Format.of.replies">Format of replies</a>
39   <ul>
40    <li><a href="#Field.jtype">Field jtype</a></li>
41    <li><a href="#Field.request">Field request</a>
42    <ul>
43     <li><a href="#Subfield.request.status">Subfield request.status</a></li>
44     <li><a href="#Subfield.request.info">Subfield request.info</a></li>
45     <li><a href="#Subfield.request.token">Subfield request.token</a></li>
46     <li><a href="#Subfield.request.uuid">Subfield request.uuid</a></li>
47     <li><a href="#Subfield.request.reqid">Subfield request.reqid</a></li>
48    </ul>
49    </li>
50    <li><a href="#Field.response">Field response</a></li>
51    <li><a href="#Template">Template</a></li>
52   </ul>
53   </li>
54  </ul>
55  </li>
56 </ul></p>
57
58 <a name="Languages.for.writing.Applications"></a>
59 <h2>Languages for writing Applications</h2>
60
61 <a name="Writing.an.HTML5.application"></a>
62 <h3>Writing an HTML5 application</h3>
63
64 <p>Developpers of HTML5 applications (client side) can easyly create
65 applications for AGL framework using their prefered
66 HTML framework.</p>
67
68 <p>Developpers can also create powerful server side plugins to improve
69 their application. This server side plugin should return the mime-type
70 application/json and can be accessed either by HTTP or by Websockets.</p>
71
72 <p>In a near future, the JSON-RPC protocol will be available together
73 with the current x-afb-json1 protocol.</p>
74
75 <p>Two examples of HTML5 applications are given:</p>
76
77 <ul>
78 <li><p><a href="https://github.com/iotbzh/afb-client">afb-client</a> a simple &ldquo;hello world&rdquo; application</p></li>
79 <li><p><a href="https://github.com/iotbzh/afm-client">afm-client</a> a simple &ldquo;Home screen&rdquo; application</p></li>
80 </ul>
81
82
83 <a name="Writing.a.Qt.application"></a>
84 <h3>Writing a Qt application</h3>
85
86 <p>Writing Qt applications is also possible because Qt offers APIs to
87 make HTTP queries and to connect using WebSockets.</p>
88
89 <p>It is even possible to write a QML application.
90 It is demontrated by the sample application token-websock:</p>
91
92 <ul>
93 <li><a href="https://github.com/iotbzh/afb-daemon/blob/master/test/token-websock.qml">token-websock</a>
94 a simple &ldquo;hello world&rdquo; application in QML</li>
95 </ul>
96
97
98 <a name="Writing.a.C.application"></a>
99 <h3>Writing a C application</h3>
100
101 <p>C applications can use the binder afb-daemon through a websocket connection.</p>
102
103 <p>The library <strong>libafbwsc</strong> is made for C clients that want
104 to connect to the afb-daemon binder.</p>
105
106 <p>The program <strong>afb-client-demo</strong> is the C program that use
107 the provided library <strong>libafbwsc</strong>.
108 Its source code is here
109 <a href="https://github.com/iotbzh/afb-daemon/blob/master/src/afb-client-demo.c">src/afb-client-demo.c</a>.</p>
110
111 <p>The current implementation use libsystemd and file descriptors.
112 This may be changed in the future to also support secure sockets
113 and being less dependant of libsystemd.</p>
114
115 <a name="Handling.sessions.within.applications"></a>
116 <h2>Handling sessions within applications</h2>
117
118 <p>Applications must be aware of the the features session and token
119 when they interact with the binder afb-daemon.</p>
120
121 <p>Applications are communicating with their binder afb-daemon using
122 a network connection or a kind of network connection (unix domain
123 socket isn&rsquo;t currently implemented but could be used in near future).
124 Also, HTTP protocol is not a connected protocol. It means that
125 the socket connection can not be used to authenticate a client.</p>
126
127 <p>For this reason, the binder should authenticate the application
128 by using a commonly shared secret named token and the identification
129 of the client named session.</p>
130
131 <p>The examples <strong>token-websock.qml</strong> and <strong>afb-client</strong> are demonstrating
132 how authentication and sessions are managed.</p>
133
134 <a name="Handling.sessions"></a>
135 <h3>Handling sessions</h3>
136
137 <p>Plugins and features of the binder need to keep track of the client
138 instances. This of importance for plugins running as service
139 because they may have to separate the data of each client.</p>
140
141 <p>For HTML5 applications, the web runtime handles the cookie of session
142 that the binder afb-daemon automatically sets.</p>
143
144 <p>In any case, the session identifier can be set using the parameters
145 <strong>uuid</strong> or <strong>x-afb-uuid</strong> in the request uri. That is understood
146 by HTTP requests and by the negociation of websockets.</p>
147
148 <a name="Exchanging.tokens"></a>
149 <h3>Exchanging tokens</h3>
150
151 <p>At start, the framework communicates a common secret to both the binder
152 and its client: the application. This initial secret is the
153 initial token.</p>
154
155 <p>For each of its client application, the binder manages a current active
156 token for the session. This authentication token can be a requirement for
157 accessing some methods.</p>
158
159 <p>The token must be passed in the request uri on HTTP or at connecting
160 websockets using the parameter <strong>token</strong> or <strong>x-afb-token</strong>.</p>
161
162 <p>To ensure security, tokens must be refreshed periodically.</p>
163
164 <a name="Example.of.session.management"></a>
165 <h3>Example of session management</h3>
166
167 <p>For the following exmples, we suppose that you launched <strong>afb-daemon</strong> like that or similar:</p>
168
169 <pre><code>$ afb-daemon --port=1234 --token=123456 [...]
170 </code></pre>
171
172 <p>with the expectation that the plugin <strong>AuthLogin</strong> is loaded.</p>
173
174 <a name="Using.curl"></a>
175 <h4>Using curl</h4>
176
177 <p>First, connects with the initial token, 123456:</p>
178
179 <pre><code>$ curl http://localhost:1234/api/auth/connect?token=123456
180 {
181   "jtype": "afb-reply",
182   "request": {
183  "status": "success",
184  "token": "0aef6841-2ddd-436d-b961-ae78da3b5c5f",
185  "uuid": "850c4594-1be1-4e9b-9fcc-38cc3e6ff015"
186   },
187   "response": {"token": "A New Token and Session Context Was Created"}
188 }
189 </code></pre>
190
191 <p>It returns an answer containing the uuid of the session, 850c4594-1be1-4e9b-9fcc-38cc3e6ff015,
192 and the refreshed token, 850c4594-1be1-4e9b-9fcc-38cc3e6ff015.</p>
193
194 <p>Let check that it is available:</p>
195
196 <pre><code>$ curl http://localhost:1234/api/auth/check?token=0aef6841-2ddd-436d-b961-ae78da3b5c5f&amp;uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015
197 {
198   "jtype": "afb-reply",
199   "request": {"status":"success"},
200   "response": {"isvalid":true}
201 }
202 </code></pre>
203
204 <p>It works! So try now to refresh the token:</p>
205
206 <pre><code>$ curl http://localhost:1234/api/auth/refresh?token=0aef6841-2ddd-436d-b961-ae78da3b5c5f&amp;uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015
207 {
208   "jtype": "afb-reply",
209   "request": {
210  "status":"success",
211  "token":"b8ec3ec3-6ffe-448c-9a6c-efda69ad7bd9"
212   },
213   "response": {"token":"Token was refreshed"}
214 }
215 </code></pre>
216
217 <p>Let now close the session:</p>
218
219 <pre><code>curl http://localhost:1234/api/auth/logout?token=b8ec3ec3-6ffe-448c-9a6c-efda69ad7bd9&amp;uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015
220 {
221   "jtype": "afb-reply",
222   "request": {"status": "success"},
223   "response": {"info":"Token and all resources are released"}
224 }
225 </code></pre>
226
227 <p>So now, checking for the uuid will be refused:</p>
228
229 <pre><code>curl http://localhost:1234/api/auth/check?token=b8ec3ec3-6ffe-448c-9a6c-efda69ad7bd9&amp;uuid=850c4594-1be1-4e9b-9fcc-38cc3e6ff015
230 {
231   "jtype": "afb-reply",
232   "request": {
233  "status": "failed",
234  "info": "invalid token's identity"
235   }
236 }
237 </code></pre>
238
239 <a name="Using.afb-client-demo"></a>
240 <h4>Using afb-client-demo</h4>
241
242 <p>Here is an example of exchange using <strong>afb-client-demo</strong>:</p>
243
244 <pre><code>$ afb-client-demo ws://localhost:1234/api?token=123456
245 auth connect
246 ON-REPLY 1:auth/connect: {"jtype":"afb-reply","request":{"status":"success",
247    "token":"63f71a29-8b52-4f9b-829f-b3028ba46b68","uuid":"5fcc3f3d-4b84-4fc7-ba66-2d8bd34ae7d1"},
248    "response":{"token":"A New Token and Session Context Was Created"}}
249 auth check
250 ON-REPLY 2:auth/check: {"jtype":"afb-reply","request":{"status":"success"},"response":{"isvalid":true}}
251 auth refresh
252 ON-REPLY 4:auth/refresh: {"jtype":"afb-reply","request":{"status":"success",
253    "token":"8b8ba8f4-1b0c-48fa-962d-4a00a8c9157e"},"response":{"token":"Token was refreshed"}}
254 auth check
255 ON-REPLY 5:auth/check: {"jtype":"afb-reply","request":{"status":"success"},"response":{"isvalid":true}}
256 auth refresh
257 ON-REPLY 6:auth/refresh: {"jtype":"afb-reply","request":{"status":"success",
258    "token":"e83b36f8-d945-463d-b983-5d8ed73ba529"},"response":{"token":"Token was refreshed"}}
259 </code></pre>
260
261 <p>Then you leave. And can reconnect as below:</p>
262
263 <pre><code>$ afb-client-demo ws://localhost:1234/api?token=e83b36f8-d945-463d-b983-5d8ed73ba529&amp;uuid=5fcc3f3d-4b84-4fc7-ba66-2d8bd34ae7d1 auth check
264 ON-REPLY 1:auth/check: {"jtype":"afb-reply","request":{"status":"success"},"response":{"isvalid":true}}
265 </code></pre>
266
267 <p>The same can be continued using <strong>curl</strong>:</p>
268
269 <pre><code>$ curl http://localhost:1234/api/auth/check?token=e83b36f8-d945-463d-b983-5d8ed73ba529&amp;uuid=5fcc3f3d-4b84-4fc7-ba66-2d8bd34ae7d1
270 {"jtype":"afb-reply","request":{"status":"success"},"response":{"isvalid":true}}
271 </code></pre>
272
273 <a name="Format.of.replies"></a>
274 <h2>Format of replies</h2>
275
276 <p>The replies are made of one javascript object returned using JSON serialization.</p>
277
278 <p>This object containts at least 2 mandatory fields of name <strong>jtype</strong> and <strong>request</strong>
279 and an optionnal field of name <strong>response</strong>.</p>
280
281 <a name="Field.jtype"></a>
282 <h3>Field jtype</h3>
283
284 <p>The field <strong>jtype</strong> must have a value of type string equel to <strong>&ldquo;afb-reply&rdquo;</strong>.</p>
285
286 <a name="Field.request"></a>
287 <h3>Field request</h3>
288
289 <p>The field <strong>request</strong> must have a value of type object. This request object
290 has at least one field named <strong>status</strong> and four optionnal fields of name
291 <strong>info</strong>, <strong>token</strong>, <strong>uuid</strong>, <strong>reqid</strong>.</p>
292
293 <a name="Subfield.request.status"></a>
294 <h4>Subfield request.status</h4>
295
296 <p><strong>status</strong> must have a value of type string. This string is equal to <strong>&ldquo;success&rdquo;</strong>
297 only in case of success.</p>
298
299 <a name="Subfield.request.info"></a>
300 <h4>Subfield request.info</h4>
301
302 <p><strong>info</strong> is of type string and represent optionnal the information added to the reply.</p>
303
304 <a name="Subfield.request.token"></a>
305 <h4>Subfield request.token</h4>
306
307 <p><strong>token</strong> is of type string. It is sent either on the creation of the
308 session or when the token is refreshed.</p>
309
310 <a name="Subfield.request.uuid"></a>
311 <h4>Subfield request.uuid</h4>
312
313 <p><strong>uuid</strong> is of type string. It is sent on the creation of the session.</p>
314
315 <a name="Subfield.request.reqid"></a>
316 <h4>Subfield request.reqid</h4>
317
318 <p><strong>reqid</strong> is of type string. It is sent in response of HTTP requests
319 that added a parameter of name <strong>reqid</strong> or <strong>x-afb-reqid</strong>. The value
320 sent in the reply is the exact value received on the request.</p>
321
322 <a name="Field.response"></a>
323 <h3>Field response</h3>
324
325 <p>This field response optionnaly containts the object returned with successful replies.</p>
326
327 <a name="Template"></a>
328 <h3>Template</h3>
329
330 <p>This is a template of replies:</p>
331
332 <pre><code>{
333   "jtype": "afb-reply",
334   "request": {
335    "status": "success",
336    "info": "informationnal text",
337    "token": "e83b36f8-d945-463d-b983-5d8ed73ba52",
338    "uuid": "5fcc3f3d-4b84-4fc7-ba66-2d8bd34ae7d1",
339    "reqid": "application-generated-id-23456"
340  },
341   "response": ....any response object....
342 }
343 </code></pre>
344 </body>
345 </html>