7c8182c840446a5992b617a599620c43f92516c7
[iotivity.git] / resource / provisioning / examples / cloudAuth.cpp
1 /* *****************************************************************
2  *
3  * Copyright 2016 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20
21 #include "octypes.h"
22 #include "logger.h"
23 #include "payload_logging.h"
24 #include "ocstack.h"
25 #include "ocpayload.h"
26 //#include "psinterface.h"
27 #include "experimental/securevirtualresourcetypes.h"
28 #include "doxmresource.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "srmutility.h"
32 #include "pmutility.h"
33 #include "credresource.h"
34 #include "payload_logging.h"
35
36 #include "utils.h"
37 #include "cloudAuth.h"
38
39 #define TAG "cloudAuth"
40
41 #define LOGIN_OK 4
42
43 #define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
44
45 typedef struct
46 {
47     char *accesstoken;
48     char *refreshtoken;
49     char *tokentype;
50     int64_t expiresin;
51     char *uid;
52     char *redirecturi;
53     char *certificate;
54     char *sid;
55 } sessionObject_t;
56
57 static sessionObject_t sessionObject = {0,0,0,0,0,0,0,0};
58
59 extern void handleCB(void* ctx, OCClientResponse *response, void* data);
60
61 /**
62  * Session free function
63  *
64  * @return  OCStackResult application result
65  */
66 void SessionFree()
67 {
68     if (sessionObject.accesstoken)  OICFree(sessionObject.accesstoken);
69     if (sessionObject.refreshtoken) OICFree(sessionObject.refreshtoken);
70     if (sessionObject.tokentype)    OICFree(sessionObject.tokentype);
71     if (sessionObject.uid)          OICFree(sessionObject.uid);
72     if (sessionObject.redirecturi)  OICFree(sessionObject.redirecturi);
73     if (sessionObject.certificate)  OICFree(sessionObject.certificate);
74     if (sessionObject.sid)          OICFree(sessionObject.sid);
75
76     memset(&sessionObject, 0, sizeof(sessionObject_t));
77 }
78
79 /**
80  * Session init function
81  *
82  * @param[in] sessionObject session data
83  * @return  OCStackResult application result
84  */
85 OCStackResult SessionInit()
86 {
87     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
88
89     SessionFree();
90
91     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
92
93     return OC_STACK_OK;
94 }
95
96 /**
97  * Session parse payload
98  *
99  * @param[in] payload
100  * @param[in] sessionObject session data
101  * @return  OCStackResult application result
102  */
103 OCStackResult SessionParsePayload(OCRepPayload *payload)
104 {
105     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
106
107     VERIFY_NOT_NULL(TAG, payload, ERROR);
108
109     SessionInit();
110
111     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
112                                    &sessionObject.accesstoken))
113     {
114         OIC_LOG(ERROR, TAG, "Can't get: accesstoken");
115     }
116     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REFRESH_TOKEN,
117                                    &sessionObject.refreshtoken))
118     {
119         OIC_LOG(ERROR, TAG, "Can't get: refreshtoken");
120     }
121     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_TOKEN_TYPE,
122                                    &sessionObject.tokentype))
123     {
124         OIC_LOG(ERROR, TAG, "Can't get: tokentype");
125     }
126     if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN,
127                                 &(sessionObject.expiresin)))
128     {
129         OIC_LOG(ERROR, TAG, "Can't get: expiresin");
130     }
131     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_USER_UUID,
132                                    &sessionObject.uid))
133     {
134         OIC_LOG(ERROR, TAG, "Can't get: uid");
135     }
136     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REDIRECT_URI,
137                                    &sessionObject.redirecturi))
138     {
139         OIC_LOG(ERROR, TAG, "Can't get: redirecturi");
140     }
141     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_CERTIFICATE,
142                                    &sessionObject.certificate))
143     {
144         OIC_LOG(ERROR, TAG, "Can't get: certificate");
145     }
146     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_SUBJECT_ID,
147                                    &sessionObject.sid))
148     {
149         OIC_LOG(ERROR, TAG, "Can't get: sid");
150     }
151
152     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
153 exit:
154     return OC_STACK_OK;
155 }
156
157 /**
158  * Cloud login handler
159  *
160  * @param[in] response  login response
161  */
162 OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
163                                                           OCDoHandle handle,
164                                                           OCClientResponse *response)
165 {
166     OC_UNUSED(ctx);
167     OC_UNUSED(handle);
168
169     if (!response)
170     {
171         OIC_LOG(ERROR, TAG, "Received NULL response!");
172         goto exit;
173     }
174
175     if (response->payload)
176     {
177         OIC_LOG(ERROR, TAG, "Payload received");
178         OIC_LOG_PAYLOAD(DEBUG, response->payload);
179     }
180
181     if (response->result != LOGIN_OK)
182     {
183         OIC_LOG_V(ERROR, TAG, "Login error: %d",response->result);
184     }
185     else
186     {
187         OIC_LOG(DEBUG, TAG, "Login successful");
188         SessionParsePayload((OCRepPayload*)response->payload);
189     }
190     response->result = OC_STACK_OK;
191 exit:
192     handleCB(NULL, response, NULL);
193     return OC_STACK_DELETE_TRANSACTION;
194 }
195
196 /**
197  * Cloud authentication
198  *
199  * @param[in] endPoint          cloud host and port
200  * @param[in] authProvider      auth provider
201  * @param[in] authToken         token
202  * @return  OCStackResult application result
203  */
204 OCStackResult
205 CloudSignUp(OCDevAddr *endPoint,
206            const char *authProvider,
207            const char *authToken,
208            OCClientResponseHandler response)
209 {
210     char uri[MAX_URI_LENGTH] = { 0 };
211
212     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
213
214     if (!endPoint || !authProvider || !authToken)
215     {
216         OIC_LOG(ERROR, TAG, "Some of the input params are NULL");
217         return OC_STACK_INVALID_PARAM;
218     }
219
220     char *deviceId = getDeviceId();
221     if (!deviceId)
222     {
223         OIC_LOG(ERROR, TAG, "Can't get the device id");
224         return OC_STACK_ERROR;
225     }
226
227     snprintf(uri, MAX_URI_LENGTH, DEFAULT_QUERY,
228              endPoint->addr, endPoint->port, OC_RSRVD_ACCOUNT_URI);
229
230     OIC_LOG_V(DEBUG, TAG, "Query created: %s", uri);
231
232     OCCallbackData cbData;
233     memset(&cbData, 0, sizeof(OCCallbackData));
234     cbData.cb = response;
235     cbData.context = (void*)handleCloudSignUpResponse;
236
237     OCRepPayload *payload = OCRepPayloadCreate();
238     if (!payload)
239     {
240         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
241         return OC_STACK_NO_MEMORY;
242     }
243
244     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
245     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, OICStrdup(authProvider));
246     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHCODE, OICStrdup(authToken));
247
248     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
249                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
250 }
251
252 /**
253  * Cloud Sign In handler
254  *
255  * @param[in] OCClientResponse  cloud response
256  * @return  OCStackApplicationResult application result
257  */
258 OCStackApplicationResult handleCloudSignInResponse(void *ctx,
259                                                           OCDoHandle handle,
260                                                           OCClientResponse *response)
261 {
262     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
263
264     OC_UNUSED(ctx);
265     OC_UNUSED(handle);
266
267     if (!response)
268     {
269         OIC_LOG(ERROR, TAG, "Received NULL response!");
270         goto exit;
271     }
272
273     if (response->payload)
274     {
275         OIC_LOG(ERROR, TAG, "Payload received");
276         OIC_LOG_PAYLOAD(DEBUG, response->payload);
277     }
278
279     if (response->result < 4 && response->payload)
280     {
281         OIC_LOG_V(ERROR, TAG, "Sign In error: result: %d, payload exist: %s",
282                   response->result, response->payload ? "yes" : "no");
283         goto exit;
284     }
285
286     if (!OCRepPayloadGetPropString((OCRepPayload*)response->payload, OC_RSRVD_USER_UUID,
287                                    &(sessionObject.uid)))
288     {
289         OIC_LOG(ERROR, TAG, "Can't get: uid");
290     }
291
292     if (!OCRepPayloadGetPropInt((OCRepPayload*)response->payload, OC_RSRVD_EXPIRES_IN,
293                                 &(sessionObject.expiresin)))
294     {
295         OIC_LOG(ERROR, TAG, "Cann't get: expiresin");
296     }
297
298     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
299     response->result = OC_STACK_OK;
300
301 exit:
302     handleCB(NULL, response, NULL);
303     return OC_STACK_DELETE_TRANSACTION;
304 }
305
306 /**
307  * Sign In request function
308  *
309  * @param[in] endPoint          cloud host and port
310  * @return  OCStackResult application result
311  */
312 OCStackResult CloudSignIn(OCDevAddr  *endPoint, OCClientResponseHandler response)
313 {
314     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
315
316     if (!endPoint)
317     {
318         OIC_LOG_V(ERROR, TAG, "%s: endPoint is NULL",__func__);
319         return OC_STACK_INVALID_PARAM;
320     }
321
322     if (!sessionObject.uid)
323     {
324         OIC_LOG_V(ERROR, TAG, "%s: UID is missing. Please run Sign Up first",__func__);
325         return OC_STACK_ERROR;
326     }
327
328     if (!sessionObject.accesstoken)
329     {
330         OIC_LOG_V(ERROR, TAG, "%s: accesstoken is missing. Please run Sign Up first",__func__);
331         return OC_STACK_ERROR;
332     }
333
334     char *deviceId = getDeviceId();
335     if (!deviceId)
336     {
337         OIC_LOG(ERROR, TAG, "Can't get the device id");
338         return OC_STACK_ERROR;
339     }
340
341     OCRepPayload* payload = OCRepPayloadCreate();
342     if (NULL == payload)
343     {
344         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
345         return OC_STACK_NO_MEMORY;
346     }
347
348     OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, sessionObject.uid);
349     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
350     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
351                               sessionObject.accesstoken);
352     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, true);
353
354     char uri[MAX_URI_QUERY] = { 0, };
355     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
356              endPoint->addr, endPoint->port,
357              OC_RSRVD_ACCOUNT_SESSION_URI);
358
359     OCCallbackData cbData;
360     memset(&cbData, 0, sizeof(OCCallbackData));
361     cbData.cb = response;
362     cbData.context = (void*)handleCloudSignInResponse;
363
364     return OCDoResource(NULL, OC_REST_POST, uri, NULL,
365                        (OCPayload *)payload,
366                        CT_ADAPTER_TCP,
367                        OC_LOW_QOS, &cbData, NULL, 0);
368 }
369 /**
370  * Cloud Sign Out handler
371  *
372  * @param[in] OCClientResponse  cloud response
373  * @return  OCStackApplicationResult application result
374  */
375 OCStackApplicationResult handleCloudSignOutResponse(void *ctx,
376                                                           OCDoHandle handle,
377                                                           OCClientResponse *response)
378 {
379     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
380
381     OC_UNUSED(ctx);
382     OC_UNUSED(handle);
383
384     if (!response)
385     {
386         OIC_LOG(ERROR, TAG, "Received NULL response!");
387         goto exit;
388     }
389
390     if (response->payload)
391     {
392         OIC_LOG(ERROR, TAG, "Payload received");
393         OIC_LOG_PAYLOAD(DEBUG, response->payload);
394     }
395
396     if (response->result < 4 && response->payload)
397     {
398         OIC_LOG_V(ERROR, TAG, "Sign Out error");
399         return OC_STACK_DELETE_TRANSACTION;
400     }
401     else
402     {
403         OIC_LOG_V(ERROR, TAG, "Sign Out OK");
404     }
405
406     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
407     response->result = OC_STACK_OK;
408
409 exit:
410     handleCB(NULL, response, NULL);
411     return OC_STACK_DELETE_TRANSACTION;
412 }
413 /**
414  * Sign In request function
415  *
416  * @param[in] endPoint          cloud host and port
417  * @return  OCStackResult application result
418  */
419 OCStackResult CloudSignOut(OCDevAddr  *endPoint, OCClientResponseHandler response)
420 {
421     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
422
423     if (!endPoint)
424     {
425         OIC_LOG_V(ERROR, TAG, "%s: endPoint is NULL",__func__);
426         return OC_STACK_INVALID_PARAM;
427     }
428
429     char *deviceId = getDeviceId();
430     if (!deviceId)
431     {
432         OIC_LOG(ERROR, TAG, "Cann't get the device id");
433         return OC_STACK_ERROR;
434     }
435
436     OCRepPayload* payload = OCRepPayloadCreate();
437     if (!payload)
438     {
439         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
440         return OC_STACK_NO_MEMORY;
441     }
442
443     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
444     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
445                               sessionObject.accesstoken);
446     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, false);
447
448     char uri[MAX_URI_QUERY] = { 0, };
449     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
450              endPoint->addr, endPoint->port,
451              OC_RSRVD_ACCOUNT_SESSION_URI);
452
453     OCCallbackData cbData;
454     memset(&cbData, 0, sizeof(OCCallbackData));
455     cbData.cb = response;
456     cbData.context = (void*)handleCloudSignOutResponse;
457
458     return OCDoResource(NULL, OC_REST_POST, uri, NULL,
459                        (OCPayload *)payload,
460                        CT_ADAPTER_TCP,
461                        OC_LOW_QOS, &cbData, NULL, 0);
462 }
463