/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Threading.Tasks;
using Tizen.Internals.Errors;
namespace Tizen.Account.FidoClient
{
///
/// The FIDO UAF Client APIs
///
/// 3
public static class UafClient
{
private static string _vendorName = null;
private static int _majorVersion;
private static int _minorVersion;
static UafClient()
{
int ret = Interop.UafClient.FidoGetClientVendor(out _vendorName);
if (ret != (int)FidoErrorCode.None)
{
Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
throw ErrorFactory.GetException(ret);
}
ret = Interop.UafClient.FidoGetClientVersion(out _majorVersion, out _minorVersion);
if (ret != (int)FidoErrorCode.None)
{
Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
throw ErrorFactory.GetException(ret);
}
}
///
/// The FIDO Client vendor name
///
/// 3
public static string VendorName
{
get
{
return _vendorName;
}
}
///
/// The FIDO Client Major version
///
/// 3
public static int MajorVersion
{
get
{
return _majorVersion;
}
}
///
/// The FIDO Client Minor version
///
/// 3
public static int MinorVersion
{
get
{
return _minorVersion;
}
}
///
/// The FIDO Server response for successfull interaction.
///
/// 3
public static int StautsOk
{
get
{
return 1200;
}
}
///
/// Checks whether the FIDO message can be processed
///
/// 3
/// The FIDO UAF message which is received from the relying party server
/// True if the message can be handled by the device, else false
/// http://tizen.org/privilege/fido.client
/// http://tizen.org/feature/fido.uaf
/// In case of invalid parameter
/// Thrown when the application does not have privilege to access this method
/// FIDO is not supported
///
///
/// UafMessage uafRequest = new UafMessage()
/// {
/// Operation = "UafRequestJson"
/// };
/// bool response = await UafClient.CheckPolicyAsync(uafRequest);
///
///
public static async Task CheckPolicyAsync(UafMessage uafMessage)
{
if (uafMessage == null)
{
Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
throw ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter);
}
bool result = false;
await Task.Run(() => result = CheckPolicy(uafMessage.Operation));
return result;
}
///
/// Processes the given FIDO UAF message.
///
/// 3
/// The FIDO UAF message which is received from the relying party server
/// The channel binding data in JSON format which is received from the relying party server
/// FIDO response message
/// http://tizen.org/privilege/fido.client
/// http://tizen.org/feature/fido.uaf
/// In case of invalid parameter
/// Thrown when the application does not have privilege to access this method
/// FIDO is not supported
///
///
/// UafMessage uafRequest = new UafMessage()
/// {
/// Operation = "UafAuthRequestJson"
/// };
///
/// var response = await UafClient.ProcessRequestAsync(uafRequest, null);
///
///
public static async Task ProcessRequestAsync(UafMessage uafMessage, string channelBindng)
{
if (uafMessage == null)
{
Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
throw ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter);
}
TaskCompletionSource tcs = new TaskCompletionSource();
Interop.UafClient.FidoUafResponseMessageCallback cb = (int errorCode, string uafResponseJson, IntPtr userData) =>
{
if (uafMessage == null)
{
Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
tcs.SetException(ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter));
}
if (errorCode != (int)FidoErrorCode.None)
{
Log.Error(ErrorFactory.LogTag, "Interop callback failed with error code: [" + errorCode + "]");
tcs.SetException(ErrorFactory.GetException(errorCode));
}
tcs.SetResult(new UafResponse() { Response = uafResponseJson });
};
int ret = Interop.UafClient.FidoUafGetResponseMessage(uafMessage.Operation, channelBindng, cb, IntPtr.Zero);
if (ret != (int)FidoErrorCode.None)
{
Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
throw ErrorFactory.GetException(ret);
}
return await tcs.Task;
}
///
/// Notifies the FIDO client about the server result. FIDO Server sends the result of processing a UAF message to FIDO client.
///
/// 3
/// The status code received from Server.(StautsOk implies success)
/// The FIDO response message sent to server in JSON format
/// http://tizen.org/privilege/fido.client
/// http://tizen.org/feature/fido.uaf
///
/// 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
///
/// In case of invalid parameter
/// Thrown when the application does not have privilege to access this method
/// FIDO is not supported
///
///
/// UafResponse response = new UafResponse()
/// {
/// Response = "Responsejson"
/// };
///
/// await UafClient.NotifyResultAsync(UafClient.StautsOk, response);
///
///
public static async Task NotifyResultAsync(int responseCode, UafResponse response)
{
if (response == null)
{
Log.Error(ErrorFactory.LogTag, "Invalid parameter");
throw ErrorFactory.GetException((int)FidoErrorCode.InvalidParameter);
}
await Task.Run(() => NotifyResult(responseCode, response.Response));
}
private static bool CheckPolicy(string uafOperation)
{
bool isSupported;
int ret = Interop.UafClient.FidoUafIsSupported(uafOperation, out isSupported);
if (ret != (int)FidoErrorCode.None)
{
Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ret + "]");
throw ErrorFactory.GetException(ret);
}
return isSupported;
}
private static void NotifyResult(int responseCode, string response)
{
int ret = Interop.UafClient.FidoUafSetServerResult(responseCode, response);
if (ret != (int)FidoErrorCode.None)
{
Log.Error(ErrorFactory.LogTag, "Interop API failed with error code: [" + ErrorFacts.GetErrorMessage(ret) + "]");
throw ErrorFactory.GetException(ret);
}
}
}
}