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