Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Account.FidoClient / Tizen.Account.FidoClient / UafClient.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Threading.Tasks;
19 using Tizen.Internals.Errors;
20
21 namespace Tizen.Account.FidoClient
22 {
23     /// <summary>
24     /// The FIDO UAF Client APIs
25     /// </summary>
26     /// <since_tizen> 3 </since_tizen>
27     public static class UafClient
28     {
29         private static string _vendorName = null;
30         private static int _majorVersion;
31         private static int _minorVersion;
32
33         static UafClient()
34         {
35             int ret = Interop.UafClient.FidoGetClientVendor(out _vendorName);
36             if (ret != (int)FidoErrorCode.None)
37             {
38                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
39                 throw ErrorFactory.GetException(ret);
40             }
41
42             ret = Interop.UafClient.FidoGetClientVersion(out _majorVersion, out _minorVersion);
43             if (ret != (int)FidoErrorCode.None)
44             {
45                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
46                 throw ErrorFactory.GetException(ret);
47             }
48         }
49
50         /// <summary>
51         /// The FIDO Client vendor name
52         /// </summary>
53         /// <since_tizen> 3 </since_tizen>
54         public static string VendorName
55         {
56             get
57             {
58                 return _vendorName;
59             }
60         }
61
62         /// <summary>
63         /// The FIDO Client Major version
64         /// </summary>
65         /// <since_tizen> 3 </since_tizen>
66         public static int MajorVersion
67         {
68             get
69             {
70                 return _majorVersion;
71             }
72         }
73
74         /// <summary>
75         /// The FIDO Client Minor version
76         /// </summary>
77         /// <since_tizen> 3 </since_tizen>
78         public static int MinorVersion
79         {
80             get
81             {
82                 return _minorVersion;
83             }
84         }
85
86         /// <summary>
87         /// The FIDO Server response for successfull interaction.
88         /// </summary>
89         /// <since_tizen> 3 </since_tizen>
90         public static int StautsOk
91         {
92             get
93             {
94                 return 1200;
95             }
96         }
97
98         /// <summary>
99         /// Checks whether the FIDO message can be processed
100         /// </summary>
101         /// <since_tizen> 3 </since_tizen>
102         /// <param name="uafMessage">The FIDO UAF message which is received from the relying party server</param>
103         /// <returns>True if the message can be handled by the device, else false</returns>
104         /// <privilege>http://tizen.org/privilege/fido.client</privilege>
105         /// <feature>http://tizen.org/feature/fido.uaf</feature>
106         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
107         /// <exception cref="UnauthorizedAccessException">Thrown when the application does not have privilege to access this method</exception>
108         /// <exception cref="NotSupportedException">FIDO is not supported</exception>
109         /// <example>
110         /// <code>
111         ///     UafMessage uafRequest = new UafMessage()
112         ///     {
113         ///         Operation = "UafRequestJson"
114         ///     };
115         ///     bool response = await UafClient.CheckPolicyAsync(uafRequest);
116         /// </code>
117         /// </example>
118         public static async Task<bool> CheckPolicyAsync(UafMessage uafMessage)
119         {
120             if (uafMessage == null)
121             {
122                 Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
123                 throw ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter);
124             }
125
126             bool result = false;
127             await Task.Run(() => result = CheckPolicy(uafMessage.Operation));
128             return result;
129         }
130
131         /// <summary>
132         /// Processes the given FIDO UAF message.
133         /// </summary>
134         /// <since_tizen> 3 </since_tizen>
135         /// <param name="uafMessage">The FIDO UAF message which is received from the relying party server</param>
136         /// <param name="channelBindng">The channel binding data in JSON format which is received from the relying party server</param>
137         /// <returns>FIDO response message</returns>
138         /// <privilege>http://tizen.org/privilege/fido.client</privilege>
139         /// <feature>http://tizen.org/feature/fido.uaf</feature>
140         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
141         /// <exception cref="UnauthorizedAccessException">Thrown when the application does not have privilege to access this method</exception>
142         /// <exception cref="NotSupportedException">FIDO is not supported</exception>
143         /// <example>
144         /// <code>
145         ///     UafMessage uafRequest = new UafMessage()
146         ///     {
147         ///         Operation = "UafAuthRequestJson"
148         ///     };
149         ///
150         ///     var response = await UafClient.ProcessRequestAsync(uafRequest, null);
151         /// </code>
152         /// </example>
153         public static async Task<UafResponse> ProcessRequestAsync(UafMessage uafMessage, string channelBindng)
154         {
155             if (uafMessage == null)
156             {
157                 Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
158                 throw ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter);
159             }
160
161             TaskCompletionSource<UafResponse> tcs = new TaskCompletionSource<UafResponse>();
162             Interop.UafClient.FidoUafResponseMessageCallback cb = (int errorCode, string uafResponseJson, IntPtr userData) =>
163             {
164                 if (uafMessage == null)
165                 {
166                     Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
167                     tcs.SetException(ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter));
168                 }
169
170                 if (errorCode != (int)FidoErrorCode.None)
171                 {
172                     Log.Error(ErrorFactory.LogTag, "Interop callback failed with error code: [" + errorCode + "]");
173                     tcs.SetException(ErrorFactory.GetException(errorCode));
174                 }
175
176                 tcs.SetResult(new UafResponse() { Response = uafResponseJson });
177             };
178
179             int ret = Interop.UafClient.FidoUafGetResponseMessage(uafMessage.Operation, channelBindng, cb, IntPtr.Zero);
180             if (ret != (int)FidoErrorCode.None)
181             {
182                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
183                 throw ErrorFactory.GetException(ret);
184             }
185
186             return await tcs.Task;
187         }
188
189         /// <summary>
190         /// Notifies the FIDO client about the server result. FIDO Server sends the result of processing a UAF message to FIDO client.
191         /// </summary>
192         /// <since_tizen> 3 </since_tizen>
193         /// <param name="responseCode">The status code received from Server.(StautsOk implies success)</param>
194         /// <param name="response">The FIDO response message sent to server in JSON format</param>
195         /// <privilege>http://tizen.org/privilege/fido.client</privilege>
196         /// <feature>http://tizen.org/feature/fido.uaf</feature>
197         /// <remarks>
198         /// This is especially important for cases when a new registration may be considered by the client to be in a pending state until it is communicated that the server accepted it
199         /// </remarks>
200         /// <exception cref="ArgumentException"> In case of invalid parameter</exception>
201         /// <exception cref="UnauthorizedAccessException">Thrown when the application does not have privilege to access this method</exception>
202         /// <exception cref="NotSupportedException">FIDO is not supported</exception>
203         /// <example>
204         /// <code>
205         ///     UafResponse response = new UafResponse()
206         ///     {
207         ///         Response = "Responsejson"
208         ///     };
209         ///
210         ///     await UafClient.NotifyResultAsync(UafClient.StautsOk, response);
211         /// </code>
212         /// </example>
213         public static async Task NotifyResultAsync(int responseCode, UafResponse response)
214         {
215             if (response == null)
216             {
217                 Log.Error(ErrorFactory.LogTag, "Invalid parameter");
218                 throw ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter);
219             }
220
221             await Task.Run(() => NotifyResult(responseCode, response.Response));
222         }
223
224         private static bool CheckPolicy(string uafOperation)
225         {
226             bool isSupported;
227             int ret = Interop.UafClient.FidoUafIsSupported(uafOperation, out isSupported);
228             if (ret != (int)FidoErrorCode.None)
229             {
230                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
231                 throw ErrorFactory.GetException(ret);
232             }
233             return isSupported;
234         }
235
236         private static void NotifyResult(int responseCode, string response)
237         {
238             int ret = Interop.UafClient.FidoUafSetServerResult(responseCode, response);
239             if (ret != (int)FidoErrorCode.None)
240             {
241                 Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ErrorFacts.GetErrorMessage(ret) + "]");
242                 throw ErrorFactory.GetException(ret);
243             }
244         }
245
246     }
247 }