2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Threading.Tasks;
19 using System.Runtime.InteropServices;
20 using System.Collections.Generic;
22 namespace Tizen.Account.OAuth2
25 /// 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
27 /// <since_tizen> 3 </since_tizen>
28 public class CodeGrantAuthorizer : Authorizer
33 /// <since_tizen> 3 </since_tizen>
34 public CodeGrantAuthorizer()
40 /// Retrieves authorization code asynchronously. The authroization request parameters should be as defined in https://tools.ietf.org/html/rfc6749#section-4.1.1
42 /// <since_tizen> 3 </since_tizen>
43 /// <param name="request">The authorization request <see cref="CodeGrantAuthorizationRequest"/></param>
44 /// <returns>The response containing authorization code.</returns>
45 /// <privilege>http://tizen.org/privilege/internet</privilege>
46 /// <exception cref="ArgumentException">Thrown when method failed due to invalid argumets</exception>
47 /// <exception cref="OAuth2Exception">Thrown when method fails due to server error</exception>
48 public override async Task<AuthorizationResponse> AuthorizeAsync(AuthorizationRequest request)
50 IntPtr requestHandle = GetRequestHandle(request as CodeGrantAuthorizationRequest);
51 return await Task.Run(() => GetAuthorizationResponse(requestHandle));
55 /// Retrieves access token by exchanging authorization code received using <see cref="AuthorizeAsync(AuthorizationRequest)"/>.
56 /// The authroization request parameters should be as defined in https://tools.ietf.org/html/rfc6749#section-4.1.3
58 /// <since_tizen> 3 </since_tizen>
59 /// <param name="request">The token request <see cref="CodeGrantTokenRequest"/></param>
60 /// <returns>The response containing access token.</returns>
61 /// <privilege>http://tizen.org/privilege/internet</privilege>
62 /// <exception cref="ArgumentException">Thrown when method failed due to invalid argumets</exception>
63 /// <exception cref="OAuth2Exception">Thrown when method fails due to server error</exception>
64 public override async Task<TokenResponse> GetAccessTokenAsync(TokenRequest request)
66 IntPtr requestHandle = GetRequestHandle(request as CodeGrantTokenRequest);
67 return await Task.Run(() => GetAccessTokenByCode(requestHandle) );
71 /// Clears the cookies
73 /// <since_tizen> 3 </since_tizen>
74 public void ClearCookies()
76 int ret = (int)OAuth2Error.None;
77 ret = Interop.Manager.ClearCookies(_managerHandle);
78 if (ret != (int)OAuth2Error.None)
80 Log.Error(ErrorFactory.LogTag, "Interop failed");
81 throw ErrorFactory.GetException(ret);
88 /// <since_tizen> 3 </since_tizen>
89 public void ClearCache()
91 int ret = (int)OAuth2Error.None;
92 ret = Interop.Manager.ClearCache(_managerHandle);
93 if (ret != (int)OAuth2Error.None)
95 Log.Error(ErrorFactory.LogTag, "Interop failed");
96 throw ErrorFactory.GetException(ret);
100 // Fill device request handle for Authorization code grant
101 private IntPtr GetRequestHandle(CodeGrantAuthorizationRequest request)
105 Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
106 throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter);
109 IntPtr requestHandle;
110 int ret = Interop.Request.Create(out requestHandle);
111 if (ret != (int)OAuth2Error.None)
113 Log.Error(ErrorFactory.LogTag, "Interop failed");
114 throw ErrorFactory.GetException(ret);
117 ret = Interop.Request.SetAuthEndPointUrl(requestHandle, request.AuthorizationEndpoint.ToString());
118 if (ret != (int)OAuth2Error.None)
120 Log.Error(ErrorFactory.LogTag, "Interop failed");
121 throw ErrorFactory.GetException(ret);
124 ret = Interop.Request.SetResponseType(requestHandle, Interop.ResponseType.Code);
125 if (ret != (int)OAuth2Error.None)
127 Log.Error(ErrorFactory.LogTag, "Interop failed");
128 throw ErrorFactory.GetException(ret);
131 if (request.ClientSecrets.Id != null)
133 ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id);
134 if (ret != (int)OAuth2Error.None)
136 Log.Error(ErrorFactory.LogTag, "Interop failed");
137 throw ErrorFactory.GetException(ret);
141 if (request.ClientSecrets.Secret != null)
143 ret = Interop.Request.SetClientSecret(requestHandle, request.ClientSecrets.Secret);
144 if (ret != (int)OAuth2Error.None)
146 Log.Error(ErrorFactory.LogTag, "Interop failed");
147 throw ErrorFactory.GetException(ret);
151 if (request.RedirectionEndPoint != null)
153 ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.OriginalString);
154 if (ret != (int)OAuth2Error.None)
156 Log.Error(ErrorFactory.LogTag, "Interop failed");
157 throw ErrorFactory.GetException(ret);
161 if (request.Scopes != null)
163 string scope = string.Join(" ", request.Scopes);
164 ret = Interop.Request.SetScope(requestHandle, scope);
165 if (ret != (int)OAuth2Error.None)
167 Log.Error(ErrorFactory.LogTag, "Interop failed");
168 throw ErrorFactory.GetException(ret);
172 if (request.State != null)
174 ret = Interop.Request.SetState(requestHandle, request.State);
175 if (ret != (int)OAuth2Error.None)
177 Log.Error(ErrorFactory.LogTag, "Interop failed");
178 throw ErrorFactory.GetException(ret);
182 if (request.CustomData != null)
184 foreach( var item in request.CustomData)
186 ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value);
187 if (ret != (int)OAuth2Error.None)
189 Log.Error(ErrorFactory.LogTag, "Interop failed");
190 throw ErrorFactory.GetException(ret);
195 return requestHandle;
198 // Fill device request handle for access token
199 private IntPtr GetRequestHandle(CodeGrantTokenRequest request)
203 Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
204 throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter);
207 IntPtr requestHandle;
208 int ret = Interop.Request.Create(out requestHandle);
209 if (ret != (int)OAuth2Error.None)
211 Log.Error(ErrorFactory.LogTag, "Interop failed");
212 throw ErrorFactory.GetException(ret);
215 ret = Interop.Request.SetGrantType(requestHandle, Interop.GrantType.AuthCode);
216 if (ret != (int)OAuth2Error.None)
218 Log.Error(ErrorFactory.LogTag, "Interop failed");
219 throw ErrorFactory.GetException(ret);
222 ret = Interop.Request.SetAuthorizationCode(requestHandle, request.Code);
223 if (ret != (int)OAuth2Error.None)
225 Log.Error(ErrorFactory.LogTag, "Interop failed");
226 throw ErrorFactory.GetException(ret);
229 ret = Interop.Request.SetTokenEndPointUrl(requestHandle, request.TokenEndpoint.ToString());
230 if (ret != (int)OAuth2Error.None)
232 Log.Error(ErrorFactory.LogTag, "Interop failed");
233 throw ErrorFactory.GetException(ret);
236 ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.ToString());
237 if (ret != (int)OAuth2Error.None)
239 Log.Error(ErrorFactory.LogTag, "Interop failed");
240 throw ErrorFactory.GetException(ret);
243 ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id);
244 if (ret != (int)OAuth2Error.None)
246 Log.Error(ErrorFactory.LogTag, "Interop failed");
247 throw ErrorFactory.GetException(ret);
250 if (request.ClientSecrets.Secret != null)
252 ret = Interop.Request.SetClientSecret(requestHandle, request.ClientSecrets.Secret);
253 if (ret != (int)OAuth2Error.None)
255 Log.Error(ErrorFactory.LogTag, "Interop failed");
256 throw ErrorFactory.GetException(ret);
260 if (request.CustomData != null)
262 foreach (var item in request.CustomData)
264 ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value);
265 if (ret != (int)OAuth2Error.None)
267 Log.Error(ErrorFactory.LogTag, "Interop failed");
268 throw ErrorFactory.GetException(ret);
273 ret = Interop.Request.SetClientAuthenticationType(requestHandle, (int)request.AuthenticationScheme);
274 if (ret != (int)OAuth2Error.None)
276 Log.Error(ErrorFactory.LogTag, "Interop failed");
277 throw ErrorFactory.GetException(ret);
280 return requestHandle;
283 private AuthorizationResponse GetAuthorizationResponse(IntPtr requestHandle)
285 AuthorizationResponse response = null;
286 int ret = (int)OAuth2Error.None;
287 IntPtr error = IntPtr.Zero;
289 Interop.Manager.Oauth2AuthGrantCallback authGrantCb = (IntPtr responseHandle, IntPtr usrData) =>
291 if (responseHandle == IntPtr.Zero)
293 Log.Error(ErrorFactory.LogTag, "Error occured");
294 throw (new ArgumentNullException());
297 Interop.Response.GetError(responseHandle, out error);
298 if (error == IntPtr.Zero)
300 Log.Warn(ErrorFactory.LogTag, "Error occured");
301 throw ErrorFactory.GetException(error);
305 IntPtr authorizationCode;
306 ret = Interop.Response.GetAuthorizationCode(responseHandle, out authorizationCode);
307 if (ret != (int)OAuth2Error.None)
309 Log.Error(ErrorFactory.LogTag, "Interop failed");
310 throw ErrorFactory.GetException(ret);
314 ret = Interop.Response.GetState(responseHandle, out state);
315 if (ret != (int)OAuth2Error.None)
317 Log.Error(ErrorFactory.LogTag, "Interop failed");
318 throw ErrorFactory.GetException(ret);
321 response = new AuthorizationResponse(responseHandle) { Code = Marshal.PtrToStringAnsi(authorizationCode), State = Marshal.PtrToStringAnsi(state) };
325 ret = Interop.Manager.RequestAuthorizationGrant(_managerHandle, requestHandle, authGrantCb, IntPtr.Zero);
326 Interop.Request.Destroy(requestHandle);
327 if (ret != (int)OAuth2Error.None || error != IntPtr.Zero)
329 if (error != IntPtr.Zero)
331 throw ErrorFactory.GetException(error);
335 Log.Error(ErrorFactory.LogTag, "Interop failed");
336 throw ErrorFactory.GetException(ret);