From 47cc60b427ad84e1e7986a84a62e8b2d8877936f Mon Sep 17 00:00:00 2001 From: jkjo92 Date: Wed, 7 Dec 2016 19:16:48 +0900 Subject: [PATCH] sync from spin dotnet branch Change-Id: I75a73324eff219cd52fe27dfb8c83c7a95467999 --- LICENSE | 202 +++++++++++ packaging/csapi-account-oauth2.manifest | 5 + packaging/csapi-account-oauth2.spec | 76 ++++ src/Tizen.Account.OAuth2/Interop/Interop.Common.cs | 55 +++ src/Tizen.Account.OAuth2/Interop/Interop.Error.cs | 44 +++ .../Interop/Interop.Libraries.cs | 28 ++ .../Interop/Interop.Manager.cs | 69 ++++ .../Interop/Interop.Request.cs | 129 +++++++ .../Interop/Interop.Response.cs | 62 ++++ src/Tizen.Account.OAuth2/Interop/Interop.Types.cs | 38 ++ .../Properties/AssemblyInfo.cs | 36 ++ .../Tizen.Account.OAuth2.Net45.csproj | 90 +++++ .../Tizen.Account.OAuth2.Net45.project.json | 11 + .../Tizen.Account.OAuth2.csproj | 132 +++++++ .../Tizen.Account.OAuth2.nuspec | 16 + .../Tizen.Account.OAuth2.project.json | 17 + src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.snk | Bin 0 -> 596 bytes .../Tizen.Account.OAuth2/AccessToken.cs | 50 +++ .../Tizen.Account.OAuth2/AuthenticationScheme.cs | 41 +++ .../Tizen.Account.OAuth2/AuthorizationRequest.cs | 67 ++++ .../Tizen.Account.OAuth2/AuthorizationResponse.cs | 95 +++++ .../Tizen.Account.OAuth2/Authorizer.cs | 385 +++++++++++++++++++++ .../Tizen.Account.OAuth2/ClientCredentials.cs | 45 +++ .../ClientCredentialsAuthorizer.cs | 163 +++++++++ .../ClientCredentialsTokenRequest.cs | 39 +++ .../CodeGrantAuthorizationRequest.cs | 38 ++ .../Tizen.Account.OAuth2/CodeGrantAuthorizer.cs | 337 ++++++++++++++++++ .../Tizen.Account.OAuth2/CodeGrantTokenRequest.cs | 44 +++ .../ImplicitGrantAuthorizationRequest.cs | 37 ++ .../ImplicitGrantAuthorizer.cs | 241 +++++++++++++ .../Tizen.Account.OAuth2/OAuth2ErrorFactory.cs | 127 +++++++ .../Tizen.Account.OAuth2/OAuth2ErrorResponse.cs | 66 ++++ .../Tizen.Account.OAuth2/RefreshToken.cs | 34 ++ .../Tizen.Account.OAuth2/RefreshTokenRequest.cs | 42 +++ .../ResourceOwnerPwdCredentialsAuthorizer.cs | 178 ++++++++++ .../ResourceOwnerPwdCredentialsTokenRequest.cs | 47 +++ .../Tizen.Account.OAuth2/TokenRequest.cs | 67 ++++ .../Tizen.Account.OAuth2/TokenResponse.cs | 103 ++++++ 38 files changed, 3256 insertions(+) create mode 100644 LICENSE create mode 100755 packaging/csapi-account-oauth2.manifest create mode 100644 packaging/csapi-account-oauth2.spec create mode 100644 src/Tizen.Account.OAuth2/Interop/Interop.Common.cs create mode 100644 src/Tizen.Account.OAuth2/Interop/Interop.Error.cs create mode 100644 src/Tizen.Account.OAuth2/Interop/Interop.Libraries.cs create mode 100644 src/Tizen.Account.OAuth2/Interop/Interop.Manager.cs create mode 100644 src/Tizen.Account.OAuth2/Interop/Interop.Request.cs create mode 100644 src/Tizen.Account.OAuth2/Interop/Interop.Response.cs create mode 100644 src/Tizen.Account.OAuth2/Interop/Interop.Types.cs create mode 100644 src/Tizen.Account.OAuth2/Properties/AssemblyInfo.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.csproj create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.project.json create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.csproj create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.nuspec create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.project.json create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.snk create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AccessToken.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthenticationScheme.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationResponse.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/Authorizer.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentials.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsAuthorizer.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsTokenRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizationRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizer.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantTokenRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizationRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizer.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorFactory.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorResponse.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshToken.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshTokenRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsAuthorizer.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsTokenRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenRequest.cs create mode 100644 src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenResponse.cs diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/packaging/csapi-account-oauth2.manifest b/packaging/csapi-account-oauth2.manifest new file mode 100755 index 0000000..75b0fa5 --- /dev/null +++ b/packaging/csapi-account-oauth2.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/csapi-account-oauth2.spec b/packaging/csapi-account-oauth2.spec new file mode 100644 index 0000000..6e19b86 --- /dev/null +++ b/packaging/csapi-account-oauth2.spec @@ -0,0 +1,76 @@ +%{!?dotnet_assembly_path: %define dotnet_assembly_path /opt/usr/share/dotnet.tizen/framework} + +%if 0%{?tizen_build_devel_mode} +%define BUILDCONF Debug +%else +%define BUILDCONF Release +%endif + +Name: csapi-account-oauth2 +Summary: OAuth2.0 C# API for Tizen +Version: 1.0.1 +Release: 1 +Group: Development/Libraries +License: Apache-2.0 +URL: https://www.tizen.org +Source0: %{name}-%{version}.tar.gz +Source1: %{name}.manifest + +AutoReqProv: no + +BuildRequires: mono-compiler +BuildRequires: mono-devel + +BuildRequires: dotnet-build-tools + +# NuGet for Dependencies +BuildRequires: csapi-tizen-nuget + + +%description +OAuth2.0 C# API for Tizen + +%prep +%setup -q +cp %{SOURCE1} . + +%define Assemblies Tizen.Account.OAuth2 + +%build +for ASM in %{Assemblies}; do +# NuGet Restore +find $ASM/*.project.json -exec nuget restore {} \; +# Build +find $ASM/*.csproj -exec xbuild {} /p:Configuration=%{BUILDCONF} \; +# NuGet Pack +nuget pack $ASM/$ASM.nuspec -Version %{version} -Properties Configuration=%{BUILDCONF} +done + +%install +# Runtime Binary +mkdir -p %{buildroot}%{dotnet_assembly_path} +for ASM in %{Assemblies}; do +%if 0%{?_with_corefx} + install -p -m 644 $ASM/bin/%{BUILDCONF}/$ASM.dll %{buildroot}%{dotnet_assembly_path} +%else + install -p -m 644 $ASM/bin/%{BUILDCONF}/Net45/$ASM.dll %{buildroot}%{dotnet_assembly_path} +%endif +done +# NuGet +mkdir -p %{buildroot}/nuget +install -p -m 644 *.nupkg %{buildroot}/nuget + +%files +%manifest %{name}.manifest +%license LICENSE +%attr(644,root,root) %{dotnet_assembly_path}/*.dll + +%package nuget +Summary: NuGet package for %{name} +Group: Development/Libraries + +%description nuget +NuGet package for %{name} + +%files nuget +/nuget/*.nupkg diff --git a/src/Tizen.Account.OAuth2/Interop/Interop.Common.cs b/src/Tizen.Account.OAuth2/Interop/Interop.Common.cs new file mode 100644 index 0000000..b16906f --- /dev/null +++ b/src/Tizen.Account.OAuth2/Interop/Interop.Common.cs @@ -0,0 +1,55 @@ +/* + * 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.Runtime.InteropServices; + +/// +/// Contains Interop declarations of OAuth2 classes. +/// +internal static partial class Interop +{ + /// + /// Safehandle wrapper for OAuth2 native handles. + /// + internal abstract class SafeOauth2Handle : SafeHandle + { + public SafeOauth2Handle() : base(IntPtr.Zero, true) + { + } + + public SafeOauth2Handle(IntPtr handle) : base(handle, true) + { + } + + public override bool IsInvalid + { + get + { + return handle == IntPtr.Zero; + } + } + + public abstract void Destroy(); + + protected override bool ReleaseHandle() + { + Destroy(); + SetHandle(IntPtr.Zero); + return true; + } + } +} diff --git a/src/Tizen.Account.OAuth2/Interop/Interop.Error.cs b/src/Tizen.Account.OAuth2/Interop/Interop.Error.cs new file mode 100644 index 0000000..de77168 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Interop/Interop.Error.cs @@ -0,0 +1,44 @@ +/* + * 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.Runtime.InteropServices; + +/// +/// Contains Interop declarations of OAuth2 classes. +/// +internal static partial class Interop +{ + /// + /// Wrapper class for OAuth2 native API. + /// + internal static partial class Error + { + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_error_get_code")] + internal static extern int GetCode(IntPtr /* oauth2_error_h */ handle, out int serverErrorCode, out int platformErrorCode); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_error_get_description")] + internal static extern int GetDescription(IntPtr /* oauth2_error_h */ handle, out string description); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_error_get_uri")] + internal static extern int GetUri(IntPtr /* oauth2_error_h */ handle, out string uri); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_error_get_custom_data")] + internal static extern int GetCustomData(IntPtr /* oauth2_error_h */ handle, string customKey, out string customValue); + + + } +} diff --git a/src/Tizen.Account.OAuth2/Interop/Interop.Libraries.cs b/src/Tizen.Account.OAuth2/Interop/Interop.Libraries.cs new file mode 100644 index 0000000..b446467 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Interop/Interop.Libraries.cs @@ -0,0 +1,28 @@ +/* + * 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. + */ + +internal static partial class Interop +{ + /// + /// Wrapper class for maintaining names of dependent native libraries. + /// + internal static partial class Libraries + { + public const string OAuth2 = "liboauth2.so.0"; + public const string Glib = "libglib-2.0.so.0"; + public const string Libc = "libc.so.6"; + } +} diff --git a/src/Tizen.Account.OAuth2/Interop/Interop.Manager.cs b/src/Tizen.Account.OAuth2/Interop/Interop.Manager.cs new file mode 100644 index 0000000..d439778 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Interop/Interop.Manager.cs @@ -0,0 +1,69 @@ +/* + * 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.Runtime.InteropServices; + +/// +/// Contains Interop declarations of OAuth2 classes. +/// +internal static partial class Interop +{ + /// + /// Wrapper class for OAuth2 native API. + /// + internal static partial class Manager + { + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate void Oauth2TokenCallback(IntPtr /* oauth2_response_h */ response, IntPtr /* void */ userData); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate void Oauth2AuthGrantCallback(IntPtr /* oauth2_response_h */ response, IntPtr /* void */ userData); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate void Oauth2AccessTokenCallback(IntPtr /* oauth2_response_h */ response, IntPtr /* void */ userData); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate void Oauth2RefreshTokenCallback(IntPtr /* oauth2_response_h */ response, IntPtr /* void */ userData); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_create")] + internal static extern int Create(out IntPtr /* oauth2_manager_h */ handle); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_destroy")] + internal static extern int Destroy(IntPtr /* oauth2_manager_h */ handle); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_request_token")] + internal static extern int RequestToken(IntPtr /* oauth2_manager_h */ handle, IntPtr /* oauth2_request_h */ request, Oauth2TokenCallback callback, IntPtr /* void */ userData); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_request_authorization_grant")] + internal static extern int RequestAuthorizationGrant(IntPtr /* oauth2_manager_h */ handle, IntPtr /* oauth2_request_h */ request, Oauth2AuthGrantCallback callback, IntPtr /* void */ userData); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_request_access_token")] + internal static extern int RequestAccessToken(IntPtr /* oauth2_manager_h */ handle, IntPtr /* oauth2_request_h */ request, Oauth2AccessTokenCallback callback, IntPtr /* void */ userData); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_refresh_access_token")] + internal static extern int RefreshAccessToken(IntPtr /* oauth2_manager_h */ handle, IntPtr /* oauth2_request_h */ request, Oauth2RefreshTokenCallback callback, IntPtr /* void */ userData); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_is_request_in_progress")] + internal static extern bool IsRequestInProgress(IntPtr /* oauth2_manager_h */ handle); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_clear_cookies")] + internal static extern int ClearCookies(IntPtr /* oauth2_manager_h */ handle); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_manager_clear_cache")] + internal static extern int ClearCache(IntPtr /* oauth2_manager_h */ handle); + } +} diff --git a/src/Tizen.Account.OAuth2/Interop/Interop.Request.cs b/src/Tizen.Account.OAuth2/Interop/Interop.Request.cs new file mode 100644 index 0000000..c76dba0 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Interop/Interop.Request.cs @@ -0,0 +1,129 @@ +/* + * 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.Runtime.InteropServices; + +/// +/// Contains Interop declarations of OAuth2 classes. +/// +internal static partial class Interop +{ + /// + /// Wrapper class for OAuth2 native API. + /// + internal static partial class Request + { + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_create")] + internal static extern int Create(out IntPtr /* oauth2_request_h */ handle); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_destroy")] + internal static extern int Destroy(IntPtr /* oauth2_request_h */ handle); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_auth_end_point_url")] + internal static extern int SetAuthEndPointUrl(IntPtr /* oauth2_request_h */ handle, string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_token_end_point_url")] + internal static extern int SetTokenEndPointUrl(IntPtr /* oauth2_request_h */ handle, string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_redirection_url")] + internal static extern int SetRedirectionUrl(IntPtr /* oauth2_request_h */ handle, string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_refresh_token_url")] + internal static extern int SetRefreshTokenUrl(IntPtr /* oauth2_request_h */ handle, string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_refresh_token")] + internal static extern int SetRefreshToken(IntPtr /* oauth2_request_h */ handle, string refreshToken); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_response_type")] + internal static extern int SetResponseType(IntPtr /* oauth2_request_h */ handle, ResponseType /* oauth2_response_type_e */ responseType); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_client_id")] + internal static extern int SetClientId(IntPtr /* oauth2_request_h */ handle, string clientId); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_client_secret")] + internal static extern int SetClientSecret(IntPtr /* oauth2_request_h */ handle, string clientSecret); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_client_authentication_type")] + internal static extern int SetClientAuthenticationType(IntPtr /* oauth2_request_h */ handle, int /* oauth2_client_authentication_type_e */ clientAuthType); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_scope")] + internal static extern int SetScope(IntPtr /* oauth2_request_h */ handle, string scope); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_state")] + internal static extern int SetState(IntPtr /* oauth2_request_h */ handle, string state); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_grant_type")] + internal static extern int SetGrantType(IntPtr /* oauth2_request_h */ handle, GrantType /* oauth2_grant_type_e */ grantType); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_authorization_code")] + internal static extern int SetAuthorizationCode(IntPtr /* oauth2_request_h */ handle, string code); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_user_name")] + internal static extern int SetUserName(IntPtr /* oauth2_request_h */ handle, string userName); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_set_password")] + internal static extern int SetPassword(IntPtr /* oauth2_request_h */ handle, string password); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_add_custom_data")] + internal static extern int AddCustomData(IntPtr /* oauth2_request_h */ handle, string key, string value); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_auth_end_point_url")] + internal static extern int GetAuthEndPointUrl(IntPtr /* oauth2_request_h */ handle, out string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_token_end_point_url")] + internal static extern int GetTokenEndPointUrl(IntPtr /* oauth2_request_h */ handle, out string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_redirection_url")] + internal static extern int GetRedirectionUrl(IntPtr /* oauth2_request_h */ handle, out string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_refresh_token_url")] + internal static extern int GetRefreshTokenUrl(IntPtr /* oauth2_request_h */ handle, out string url); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_refresh_token")] + internal static extern int GetRefreshToken(IntPtr /* oauth2_request_h */ handle, out string refreshToken); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_response_type")] + internal static extern int GetResponseType(IntPtr /* oauth2_request_h */ handle, out ResponseType /* oauth2_response_type_e */ responseType); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_client_id")] + internal static extern int GetClientId(IntPtr /* oauth2_request_h */ handle, out string clientId); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_client_secret")] + internal static extern int GetClientSecret(IntPtr /* oauth2_request_h */ handle, out string clientSecret); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_scope")] + internal static extern int GetScope(IntPtr /* oauth2_request_h */ handle, out string scope); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_state")] + internal static extern int GetState(IntPtr /* oauth2_request_h */ handle, out string state); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_grant_type")] + internal static extern int GetGrantType(IntPtr /* oauth2_request_h */ handle, out GrantType /* oauth2_grant_type_e */ grantType); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_authorization_code")] + internal static extern int GetAuthorizationCode(IntPtr /* oauth2_request_h */ handle, out string code); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_user_name")] + internal static extern int GetUserName(IntPtr /* oauth2_request_h */ handle, out string userName); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_password")] + internal static extern int GetPassword(IntPtr /* oauth2_request_h */ handle, out string password); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_request_get_custom_data")] + internal static extern int GetCustomData(IntPtr /* oauth2_request_h */ handle, string customKey, out string customValue); + } +} diff --git a/src/Tizen.Account.OAuth2/Interop/Interop.Response.cs b/src/Tizen.Account.OAuth2/Interop/Interop.Response.cs new file mode 100644 index 0000000..6131414 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Interop/Interop.Response.cs @@ -0,0 +1,62 @@ +/* + * 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.Runtime.InteropServices; + +/// +/// Contains Interop declarations of OAuth2 classes. +/// +internal static partial class Interop +{ + /// + /// Wrapper class for OAuth2 native API. + /// + internal static partial class Response + { + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_destroy")] + internal static extern int Destroy(IntPtr /* oauth2_response_h */ handle); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_authorization_code")] + internal static extern int GetAuthorizationCode(IntPtr /* oauth2_response_h */ handle, out IntPtr code); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_state")] + internal static extern int GetState(IntPtr /* oauth2_response_h */ handle, out IntPtr state); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_access_token")] + internal static extern int GetAccessToken(IntPtr /* oauth2_response_h */ handle, out IntPtr accessToken); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_token_type")] + internal static extern int GetTokenType(IntPtr /* oauth2_response_h */ handle, out IntPtr tokenType); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_expires_in")] + internal static extern int GetExpiresIn(IntPtr /* oauth2_response_h */ handle, out long expiresIn); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_refresh_token")] + internal static extern int GetRefreshToken(IntPtr /* oauth2_response_h */ handle, out IntPtr refreshToken); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_scope")] + internal static extern int GetScope(IntPtr /* oauth2_response_h */ handle, out IntPtr scope); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_error")] + internal static extern int GetError(IntPtr /* oauth2_response_h */ handle, out IntPtr /* oauth2_error_h */ error); + + [DllImport(Libraries.OAuth2, EntryPoint = "oauth2_response_get_custom_data")] + internal static extern int GetCustomData(IntPtr /* oauth2_response_h */ handle, string customKey, out IntPtr customValue); + + + } +} diff --git a/src/Tizen.Account.OAuth2/Interop/Interop.Types.cs b/src/Tizen.Account.OAuth2/Interop/Interop.Types.cs new file mode 100644 index 0000000..27bf2cb --- /dev/null +++ b/src/Tizen.Account.OAuth2/Interop/Interop.Types.cs @@ -0,0 +1,38 @@ +/* + * 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.Runtime.InteropServices; + +/// +/// Contains Interop declarations of OAuth2 classes. +/// +internal static partial class Interop +{ + internal enum GrantType + { + AuthCode, // OAUTH2_GRANT_TYPE_AUTH_CODE + Password, // OAUTH2_GRANT_TYPE_PASSWORD + ClientCredentials, // OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS + Refresh, // OAUTH2_GRANT_TYPE_REFRESH + } + + internal enum ResponseType + { + Code, // OAUTH2_RESPONSE_TYPE_CODE + Token, // OAUTH2_RESPONSE_TYPE_TOKEN + } +} diff --git a/src/Tizen.Account.OAuth2/Properties/AssemblyInfo.cs b/src/Tizen.Account.OAuth2/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7b80571 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tizen.Account.OAuth2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tizen.Account.OAuth2")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("dde83913-af4e-4998-ada7-6cba479e9709")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.csproj b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.csproj new file mode 100644 index 0000000..468ab68 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.csproj @@ -0,0 +1,90 @@ + + + + + Debug + AnyCPU + {0C39B094-8819-4005-A1D3-D4A89E741CDA} + Library + Properties + Tizen.Account.OAuth2 + Tizen.Account.OAuth2 + v4.5 + 512 + + + true + full + false + bin\Debug\Net45\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\Net45\ + TRACE + prompt + 4 + + + true + + + Tizen.Account.OAuth2.snk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.project.json b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.project.json new file mode 100644 index 0000000..2404dfb --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.Net45.project.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "Tizen": "1.0.0" + }, + "frameworks": { + "net45": {} + }, + "runtimes": { + "win": {} + } +} \ No newline at end of file diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.csproj b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.csproj new file mode 100644 index 0000000..526aa1c --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.csproj @@ -0,0 +1,132 @@ + + + + 14.0 + Debug + AnyCPU + 8.0.30703 + 2.0 + {DDE83913-AF4E-4998-ADA7-6CBA479E9709} + Library + Properties + Tizen.Account.OAuth2 + Tizen.Account.OAuth2 + 512 + en-US + + + .NETStandard + v1.6 + .NETStandard,Version=v1.6 + .NETStandard,Version=v1.6 + false + true + $(NoWarn);1701 + false + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + + + Tizen.Account.OAuth2.snk + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_TargetFrameworkDirectories>$(MSBuildThisFileDirectory) + <_FullFrameworkReferenceAssemblyPaths>$(MSBuildThisFileDirectory) + true + + + + $(MSBuildExtensionsPath)\Tizen + $(TizenBuildPath)\bin + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.nuspec b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.nuspec new file mode 100644 index 0000000..cb5fd05 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.nuspec @@ -0,0 +1,16 @@ + + + + Tizen.Account.OAuth2 + $version$ + Tizen Developers + OAuth2.0 API for Tizen.Net + + + + + + + + + \ No newline at end of file diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.project.json b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.project.json new file mode 100644 index 0000000..aef135d --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.project.json @@ -0,0 +1,17 @@ +{ + "buildOptions": { + "debugType": "portable", + "platform": "AnyCPU", + "preserveCompilationContext": true + }, + "dependencies": { + "NETStandard.Library": "1.6.0", + "Tizen": "1.0.1" + }, + "runtimes": { + "win": {} + }, + "frameworks": { + "netstandard1.6": {} + } +} \ No newline at end of file diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.snk b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2.snk new file mode 100644 index 0000000000000000000000000000000000000000..67ee69f3199a0edea4caaf32d8f1d5339d7903c7 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096iGg@C|JAy9Arvp5H!cu})Cof?3EeJbI zL1B88jh-YG&1K63tqYNg1s7`2z-XRV)p*t5f(ys^5fsr?nz51f3>3dwYET-u9?HFx zglXLPB-|-%GCUzS*%jqf=Y!{H+;HEhjEelX3+KokSV;FEzvo1)N`PF7$P ztA!xZ8*T-CP_p)=`K5Prj4Z*;r6_Vp@D8`5XRf-V$8aKtQ;cpP)GVG1H}LYA;$`rx zpil+b@F@V4hPE-;u5#gSE2zi3kgd|2Y5cQY_q~SsXKCGcY&?ETu1TKcB`Ui4yhz%+ z5JU;d2aZUK*!oWd1%yD4j(>V#I7uklCfPNvfP5s|@}PT>-sp}jjfzkn*zctdXNP)K z;mKhAeQV5TKLBQS1Mi26dx4x|&x`Jvz4JJ?EWeYoo^lBDc#2h=5y`uhrjk$<6z + /// Class containing access token and related information. + /// + public class AccessToken + { + internal AccessToken() + { + } + + /// + /// The lifetime in seconds of the access token. + /// + public long ExpiresIn { get; internal set;} + + /// + /// The access token issued by the authorization server. + /// + public string Token { get; internal set;} + + /// + /// The scope of the access token. + /// + public IEnumerable Scope { get; internal set;} + + /// + /// The type of the access token. + /// + public string TokenType { get; internal set;} + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthenticationScheme.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthenticationScheme.cs new file mode 100644 index 0000000..7a47fe6 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthenticationScheme.cs @@ -0,0 +1,41 @@ +/* + * 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. + */ + +namespace Tizen.Account.OAuth2 +{ + /// + /// Enumerations for Client authentication scheme, used to sign client id and client secret accordingly. + /// Default is Basic (http://tools.ietf.org/html/rfc2617#section-2) + /// + /// Facebook and Google does not support HTTP Basic Authentication, instead they require client credentials to be sent via request body. + public enum AuthenticationScheme + { + /// + /// HTTP Basic Authentication for client authentication + /// + Basic = 0, + + /// + /// HTTP Basic Authentication for client authentication + /// + Digest, + + /// + /// Client credentials are sent via request body + /// + RequestBody + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationRequest.cs new file mode 100644 index 0000000..32c527d --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationRequest.cs @@ -0,0 +1,67 @@ +/* + * 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.Collections.Generic; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The request parameters to be sent to authorization end point. + /// + public abstract class AuthorizationRequest + { + /// + /// The desired response type from the OAuth authorization end point. + /// + public abstract string ResponseType { get; } + + /// + /// Client secret credentials. + /// + public ClientCredentials ClientSecrets { get; set; } + + /// + /// The scope of the access. + /// + public IEnumerable Scopes { get; set; } + + /// + /// The authorization end point URL. + /// + public Uri AuthorizationEndpoint { get; set; } + + /// + /// The redirection endpoint of the auhorization flow. + /// + public Uri RedirectionEndPoint { get; set; } + + /// + /// The access token end point URL. + /// + public Uri TokenEndpoint { get; set; } + + /// + /// The client's state which is maintained between request and response. + /// + public string State { get; set; } + + /// + /// Custom key-value parameters to be sent to the server + /// + public IEnumerable> CustomData { get; set; } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationResponse.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationResponse.cs new file mode 100644 index 0000000..f3510f6 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/AuthorizationResponse.cs @@ -0,0 +1,95 @@ +/* + * 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.Runtime.InteropServices; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The response containing authroization code from the authorization server. + /// + public class AuthorizationResponse : IDisposable + { + private bool _disposed = false; + private IntPtr _responseHandle; + + internal AuthorizationResponse(IntPtr handle) + { + _responseHandle = handle; + } + + /// + /// Destructor of the AuthorizationResponse class. + /// + ~AuthorizationResponse() + { + Dispose(false); + } + + /// + /// The authroization code. + /// + public string Code { get; internal set; } + + /// + /// The state parameter present in authorization request. + /// + public string State { get; internal set; } + + /// + /// Custom key-value parameter received from service provider + /// + public string GetCustomValue(string key) + { + IntPtr value = IntPtr.Zero; + int ret = Interop.Response.GetCustomData(_responseHandle, key, out value); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + return Marshal.PtrToStringAnsi(value); + } + + /// + /// Releases any unmanaged resources used by this object. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. + /// + /// If true, disposes any disposable objects. If false, does not dispose disposable objects. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + // Free managed objects + } + + Interop.Response.Destroy(_responseHandle); + _disposed = true; + } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/Authorizer.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/Authorizer.cs new file mode 100644 index 0000000..af3c4f4 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/Authorizer.cs @@ -0,0 +1,385 @@ +/* + * 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.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Tizen.Account.OAuth2 +{ + /// + /// An abstract class to represent various OAuth 2.0 authorization code flows. + /// Refer to http://tools.ietf.org/html/rfc6749 about OAuth 2.0 protocols. + /// Also service provider document needs to be referred for using end points and additional parameters. + /// + public abstract class Authorizer : IDisposable + { + + internal IntPtr _managerHandle; + private bool _disposed = false; + + /// + /// Constructor for Authoirzer instances + /// + public Authorizer() + { + int ret = Interop.Manager.Create(out _managerHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + /// + /// Destructor of the Authorizer class. + /// + ~Authorizer() + { + Dispose(false); + } + + /// + /// Indicates if the current instance is already handling an authorization request + /// + public bool IsRequestInProgress + { + get + { + return Interop.Manager.IsRequestInProgress(_managerHandle); + } + } + + /// + /// Authorizes the client with access toekn / authorizaion code in Implicit and Authorization Code grant flows respectively. + /// + /// + /// + /// An authorization request + /// The authorization response from server + public virtual Task AuthorizeAsync(AuthorizationRequest request) + { + throw new NotImplementedException(); + } + + /// + /// Gets the access token in OAuth2 supported grant flows except Implicit Grant flow. + /// + /// + /// + /// A token request + /// The response from server + public virtual Task GetAccessTokenAsync(TokenRequest request) + { + throw new NotImplementedException(); + } + + /// + /// Releases any unmanaged resources used by this object. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Retrieves access token using a refresh token. + /// + /// Request containing refresh token + /// The response containing access token. + /// http://tizen.org/privilege/internet + /// Thrown when method failed due to invalid argumets + /// Thrown when method fails due to server error + public virtual async Task RefreshAccessTokenAsync(RefreshTokenRequest request) + { + IntPtr requestHandle = GetRequestHandle(request); + return await Task.Run(() => GetRefreshToken(requestHandle)); + } + + private TokenResponse GetRefreshToken(IntPtr requestHandle) + { + int ret = (int)OAuth2Error.None; + IntPtr error = IntPtr.Zero; + TokenResponse response = null; + Interop.Manager.Oauth2RefreshTokenCallback accessTokenCb = (IntPtr responseHandle, IntPtr usrData) => + { + Interop.Response.GetError(responseHandle, out error); + if (error != IntPtr.Zero) + { + Log.Error(ErrorFactory.LogTag, "Error occured"); + } + else + { + IntPtr accessToken; + ret = Interop.Response.GetAccessToken(responseHandle, out accessToken); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + IntPtr tokenType; + ret = Interop.Response.GetTokenType(responseHandle, out tokenType); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Failed to get token type"); + } + + long expiresIn; + ret = Interop.Response.GetExpiresIn(responseHandle, out expiresIn); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Failed to get expires in"); + } + + IntPtr refreshToken; + ret = Interop.Response.GetRefreshToken(responseHandle, out refreshToken); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + IntPtr scope; + ret = Interop.Response.GetScope(responseHandle, out scope); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Failed to get scope"); + } + + IEnumerable scopes = (scope == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(scope)?.Split(' '); + + var token = new AccessToken(); + token.Token = (accessToken == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(accessToken); + token.TokenType = (tokenType == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(tokenType); + token.Scope = scopes; + token.ExpiresIn = expiresIn; + + response = new TokenResponse(responseHandle); + response.AccessToken = token; + response.RefreshToken = (refreshToken == IntPtr.Zero) ? null : new RefreshToken() { Token = Marshal.PtrToStringAnsi(refreshToken) }; + } + }; + + ret = Interop.Manager.RefreshAccessToken(_managerHandle, requestHandle, accessTokenCb, IntPtr.Zero); + Interop.Request.Destroy(requestHandle); + if (ret != (int)OAuth2Error.None || error != IntPtr.Zero) + { + if (error != IntPtr.Zero) + { + throw ErrorFactory.GetException(error); + } + else + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + return response; + } + + /// + /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. + /// + /// If true, disposes any disposable objects. If false, does not dispose disposable objects. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + // Free managed objects + } + + Interop.Manager.Destroy(_managerHandle); + _disposed = true; + } + + // Fill device request handle for refreshing access token + internal IntPtr GetRequestHandle(RefreshTokenRequest request) + { + IntPtr requestHandle; + int ret = Interop.Request.Create(out requestHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetRefreshTokenUrl(requestHandle, request.TokenEndpoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetGrantType(requestHandle, Interop.GrantType.Refresh); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetRefreshToken(requestHandle, request.RefreshToken); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + if (request.ClientSecrets.Id != null) + { + ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.ClientSecrets.Secret != null) + { + ret = Interop.Request.SetClientSecret(requestHandle, request.ClientSecrets.Secret); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.Scopes != null) + { + string scope = string.Join(" ", request.Scopes); + ret = Interop.Request.SetScope(requestHandle, scope); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + ret = Interop.Request.SetClientAuthenticationType(requestHandle, (int)request.AuthenticationScheme); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + return requestHandle; + } + + internal TokenResponse GetAccessToken(IntPtr requestHandle) + { + int ret = (int)OAuth2Error.None; + IntPtr error = IntPtr.Zero; + TokenResponse response = null; + Interop.Manager.Oauth2TokenCallback accessTokenCb = (IntPtr responseHandle, IntPtr usrData) => + { + if (responseHandle == IntPtr.Zero) + { + Log.Error(ErrorFactory.LogTag, "Error occured"); + throw (new ArgumentNullException()); + } + + Interop.Response.GetError(responseHandle, out error); + if (error != IntPtr.Zero) + { + Log.Error(ErrorFactory.LogTag, "Server Error occured"); + } + else + { + IntPtr accessToken = IntPtr.Zero; + ret = Interop.Response.GetAccessToken(responseHandle, out accessToken); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Failed to get access token"); + throw ErrorFactory.GetException(ret); + } + + IntPtr tokenType; + ret = Interop.Response.GetTokenType(responseHandle, out tokenType); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "TokenType can't be found"); + } + + long expiresIn = -1; + ret = Interop.Response.GetExpiresIn(responseHandle, out expiresIn); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "ExpiresIn can't be found"); + } + + IntPtr refreshToken; + ret = Interop.Response.GetRefreshToken(responseHandle, out refreshToken); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "Refresh Token can't be found"); + } + + IntPtr scope; + ret = Interop.Response.GetScope(responseHandle, out scope); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "Scope can't be found"); + } + + IntPtr state; + ret = Interop.Response.GetState(responseHandle, out state); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "State can't be found"); + } + + IEnumerable scopes = (scope == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(scope)?.Split(' '); + + var token = new AccessToken(); + token.Token = (accessToken == IntPtr.Zero)? null : Marshal.PtrToStringAnsi(accessToken); + token.TokenType = (tokenType == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(tokenType); + token.Scope = scopes; + token.ExpiresIn = expiresIn; + + response = new TokenResponse(responseHandle); + response.AccessToken = token; + response.State = (state == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(state); + response.RefreshToken = (refreshToken == IntPtr.Zero) ? null : new RefreshToken() { Token = Marshal.PtrToStringAnsi(refreshToken) }; + } + }; + + ret = Interop.Manager.RequestToken(_managerHandle, requestHandle, accessTokenCb, IntPtr.Zero); + Interop.Request.Destroy(requestHandle); + if (ret != (int)OAuth2Error.None || error != IntPtr.Zero) + { + if (error != IntPtr.Zero) + { + throw ErrorFactory.GetException(error); + } + else + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + return response; + } + } +} + diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentials.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentials.cs new file mode 100644 index 0000000..edd49b7 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentials.cs @@ -0,0 +1,45 @@ +/* + * 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; + +namespace Tizen.Account.OAuth2 +{ + /// + /// Contains client credentials required for authentication in request-body + /// + public class ClientCredentials + { + /// + /// The constructor + /// + public ClientCredentials() + { + + } + + /// + /// The client identifier + /// + public string Id { get; set; } + + /// + /// The client secret + /// + public string Secret { get; set; } + } +} + diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsAuthorizer.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsAuthorizer.cs new file mode 100644 index 0000000..6fc8922 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsAuthorizer.cs @@ -0,0 +1,163 @@ +/* + * 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 System.Collections.Generic; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The ClientCredentialsAuthorizer is used to obtain access tokens using Client Credentials Grant flow as described at https://tools.ietf.org/html/rfc6749#section-4.4 + /// + public class ClientCredentialsAuthorizer : Authorizer + { + /// + /// The constructor + /// + public ClientCredentialsAuthorizer() + { + + } + + /// + /// Authorization not supported through this API for this flow. + /// + /// Thrown when the operation is not supported + public override Task AuthorizeAsync(AuthorizationRequest request) + { + Log.Error(ErrorFactory.LogTag, "Authorization is not supported in this flow"); + throw new InvalidOperationException(); + } + + /// + /// Refreshing access token is not supported in this flow. + /// + /// Thrown when the operation is not supported + public override Task RefreshAccessTokenAsync(RefreshTokenRequest request) + { + Log.Error(ErrorFactory.LogTag, "Refreshing access token is not supported in this flow"); + throw new InvalidOperationException(); + } + + /// + /// Retrieves access token using client credentials. + /// The authroization request parameters should be as defined in https://tools.ietf.org/html/rfc6749#section-4.4.2 + /// + /// The token request + /// The response containing access token. + /// http://tizen.org/privilege/internet + /// Thrown when method failed due to invalid argumets + /// Thrown when method fails due to server error + public override async Task GetAccessTokenAsync(TokenRequest request) + { + IntPtr requestHandle = GetRequestHandle(request as ClientCredentialsTokenRequest); + return await Task.Run(() => GetAccessToken(requestHandle)); + } + + // Fill device request handle for access token + private IntPtr GetRequestHandle(ClientCredentialsTokenRequest request) + { + if (request == null) + { + Log.Error(ErrorFactory.LogTag, "Invalid request or request is null"); + throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter); + } + + IntPtr requestHandle; + int ret = Interop.Request.Create(out requestHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetTokenEndPointUrl(requestHandle, request.TokenEndpoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetGrantType(requestHandle, Interop.GrantType.ClientCredentials); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + if (request.ClientSecrets.Id != null) + { + ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.ClientSecrets.Secret != null) + { + ret = Interop.Request.SetClientSecret(requestHandle, request.ClientSecrets.Secret); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.Scopes != null) + { + string scope = string.Join(" ", request.Scopes); + ret = Interop.Request.SetScope(requestHandle, scope); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.CustomData != null) + { + foreach (var item in request.CustomData) + { + ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + } + + ret = Interop.Request.SetClientAuthenticationType(requestHandle, (int) request.AuthenticationScheme); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + return requestHandle; + } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsTokenRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsTokenRequest.cs new file mode 100644 index 0000000..50fa43a --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ClientCredentialsTokenRequest.cs @@ -0,0 +1,39 @@ +/* + * 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; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The class contains request parameters for retreiving access token in Client Credentials Grant flow. + /// + public class ClientCredentialsTokenRequest : TokenRequest + { + /// + /// The constructor + /// + public ClientCredentialsTokenRequest() + { + + } + + /// + /// The grant type. + /// + public override string GrantType { get; } = "client_credentials"; + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizationRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizationRequest.cs new file mode 100644 index 0000000..a53dc36 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizationRequest.cs @@ -0,0 +1,38 @@ +/* + * 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. + */ + +namespace Tizen.Account.OAuth2 +{ + /// + /// The class contains request parameters for retreiving authorization code in Authorization Code Grant flow. + /// Please refer https://tools.ietf.org/html/rfc6749#section-4.1.1 for more details + /// + public class CodeGrantAuthorizationRequest : AuthorizationRequest + { + /// + /// The constructor + /// + public CodeGrantAuthorizationRequest() + { + + } + + /// + /// The response type parameter to authorization server. + /// + public override string ResponseType { get; } = "code"; + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizer.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizer.cs new file mode 100644 index 0000000..213e1ba --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantAuthorizer.cs @@ -0,0 +1,337 @@ +/* + * 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 System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The CodeGrantAuthorizer is used to obtain access tokens and refresh tokens using Authorization Code Grant flow as described at https://tools.ietf.org/html/rfc6749#section-4.1 + /// + public class CodeGrantAuthorizer : Authorizer + { + /// + /// The constructor + /// + public CodeGrantAuthorizer() + { + + } + + /// + /// Retrieves authorization code asynchronously. The authroization request parameters should be as defined in https://tools.ietf.org/html/rfc6749#section-4.1.1 + /// + /// The authorization request + /// The response containing authorization code. + /// http://tizen.org/privilege/internet + /// Thrown when method failed due to invalid argumets + /// Thrown when method fails due to server error + public override async Task AuthorizeAsync(AuthorizationRequest request) + { + IntPtr requestHandle = GetRequestHandle(request as CodeGrantAuthorizationRequest); + return await Task.Run(() => GetAuthorizationResponse(requestHandle)); + } + + /// + /// Retrieves access token by exchanging authorization code received using . + /// The authroization request parameters should be as defined in https://tools.ietf.org/html/rfc6749#section-4.1.3 + /// + /// The token request + /// The response containing access token. + /// http://tizen.org/privilege/internet + /// Thrown when method failed due to invalid argumets + /// Thrown when method fails due to server error + public override async Task GetAccessTokenAsync(TokenRequest request) + { + IntPtr requestHandle = GetRequestHandle(request as CodeGrantTokenRequest); + return await Task.Run(() => GetAccessToken(requestHandle) ); + } + + /// + /// Clears the cookies + /// + public void ClearCookies() + { + int ret = (int)OAuth2Error.None; + ret = Interop.Manager.ClearCookies(_managerHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + /// + /// Clear the cache + /// + public void ClearCache() + { + int ret = (int)OAuth2Error.None; + ret = Interop.Manager.ClearCache(_managerHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + // Fill device request handle for Authorization code grant + private IntPtr GetRequestHandle(CodeGrantAuthorizationRequest request) + { + if (request == null) + { + Log.Error(ErrorFactory.LogTag, "Invalid request or request is null"); + throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter); + } + + IntPtr requestHandle; + int ret = Interop.Request.Create(out requestHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetAuthEndPointUrl(requestHandle, request.AuthorizationEndpoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetResponseType(requestHandle, Interop.ResponseType.Code); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + if (request.ClientSecrets.Id != null) + { + ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.ClientSecrets.Secret != null) + { + ret = Interop.Request.SetClientSecret(requestHandle, request.ClientSecrets.Secret); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.RedirectionEndPoint != null) + { + ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.OriginalString); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.Scopes != null) + { + string scope = string.Join(" ", request.Scopes); + ret = Interop.Request.SetScope(requestHandle, scope); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.State != null) + { + ret = Interop.Request.SetState(requestHandle, request.State); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.CustomData != null) + { + foreach( var item in request.CustomData) + { + ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + } + + return requestHandle; + } + + // Fill device request handle for access token + private IntPtr GetRequestHandle(CodeGrantTokenRequest request) + { + if (request == null) + { + Log.Error(ErrorFactory.LogTag, "Invalid request or request is null"); + throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter); + } + + IntPtr requestHandle; + int ret = Interop.Request.Create(out requestHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetGrantType(requestHandle, Interop.GrantType.AuthCode); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetAuthorizationCode(requestHandle, request.Code); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetTokenEndPointUrl(requestHandle, request.TokenEndpoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + if (request.ClientSecrets.Secret != null) + { + ret = Interop.Request.SetClientSecret(requestHandle, request.ClientSecrets.Secret); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.CustomData != null) + { + foreach (var item in request.CustomData) + { + ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + } + + ret = Interop.Request.SetClientAuthenticationType(requestHandle, (int)request.AuthenticationScheme); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + return requestHandle; + } + + private AuthorizationResponse GetAuthorizationResponse(IntPtr requestHandle) + { + AuthorizationResponse response = null; + int ret = (int)OAuth2Error.None; + IntPtr error = IntPtr.Zero; + + Interop.Manager.Oauth2AuthGrantCallback authGrantCb = (IntPtr responseHandle, IntPtr usrData) => + { + if (responseHandle == IntPtr.Zero) + { + Log.Error(ErrorFactory.LogTag, "Error occured"); + throw (new ArgumentNullException()); + } + + Interop.Response.GetError(responseHandle, out error); + if (error == IntPtr.Zero) + { + Log.Warn(ErrorFactory.LogTag, "Error occured"); + throw ErrorFactory.GetException(error); + } + else + { + IntPtr authorizationCode; + ret = Interop.Response.GetAuthorizationCode(responseHandle, out authorizationCode); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + IntPtr state; + ret = Interop.Response.GetState(responseHandle, out state); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + response = new AuthorizationResponse(responseHandle) { Code = Marshal.PtrToStringAnsi(authorizationCode), State = Marshal.PtrToStringAnsi(state) }; + } + }; + + ret = Interop.Manager.RequestAuthorizationGrant(_managerHandle, requestHandle, authGrantCb, IntPtr.Zero); + Interop.Request.Destroy(requestHandle); + if (ret != (int)OAuth2Error.None || error != IntPtr.Zero) + { + if (error != IntPtr.Zero) + { + throw ErrorFactory.GetException(error); + } + else + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + return response; + } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantTokenRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantTokenRequest.cs new file mode 100644 index 0000000..c537f0e --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/CodeGrantTokenRequest.cs @@ -0,0 +1,44 @@ +/* + * 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; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The class contains request parameters for retreiving access token in Authorization Code Grant flow. + /// + public class CodeGrantTokenRequest : TokenRequest + { + /// + /// The constructor + /// + public CodeGrantTokenRequest() + { + + } + + /// + /// The grant type + /// + public override string GrantType { get; } = "authorization_code"; + + /// + /// The authoriztion code received from the authorization server. + /// + public string Code { get; set; } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizationRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizationRequest.cs new file mode 100644 index 0000000..40732ab --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizationRequest.cs @@ -0,0 +1,37 @@ +/* + * 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. + */ + +namespace Tizen.Account.OAuth2 +{ + /// + /// The class contains request parameters for retreiving access token in Implicit Grant flow. + /// + public class ImplicitGrantAuthorizationRequest : AuthorizationRequest + { + /// + /// The constructor + /// + public ImplicitGrantAuthorizationRequest() + { + + } + + /// + /// The response type parameter to aturhoization server. + /// + public override string ResponseType { get; } = "token"; + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizer.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizer.cs new file mode 100644 index 0000000..f86c046 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ImplicitGrantAuthorizer.cs @@ -0,0 +1,241 @@ +/* + * 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.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The ImplicitGrantAuthorizer is used to obtain access tokens using Implicit Grant flow as described at https://tools.ietf.org/html/rfc6749#section-4.2 + /// + public class ImplicitGrantAuthorizer : Authorizer + { + /// + /// The constructor + /// + public ImplicitGrantAuthorizer() + { + + } + + /// + /// Retrieves access token asynchronously. The authroization request parameters should be as defined in https://tools.ietf.org/html/rfc6749#section-4.2.1 + /// + /// The authorization request + /// The response containing access token. + /// http://tizen.org/privilege/internet + /// Thrown when method failed due to invalid argumets + /// Thrown when method fails due to server error + public new virtual async Task AuthorizeAsync(AuthorizationRequest request) + { + IntPtr requestHandle = GetRequestHandle(request as ImplicitGrantAuthorizationRequest); + return await Task.Run(() => GetAuthorizationResponse(requestHandle)); + } + + /// + /// Access token can be retreived implicitly using in this flow. + /// + /// Thrown when the operation is not supported + public override Task GetAccessTokenAsync(TokenRequest request) + { + Log.Error(ErrorFactory.LogTag, "Obtain token directly from authorization grant "); + throw new InvalidOperationException(); + } + + /// + /// Refreshing access token is not supported in this flow. + /// + /// Thrown when the operation is not supported + public override Task RefreshAccessTokenAsync(RefreshTokenRequest request) + { + Log.Error(ErrorFactory.LogTag, "Refesh token is not supported in Implicit Grant flow"); + throw new InvalidOperationException(); + } + + private TokenResponse GetAuthorizationResponse(IntPtr requestHandle) + { + IntPtr error = IntPtr.Zero; + TokenResponse response = null; + int ret = (int)OAuth2Error.None; + Interop.Manager.Oauth2AuthGrantCallback authGrantCb = (IntPtr responseHandle, IntPtr usrData) => + { + if (responseHandle == IntPtr.Zero) + { + Log.Error(ErrorFactory.LogTag, "Error occured"); + throw (new ArgumentNullException()); + } + + Interop.Response.GetError(responseHandle, out error); + if (error != IntPtr.Zero) + { + Log.Error(ErrorFactory.LogTag, "Server Error occured"); + } + else + { + IntPtr accessToken; + ret = Interop.Response.GetAccessToken(responseHandle, out accessToken); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + IntPtr tokenType; + ret = Interop.Response.GetTokenType(responseHandle, out tokenType); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + long expiresIn; + ret = Interop.Response.GetExpiresIn(responseHandle, out expiresIn); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + IntPtr scope; + ret = Interop.Response.GetScope(responseHandle, out scope); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + IntPtr state; + ret = Interop.Response.GetState(responseHandle, out state); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + IEnumerable scopes = (scope == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(scope)?.Split(' '); + + var token = new AccessToken() { Token = Marshal.PtrToStringAnsi(accessToken), ExpiresIn = expiresIn, Scope = scopes, TokenType = Marshal.PtrToStringAnsi(tokenType) }; + response = new TokenResponse(responseHandle) { AccessToken = token, State = Marshal.PtrToStringAnsi(state), RefreshToken = null }; + } + }; + + ret = Interop.Manager.RequestAuthorizationGrant(_managerHandle, requestHandle, authGrantCb, IntPtr.Zero); + Interop.Request.Destroy(requestHandle); + if (ret != (int)OAuth2Error.None || error != IntPtr.Zero) + { + if (error != IntPtr.Zero) + { + throw ErrorFactory.GetException(error); + } + else + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + return response; + } + + // Fill device request handle for Authorization code grant + private IntPtr GetRequestHandle(ImplicitGrantAuthorizationRequest request) + { + if (request == null) + { + Log.Error(ErrorFactory.LogTag, "Invalid request or request is null"); + throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter); + } + + IntPtr requestHandle; + int ret = Interop.Request.Create(out requestHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetAuthEndPointUrl(requestHandle, request.AuthorizationEndpoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetResponseType(requestHandle, Interop.ResponseType.Token); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + if (request.RedirectionEndPoint != null) + { + ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.Scopes != null) + { + string scope = string.Join(" ", request.Scopes); + ret = Interop.Request.SetScope(requestHandle, scope); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.State != null) + { + ret = Interop.Request.SetState(requestHandle, request.State); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.CustomData != null) + { + foreach (var item in request.CustomData) + { + ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + } + + return requestHandle; + } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorFactory.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorFactory.cs new file mode 100644 index 0000000..aba1f8a --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorFactory.cs @@ -0,0 +1,127 @@ +/* + * 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 Tizen.Internals.Errors; + +namespace Tizen.Account.OAuth2 +{ + internal enum OAuth2Error + { + // Tizen Account Oauth Error + // TIZEN_ERROR_ACCOUNT_OAUTH -0x01010000 + + None = ErrorCode.None, + OutOfMemory = ErrorCode.OutOfMemory, + InvalidParameter = ErrorCode.InvalidParameter, + AlreadyInProgress = ErrorCode.AlreadyInProgress, + NotSupported = ErrorCode.NotSupported, + PermissionDenied = ErrorCode.PermissionDenied, + ParseFailed = -0x01010000 | 0X01, + NetworkError = -0x01010000 | 0X02, + Server = -0x01010000 | 0X03, + UserCancelled = -0x01010000 | 0X04, + ValueNotFound = -0x01010000 | 0X05, + Unknown = ErrorCode.Unknown + } + + internal class ErrorFactory + { + internal static string LogTag = "Tizen.Account.OAuth2"; + + internal static Exception GetException(IntPtr error) + { + int serverErrorCode, platformErrorCode; + int ret = Interop.Error.GetCode(error, out serverErrorCode, out platformErrorCode); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "error code can't be found"); + } + + string errorDescription; + ret = Interop.Error.GetDescription(error, out errorDescription); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "error description can't be found"); + } + + string uri; + Interop.Error.GetUri(error, out uri); + if (ret != (int)OAuth2Error.None) + { + Log.Debug(ErrorFactory.LogTag, "error uri can't be found"); + } + + var errorResponse = new OAuth2ErrorResponse() + { + PlatformErrorCode = platformErrorCode, + ServerErrorCode = serverErrorCode, + ErrorUri = uri, + Error = errorDescription + }; + + return new OAuth2Exception() { Error = errorResponse }; + } + + internal static Exception GetException(int error) + { + if ((OAuth2Error)error == OAuth2Error.OutOfMemory) + { + return new OutOfMemoryException("Out of memory"); + } + else if ((OAuth2Error)error == OAuth2Error.InvalidParameter) + { + return new ArgumentException("Invalid parameter"); + } + else if ((OAuth2Error)error == OAuth2Error.AlreadyInProgress) + { + return new InvalidOperationException("Request already in progress"); + } + else if ((OAuth2Error)error == OAuth2Error.NotSupported) + { + return new NotSupportedException("Not supported"); + } + else if ((OAuth2Error)error == OAuth2Error.PermissionDenied) + { + return new UnauthorizedAccessException("Permission denied"); + } + else if ((OAuth2Error)error == OAuth2Error.ParseFailed) + { + return new FormatException("Parsing failed"); + } + else if ((OAuth2Error)error == OAuth2Error.NetworkError) + { + return new Exception("Networking error occured"); + } + else if ((OAuth2Error)error == OAuth2Error.Server) + { + return new Exception("Server error"); + } + else if ((OAuth2Error)error == OAuth2Error.UserCancelled) + { + return new Exception("User cancelled"); + } + else if ((OAuth2Error)error == OAuth2Error.ValueNotFound) + { + return new Exception("Value not found"); + } + else + { + return new Exception("Unknown error"); + } + } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorResponse.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorResponse.cs new file mode 100644 index 0000000..89b2fac --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/OAuth2ErrorResponse.cs @@ -0,0 +1,66 @@ +/* + * 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; + +namespace Tizen.Account.OAuth2 +{ + /// + /// Exception wrapper for OAuth2 related exception + /// + public class OAuth2Exception : Exception + { + internal OAuth2Exception() + { + } + + /// + /// The error response. + /// + public OAuth2ErrorResponse Error { get; internal set; } + } + + /// + /// Wrapper class contaning OAuth2 related error information + /// + public class OAuth2ErrorResponse + { + internal OAuth2ErrorResponse () + { + + } + + /// + /// The server error code + /// + public int ServerErrorCode { get; internal set; } + + /// + /// The platform error cocde + /// + public int PlatformErrorCode { get; internal set; } + + /// + /// Error description + /// + public string Error { get; internal set; } + + /// + /// URI of the error page. + /// + public string ErrorUri { get; internal set; } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshToken.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshToken.cs new file mode 100644 index 0000000..37d09d5 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshToken.cs @@ -0,0 +1,34 @@ +/* + * 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. + */ + +namespace Tizen.Account.OAuth2 +{ + /// + /// The refresh token which can be used to obtain new access token. + /// + public class RefreshToken + { + internal RefreshToken () + { + + } + + /// + /// The refresh token issued to the client. + /// + public string Token { get; internal set; } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshTokenRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshTokenRequest.cs new file mode 100644 index 0000000..45f4fae --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/RefreshTokenRequest.cs @@ -0,0 +1,42 @@ +/* + * 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. + */ + +namespace Tizen.Account.OAuth2 +{ + /// + /// The class contains request parameters for refreshing an access token. + /// + public class RefreshTokenRequest : TokenRequest + { + /// + /// The constructor + /// + public RefreshTokenRequest() + { + + } + + /// + /// The grant type to be used + /// + public override string GrantType { get; } = "refresh_token"; + + /// + /// The refresh token issued by authorization server. + /// + public string RefreshToken { get; set; } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsAuthorizer.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsAuthorizer.cs new file mode 100644 index 0000000..5bb5c30 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsAuthorizer.cs @@ -0,0 +1,178 @@ +/* + * 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.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The ResourceOwnerPwdCredentialsAuthorizer is used to obtain access tokens using Resource Owner Password Credentials Grant flow as described at https://tools.ietf.org/html/rfc6749#section-4.3 + /// + public class ResourceOwnerPwdCredentialsAuthorizer : Authorizer + { + /// + /// The constructor + /// + public ResourceOwnerPwdCredentialsAuthorizer() + { + + } + + /// + /// Authorization not supported through this API for this flow. + /// + /// Thrown when the operation is not supported + public override Task AuthorizeAsync(AuthorizationRequest request) + { + Log.Error(ErrorFactory.LogTag, "Authorization is not supported in this flow"); + throw new InvalidOperationException(); + } + + /// + /// Retrieves access token by sending resource owner's password credentials. + /// The authroization request parameters should be as defined in https://tools.ietf.org/html/rfc6749#section-4.3.2 + /// + /// The token request + /// The response containing access token. + /// http://tizen.org/privilege/internet + /// Thrown when method failed due to invalid argumets + /// Thrown when method fails due to server error + public override async Task GetAccessTokenAsync(TokenRequest request) + { + IntPtr requestHandle = GetRequestHandle(request as ResourceOwnerPwdCredentialsTokenRequest); + return await Task.Run(() => GetAccessToken(requestHandle)); + } + + // Fill device request handle for access token + private IntPtr GetRequestHandle(ResourceOwnerPwdCredentialsTokenRequest request) + { + if (request == null) + { + Log.Error(ErrorFactory.LogTag, "Invalid request or request is null"); + throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter); + } + + IntPtr requestHandle; + int ret = Interop.Request.Create(out requestHandle); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetTokenEndPointUrl(requestHandle, request.TokenEndpoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.ToString()); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetGrantType(requestHandle, Interop.GrantType.Password); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetUserName(requestHandle, request.Username); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + ret = Interop.Request.SetPassword(requestHandle, request.Password); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + if (request.ClientSecrets.Id != null) + { + ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.ClientSecrets.Secret != null) + { + ret = Interop.Request.SetClientSecret(requestHandle, request.ClientSecrets.Secret); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.Scopes != null) + { + string scope = string.Join(" ", request.Scopes); + ret = Interop.Request.SetScope(requestHandle, scope); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + if (request.CustomData != null) + { + foreach (var item in request.CustomData) + { + ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + } + + if (request.State != null) + { + ret = Interop.Request.SetState(requestHandle, request.State); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + } + + ret = Interop.Request.SetClientAuthenticationType(requestHandle, (int)request.AuthenticationScheme); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + + return requestHandle; + } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsTokenRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsTokenRequest.cs new file mode 100644 index 0000000..f7ffb8c --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/ResourceOwnerPwdCredentialsTokenRequest.cs @@ -0,0 +1,47 @@ +/* + * 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. + */ + +namespace Tizen.Account.OAuth2 +{ + /// + /// The class contains request parameters for retreiving access token in Resource Owner Password Credentials Grant flow. + /// + public class ResourceOwnerPwdCredentialsTokenRequest : TokenRequest + { + /// + /// The constructor + /// + public ResourceOwnerPwdCredentialsTokenRequest() + { + + } + + /// + /// The grant type + /// + public override string GrantType { get; } = "password"; + + /// + /// The resource owner username + /// + public string Username { get; set; } + + /// + /// The resource owner password + /// + public string Password { get; set; } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenRequest.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenRequest.cs new file mode 100644 index 0000000..66bdb10 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenRequest.cs @@ -0,0 +1,67 @@ +/* + * 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.Collections.Generic; + +namespace Tizen.Account.OAuth2 +{ + /// + /// Abstract wrapper class containing OAuth 2.0 request parameters for requesting an access token. + /// + public abstract class TokenRequest + { + /// + /// The Grant type + /// + public abstract string GrantType { get; } + + /// + /// The client credentials + /// + public ClientCredentials ClientSecrets { get; set; } + + /// + /// The access token end point URL. + /// + public Uri TokenEndpoint { get; set; } + + /// + /// The redirection endpoint of the auhorization flow. + /// + public Uri RedirectionEndPoint { get; set; } + + /// + /// The scope of the access request as described by https://tools.ietf.org/html/rfc6749#section-3.3 + /// + public IEnumerable Scopes { get; set; } + + /// + /// Custom key-value parameters to be sent to the server + /// + public IEnumerable> CustomData { get; set; } + + /// + /// Client authentication scheme. Default is Basic + /// + public AuthenticationScheme AuthenticationScheme { get; set; } = AuthenticationScheme.Basic; + + /// + /// The client's state which is maintained between request and response. + /// + public string State { get; set; } + } +} diff --git a/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenResponse.cs b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenResponse.cs new file mode 100644 index 0000000..5bcfee4 --- /dev/null +++ b/src/Tizen.Account.OAuth2/Tizen.Account.OAuth2/TokenResponse.cs @@ -0,0 +1,103 @@ +/* + * 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.Runtime.InteropServices; + +namespace Tizen.Account.OAuth2 +{ + /// + /// The response from authroization server containing access token and an optional refresh token. + /// + public class TokenResponse + { + private bool _disposed = false; + private IntPtr _responseHandle; + + internal TokenResponse(IntPtr handle) + { + _responseHandle = handle; + } + + /// + /// Destructor of the AuthorizationResponse class. + /// + ~TokenResponse() + { + Dispose(false); + } + + /// + /// The access token + /// + public AccessToken AccessToken { get; internal set; } + + /// + /// The state parameter present in authorization request. + /// + public string State { get; internal set; } + + /// + /// The refresh token. The value will be null if authorization server doesn't return a refresh token. + /// + /// + /// Issuing a refresh token is optional at the discretion of the authorization server. + /// + public RefreshToken RefreshToken { get; internal set; } + + /// + /// Custom key-value parameter received from service provider + /// + public string GetCustomValue(string key) + { + IntPtr value; + int ret = Interop.Response.GetCustomData(_responseHandle, key, out value); + if (ret != (int)OAuth2Error.None) + { + Log.Error(ErrorFactory.LogTag, "Interop failed"); + throw ErrorFactory.GetException(ret); + } + return Marshal.PtrToStringAnsi(value); + } + + /// + /// Releases any unmanaged resources used by this object. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. + /// + /// If true, disposes any disposable objects. If false, does not dispose disposable objects. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + // Free managed objects + } + + Interop.Response.Destroy(_responseHandle); + _disposed = true; + } + } +} -- 2.7.4