0b7867a86e1908c5b39e78485232cef082b3fee2
[platform/core/csapi/tizenfx.git] / src / Tizen.Account.OAuth2 / Tizen.Account.OAuth2 / ImplicitGrantAuthorizer.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.Threading.Tasks;
21
22 namespace Tizen.Account.OAuth2
23 {
24     /// <summary>
25     /// The ImplicitGrantAuthorizer is used to obtain access tokens using Implicit Grant flow as described at https://tools.ietf.org/html/rfc6749#section-4.2
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public class ImplicitGrantAuthorizer : Authorizer
29     {
30         /// <summary>
31         /// The constructor
32         /// </summary>
33         /// <since_tizen> 3 </since_tizen>
34         public ImplicitGrantAuthorizer()
35         {
36
37         }
38
39         /// <summary>
40         /// Access token can be retreived implicitly using <see cref="ClientCredentialsAuthorizer.AuthorizeAsync"/> in this flow.
41         /// </summary>
42         /// <since_tizen> 3 </since_tizen>
43         /// <exception cref="InvalidOperationException">Thrown when the operation is not supported</exception>
44         public Task<TokenResponse> GetAccessTokenAsync(TokenRequest request)
45         {
46             Log.Error(ErrorFactory.LogTag, "Obtain token directly from authorization grant ");
47             throw new InvalidOperationException();
48         }
49
50         /// <summary>
51         /// Refreshing access token is not supported in this flow.
52         /// </summary>
53         /// <since_tizen> 3 </since_tizen>
54         /// <exception cref="InvalidOperationException">Thrown when the operation is not supported</exception>
55         public override Task<TokenResponse> RefreshAccessTokenAsync(RefreshTokenRequest request)
56         {
57             Log.Error(ErrorFactory.LogTag, "Refesh token is not supported in Implicit Grant flow");
58             throw new InvalidOperationException();
59         }
60
61         private TokenResponse GetAuthorizationResponse(IntPtr requestHandle)
62         {
63             IntPtr error = IntPtr.Zero;
64             TokenResponse response = null;
65             int ret = (int)OAuth2Error.None;
66             Interop.Manager.Oauth2AuthGrantCallback authGrantCb = (IntPtr responseHandle, IntPtr usrData) =>
67             {
68                 if (responseHandle == IntPtr.Zero)
69                 {
70                     Log.Error(ErrorFactory.LogTag, "Error occured");
71                     throw (new ArgumentNullException());
72                 }
73
74                 Interop.Response.GetError(responseHandle, out error);
75                 if (error != IntPtr.Zero)
76                 {
77                     Log.Error(ErrorFactory.LogTag, "Server Error occured");
78                 }
79                 else
80                 {
81                     IntPtr accessToken;
82                     ret = Interop.Response.GetAccessToken(responseHandle, out accessToken);
83                     if (ret != (int)OAuth2Error.None)
84                     {
85                         Log.Error(ErrorFactory.LogTag, "Interop failed");
86                         throw ErrorFactory.GetException(ret);
87                     }
88
89                     IntPtr tokenType;
90                     ret = Interop.Response.GetTokenType(responseHandle, out tokenType);
91                     if (ret != (int)OAuth2Error.None)
92                     {
93                         Log.Error(ErrorFactory.LogTag, "Interop failed");
94                         throw ErrorFactory.GetException(ret);
95                     }
96
97                     long expiresIn;
98                     ret = Interop.Response.GetExpiresIn(responseHandle, out expiresIn);
99                     if (ret != (int)OAuth2Error.None)
100                     {
101                         Log.Error(ErrorFactory.LogTag, "Interop failed");
102                         throw ErrorFactory.GetException(ret);
103                     }
104
105                     IntPtr scope;
106                     ret = Interop.Response.GetScope(responseHandle, out scope);
107                     if (ret != (int)OAuth2Error.None)
108                     {
109                         Log.Error(ErrorFactory.LogTag, "Interop failed");
110                         throw ErrorFactory.GetException(ret);
111                     }
112
113                     IntPtr state;
114                     ret = Interop.Response.GetState(responseHandle, out state);
115                     if (ret != (int)OAuth2Error.None)
116                     {
117                         Log.Error(ErrorFactory.LogTag, "Interop failed");
118                         throw ErrorFactory.GetException(ret);
119                     }
120
121                     IEnumerable<string> scopes = (scope == IntPtr.Zero) ? null : Marshal.PtrToStringAnsi(scope)?.Split(' ');
122
123                     var token = new AccessToken() { Token = Marshal.PtrToStringAnsi(accessToken), ExpiresIn = expiresIn, Scope = scopes, TokenType = Marshal.PtrToStringAnsi(tokenType) };
124                     response = new TokenResponse(responseHandle) { AccessToken = token, State = Marshal.PtrToStringAnsi(state), RefreshToken = null };
125                 }
126             };
127
128             ret = Interop.Manager.RequestAuthorizationGrant(_managerHandle, requestHandle, authGrantCb, IntPtr.Zero);
129             Interop.Request.Destroy(requestHandle);
130             if (ret != (int)OAuth2Error.None || error != IntPtr.Zero)
131             {
132                 if (error != IntPtr.Zero)
133                 {
134                     throw ErrorFactory.GetException(error);
135                 }
136                 else
137                 {
138                     Log.Error(ErrorFactory.LogTag, "Interop failed");
139                     throw ErrorFactory.GetException(ret);
140                 }
141             }
142
143             return response;
144         }
145
146         // Fill device request handle for Authorization code grant
147         private IntPtr GetRequestHandle(ImplicitGrantAuthorizationRequest request)
148         {
149             if (request == null)
150             {
151                 Log.Error(ErrorFactory.LogTag, "Invalid request or request is null");
152                 throw ErrorFactory.GetException((int)OAuth2Error.InvalidParameter);
153             }
154
155             IntPtr requestHandle;
156             int ret = Interop.Request.Create(out requestHandle);
157             if (ret != (int)OAuth2Error.None)
158             {
159                 Log.Error(ErrorFactory.LogTag, "Interop failed");
160                 throw ErrorFactory.GetException(ret);
161             }
162
163             ret = Interop.Request.SetAuthEndPointUrl(requestHandle, request.AuthorizationEndpoint.ToString());
164             if (ret != (int)OAuth2Error.None)
165             {
166                 Log.Error(ErrorFactory.LogTag, "Interop failed");
167                 throw ErrorFactory.GetException(ret);
168             }
169
170             ret = Interop.Request.SetResponseType(requestHandle, Interop.ResponseType.Token);
171             if (ret != (int)OAuth2Error.None)
172             {
173                 Log.Error(ErrorFactory.LogTag, "Interop failed");
174                 throw ErrorFactory.GetException(ret);
175             }
176
177             ret = Interop.Request.SetClientId(requestHandle, request.ClientSecrets.Id);
178             if (ret != (int)OAuth2Error.None)
179             {
180                 Log.Error(ErrorFactory.LogTag, "Interop failed");
181                 throw ErrorFactory.GetException(ret);
182             }
183
184             if (request.RedirectionEndPoint != null)
185             {
186                 ret = Interop.Request.SetRedirectionUrl(requestHandle, request.RedirectionEndPoint.ToString());
187                 if (ret != (int)OAuth2Error.None)
188                 {
189                     Log.Error(ErrorFactory.LogTag, "Interop failed");
190                     throw ErrorFactory.GetException(ret);
191                 }
192             }
193
194             if (request.Scopes != null)
195             {
196                 string scope = string.Join(" ", request.Scopes);
197                 ret = Interop.Request.SetScope(requestHandle, scope);
198                 if (ret != (int)OAuth2Error.None)
199                 {
200                     Log.Error(ErrorFactory.LogTag, "Interop failed");
201                     throw ErrorFactory.GetException(ret);
202                 }
203             }
204
205             if (request.State != null)
206             {
207                 ret = Interop.Request.SetState(requestHandle, request.State);
208                 if (ret != (int)OAuth2Error.None)
209                 {
210                     Log.Error(ErrorFactory.LogTag, "Interop failed");
211                     throw ErrorFactory.GetException(ret);
212                 }
213             }
214
215             if (request.CustomData != null)
216             {
217                 foreach (var item in request.CustomData)
218                 {
219                     ret = Interop.Request.AddCustomData(requestHandle, item.Key, item.Value);
220                     if (ret != (int)OAuth2Error.None)
221                     {
222                         Log.Error(ErrorFactory.LogTag, "Interop failed");
223                         throw ErrorFactory.GetException(ret);
224                     }
225                 }
226             }
227
228             return requestHandle;
229         }
230     }
231 }