examples: Add notice about using experimental API
[iotivity.git] / resource / csdk / security / provisioning / sample / cloud / cloudAuth.c
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 "ocstack.h"
23 #include "ocpayload.h"
24 #include "psinterface.h"
25 #include "doxmresource.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "pmutility.h"
29 #include "credresource.h"
30 #include "cacommonutil.h"
31 #include "utils.h"
32 #include "cloudAuth.h"
33 #include "cloudCommon.h"
34
35 /// This example is using experimental API, so there is no guarantee of support for future release,
36 /// nor any there any guarantee that breaking changes will not occur across releases.
37 #include "experimental/logger.h"
38 #include "experimental/payload_logging.h"
39 #include "experimental/securevirtualresourcetypes.h"
40
41 #define TAG "cloudAuth"
42
43 #define LOGIN_OK 4
44
45 #define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
46
47 typedef struct
48 {
49     char *accesstoken;
50     char *refreshtoken;
51     char *tokentype;
52     int64_t  expiresin;
53     char *uid;
54     char *redirecturi;
55     char *certificate;
56     char *sid;
57 } sessionObject_t;
58
59 static sessionObject_t sessionObject = {NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL};
60
61 /**
62  * Session free function
63  *
64  * @return  OCStackResult application result
65  */
66 static void SessionFree()
67 {
68     OICFree(sessionObject.accesstoken);
69     OICFree(sessionObject.refreshtoken);
70     OICFree(sessionObject.tokentype);
71     OICFree(sessionObject.uid);
72     OICFree(sessionObject.redirecturi);
73     OICFree(sessionObject.certificate);
74     OICFree(sessionObject.sid);
75
76     memset(&sessionObject, 0, sizeof(sessionObject_t));
77 }
78
79 /**
80  * Session parse payload
81  *
82  * @param[in] payload
83  * @param[in] sessionObject session data
84  * @return  OCStackResult application result
85  */
86 static OCStackResult SessionParsePayload(OCRepPayload *payload)
87 {
88     VERIFY_NON_NULL_RET(payload, TAG, "NULL payload", OC_STACK_ERROR);
89
90     SessionFree();
91
92     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
93                                    &sessionObject.accesstoken))
94     {
95         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_ACCESS_TOKEN);
96     }
97     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REFRESH_TOKEN,
98                                    &sessionObject.refreshtoken))
99     {
100         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_REFRESH_TOKEN);
101     }
102     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_TOKEN_TYPE,
103                                    &sessionObject.tokentype))
104     {
105         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_TOKEN_TYPE);
106     }
107     if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN, &(sessionObject.expiresin)))
108     {
109         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
110     }
111     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_USER_UUID,
112                                    &sessionObject.uid))
113     {
114         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_USER_UUID);
115     }
116     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REDIRECT_URI,
117                                    &sessionObject.redirecturi))
118     {
119         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_REDIRECT_URI);
120     }
121     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_CERTIFICATE,
122                                    &sessionObject.certificate))
123     {
124         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_CERTIFICATE);
125     }
126     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_SUBJECT_ID,
127                                    &sessionObject.sid))
128     {
129         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_SUBJECT_ID);
130     }
131
132     return OC_STACK_OK;
133 }
134
135 /**
136  * Sends Sign Up request to cloud
137  *
138  * @param[in] ctx                    context
139  * @param[in] handle                 handle
140  * @param[in] response               response from peer
141  * @return  OCStackApplicationResult application result
142  */
143 static OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
144                                                           OCDoHandle handle,
145                                                           OCClientResponse *response)
146 {
147     OC_UNUSED(ctx);
148     OC_UNUSED(handle);
149
150     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
151
152     if (response->payload)
153     {
154         OIC_LOG(INFO, TAG, "Payload received");
155         OIC_LOG_PAYLOAD(DEBUG, response->payload);
156     }
157
158     if (response->result != LOGIN_OK)
159     {
160         OIC_LOG_V(ERROR, TAG, "Login error: %d",response->result);
161     }
162     else
163     {
164         SessionParsePayload((OCRepPayload*)response->payload);
165         OIC_LOG(INFO, TAG, "Sign Up OK");
166     }
167
168     return OC_STACK_DELETE_TRANSACTION;
169 }
170
171 OCStackResult CloudSignUp(const OCDevAddr *endPoint,
172                           const char *authProvider,
173                           const char *authToken)
174 {
175     char uri[MAX_URI_LENGTH] = { 0 };
176
177     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
178     VERIFY_NON_NULL_RET(authProvider, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
179     VERIFY_NON_NULL_RET(authToken, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
180
181     char *deviceId = getDeviceId();
182     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
183
184     snprintf(uri, MAX_URI_LENGTH, DEFAULT_QUERY,
185              endPoint->addr, endPoint->port, OC_RSRVD_ACCOUNT_URI);
186
187     OCCallbackData cbData;
188     memset(&cbData, 0, sizeof(OCCallbackData));
189     cbData.cb = handleCloudSignUpResponse;
190     cbData.cd = unlockMenu;
191
192     OCRepPayload *payload = OCRepPayloadCreate();
193     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
194
195     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
196     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, authProvider);
197     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHCODE, authToken);
198
199     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
200                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
201 }
202
203 /**
204  * Sends Sign In request to cloud
205  *
206  * @param[in] ctx                    context
207  * @param[in] handle                 handle
208  * @param[in] response               response from peer
209  * @return  OCStackApplicationResult application result
210  */
211 static OCStackApplicationResult handleCloudSignInResponse(void *ctx,
212                                                           OCDoHandle handle,
213                                                           OCClientResponse *response)
214 {
215     OC_UNUSED(ctx);
216     OC_UNUSED(handle);
217
218     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
219
220     if (response->payload)
221     {
222         OIC_LOG(INFO, TAG, "Payload received");
223         OIC_LOG_PAYLOAD(DEBUG, response->payload);
224     }
225
226     if (response->result != LOGIN_OK)
227     {
228         OIC_LOG_V(ERROR, TAG, "Sign In error: result: %d", response->result);
229         return OC_STACK_DELETE_TRANSACTION;
230     }
231
232     sessionObject.expiresin = 0;
233     if (!OCRepPayloadGetPropInt((OCRepPayload*)response->payload, OC_RSRVD_EXPIRES_IN, &(sessionObject.expiresin)))
234     {
235         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
236     }
237
238     OIC_LOG(INFO, TAG, "Sign In OK");
239
240     return OC_STACK_DELETE_TRANSACTION;
241 }
242
243 static OCStackApplicationResult handleCloudSignOutResponse(void *ctx,
244                                                            OCDoHandle handle,
245                                                            OCClientResponse *response)
246 {
247     OC_UNUSED(ctx);
248     OC_UNUSED(handle);
249
250     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
251
252     if (response->payload)
253     {
254         OIC_LOG(INFO, TAG, "Payload received");
255         OIC_LOG_PAYLOAD(DEBUG, response->payload);
256     }
257
258     if (response->result != LOGIN_OK)
259     {
260         OIC_LOG(ERROR, TAG, "Sign Out error");
261         return OC_STACK_DELETE_TRANSACTION;
262     }
263
264     OIC_LOG(INFO, TAG, "Sign Out OK");
265
266     return OC_STACK_DELETE_TRANSACTION;
267 }
268
269 /**
270  * Sends Sign In/Out request to cloud
271  *
272  * @param[in] endPoint               peer endPoint
273  * @param[in] signIn                 is it Sign In or Sign Out request
274  * @return  OCStackApplicationResult application result
275  */
276 static OCStackResult CloudSign(const OCDevAddr *endPoint, bool signIn)
277 {
278     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
279     VERIFY_NON_NULL_RET(sessionObject.uid, TAG,
280                         "UID is missing. Please run Sign Up first", OC_STACK_ERROR);
281     VERIFY_NON_NULL_RET(sessionObject.accesstoken, TAG,
282                         "accesstoken is missing. Please run Sign Up first", OC_STACK_ERROR);
283
284     char *deviceId = getDeviceId();
285     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
286
287     OCRepPayload* payload = OCRepPayloadCreate();
288     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
289
290     OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, sessionObject.uid);
291     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
292     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN, sessionObject.accesstoken);
293     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, signIn);
294
295     char uri[MAX_URI_QUERY] = { 0 };
296     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
297              endPoint->addr, endPoint->port,
298              OC_RSRVD_ACCOUNT_SESSION_URI);
299
300     OCCallbackData cbData;
301     memset(&cbData, 0, sizeof(OCCallbackData));
302     cbData.cb = signIn? handleCloudSignInResponse : handleCloudSignOutResponse;
303     cbData.cd = unlockMenu;
304
305     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
306                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
307 }
308
309 OCStackResult CloudSignIn(const OCDevAddr *endPoint)
310 {
311     return CloudSign(endPoint, true);
312 }
313
314 OCStackResult CloudSignOut(const OCDevAddr *endPoint)
315 {
316     return CloudSign(endPoint, false);
317 }
318