Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(331)

Delta Between Two Patch Sets: Src/GoogleApis.Auth/OAuth2/AuthorizationCodeFlow.cs

Issue 13972043: Issue 351: Reimplement OAuth2 (Step 3 - Tests, Flows and Credential) (Closed) Base URL: https://google-api-dotnet-client.googlecode.com/hg/
Left Patch Set: Created 10 years, 6 months ago
Right Patch Set: minor Created 10 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Src/GoogleApis.Auth/GoogleApis.Auth.csproj ('k') | Src/GoogleApis.Auth/OAuth2/AuthorizationCodeInstalledApp.cs » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 Copyright 2013 Google Inc 2 Copyright 2013 Google Inc
3 3
4 Licensed under the Apache License, Version 2.0 (the "License"); 4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with 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 6 You may obtain a copy of the License at
7 7
8 http://www.apache.org/licenses/LICENSE-2.0 8 http://www.apache.org/licenses/LICENSE-2.0
9 9
10 Unless required by applicable law or agreed to in writing, software 10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS, 11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and 13 See the License for the specific language governing permissions and
14 limitations under the License. 14 limitations under the License.
15 */ 15 */
16 16
17 using System; 17 using System;
18 using System.Collections.Generic; 18 using System.Collections.Generic;
19 using System.IO; 19 using System.IO;
20 using System.Net.Http; 20 using System.Net.Http;
21 using System.Threading; 21 using System.Threading;
22 using System.Threading.Tasks; 22 using System.Threading.Tasks;
23 23
24 using Google.Apis.Auth.OAuth2.Requests; 24 using Google.Apis.Auth.OAuth2.Requests;
25 using Google.Apis.Auth.OAuth2.Responses; 25 using Google.Apis.Auth.OAuth2.Responses;
26 using Google.Apis.Http; 26 using Google.Apis.Http;
27 using Google.Apis.Json;
28 using Google.Apis.Logging; 27 using Google.Apis.Logging;
29 using Google.Apis.Requests.Parameters;
30 using Google.Apis.Util; 28 using Google.Apis.Util;
31 using Google.Apis.Util.Store; 29 using Google.Apis.Util.Store;
32 using Google.Apis.Testing; 30 using Google.Apis.Testing;
33 31
34 namespace Google.Apis.Auth.OAuth2 32 namespace Google.Apis.Auth.OAuth2
35 { 33 {
36 /// <summary> 34 /// <summary>
37 /// Thread-safe OAuth 2.0 authorization code flow that manages and persists end-user credentials. 35 /// Thread-safe OAuth 2.0 authorization code flow that manages and persists end-user credentials.
38 /// <para> 36 /// <para>
39 /// This is designed to simplify the flow in which an end-user authorizes th e application to access their protected 37 /// This is designed to simplify the flow in which an end-user authorizes th e application to access their protected
40 /// data, and then the application has access to their data based on an acce ss token and a refresh token to refresh· 38 /// data, and then the application has access to their data based on an acce ss token and a refresh token to refresh·
41 /// that access token when it expires. 39 /// that access token when it expires.
42 /// </para> 40 /// </para>
43 /// </summary> 41 /// </summary>
44 public class AuthorizationCodeFlow : IAuthorizationCodeFlow 42 public class AuthorizationCodeFlow : IAuthorizationCodeFlow
45 { 43 {
46 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<AuthorizationCodeFlow>(); 44 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<AuthorizationCodeFlow>();
47 45
48 #region Initializer 46 #region Initializer
49 47
50 /// <summary>An initializer class for the authorization code flow. </sum mary> 48 /// <summary>An initializer class for the authorization code flow. </sum mary>
51 public class Initializer 49 public class Initializer
52 { 50 {
53 /// <summary> 51 /// <summary>
54 /// Gets or sets the method for presenting the access token to the r esource server. 52 /// Gets or sets the method for presenting the access token to the r esource server.
55 /// The default value is <seealso cref="BearerToken.AuthorizationHea derAccessMethod"/>. 53 /// The default value is <seealso cref="BearerToken.AuthorizationHea derAccessMethod"/>.
56 /// </summary> 54 /// </summary>
57 public IAccessMethod AccessMethod { get; set; } 55 public IAccessMethod AccessMethod { get; set; }
58 56
59 /// <summary>Gets or sets the token server URL.</summary> 57 /// <summary>Gets the token server URL.</summary>
60 public string TokenServerUrl { get; private set; } 58 public string TokenServerUrl { get; private set; }
61 59
62 /// <summary>Gets or sets the authorization server URL.</summary> 60 /// <summary>Gets or sets the authorization server URL.</summary>
63 public string AuthorizationServerUrl { get; private set; } 61 public string AuthorizationServerUrl { get; private set; }
64 62
65 /// <summary>Gets or sets the client secrets which includes the clie nt identifier and its secret.</summary> 63 /// <summary>Gets or sets the client secrets which includes the clie nt identifier and its secret.</summary>
66 public ClientSecrets ClientSecrets { get; set; } 64 public ClientSecrets ClientSecrets { get; set; }
67 65
68 /// <summary> 66 /// <summary>
69 /// Gets or sets the client secrets stream which contains the client identifier and its secret. 67 /// Gets or sets the client secrets stream which contains the client identifier and its secret.
70 /// </summary> 68 /// </summary>
71 /// <remarks>The AuthorizationCodeFlow constructor is responsible fo r disposing the stream.</remarks> 69 /// <remarks>The AuthorizationCodeFlow constructor is responsible fo r disposing the stream.</remarks>
72 public Stream ClientSecretsStream { get; set; } 70 public Stream ClientSecretsStream { get; set; }
73 71
74 /// <summary>Gets or sets the data store used to store the credentia l.</summary> 72 /// <summary>Gets or sets the data store used to store the token res ponse.</summary>
75 public IDataStore DataStore { get; set; } 73 public IDataStore DataStore { get; set; }
76 74
77 /// <summary>Gets or sets the scopes.</summary> 75 /// <summary>
76 /// Gets or sets the scopes which indicate the API access your appli cation is requesting.
77 /// </summary>
78 public IEnumerable<string> Scopes { get; set; } 78 public IEnumerable<string> Scopes { get; set; }
79 79
80 /// <summary>· 80 /// <summary>·
81 /// Gets or sets the factory for creating <see cref="System.Net.Http .HttpClient"/> instance. 81 /// Gets or sets the factory for creating <see cref="System.Net.Http .HttpClient"/> instance.
82 /// </summary> 82 /// </summary>
83 public IHttpClientFactory HttpClientFactory { get; set; } 83 public IHttpClientFactory HttpClientFactory { get; set; }
84 84
85 /// <summary> 85 /// <summary>
86 /// Get or sets the exponential back-off policy. Default value is < c>UnsuccessfulResponse503</c>, which· 86 /// Get or sets the exponential back-off policy. Default value is < c>UnsuccessfulResponse503</c>, which·
87 /// means that exponential back-off is used on 503 abnormal HTTP res ponses. 87 /// means that exponential back-off is used on 503 abnormal HTTP res ponses.
88 /// If the value is set to <c>None</c>, no exponential back-off poli cy is used, and it's up to user to 88 /// If the value is set to <c>None</c>, no exponential back-off poli cy is used, and it's up to user to
89 /// configure the <seealso cref="Google.Apis.Http.ConfigurableMessag eHandler"/> in an 89 /// configure the <seealso cref="Google.Apis.Http.ConfigurableMessag eHandler"/> in an
90 /// <seealso cref="Google.Apis.Http.IConfigurableHttpClientInitializ er"/> to set a specific back-off 90 /// <seealso cref="Google.Apis.Http.IConfigurableHttpClientInitializ er"/> to set a specific back-off
91 /// implementation (using <seealso cref="Google.Apis.Http.BackOffHan dler"/>). 91 /// implementation (using <seealso cref="Google.Apis.Http.BackOffHan dler"/>).
92 /// </summary> 92 /// </summary>
93 public ExponentialBackOffPolicy DefaultExponentialBackOffPolicy { ge t; set; } 93 public ExponentialBackOffPolicy DefaultExponentialBackOffPolicy { ge t; set; }
94 94
95 /// <summary> 95 /// <summary>
96 /// Gets or sets the clock. The clock is used to determine if the to ken has expired, if so we will try 96 /// Gets or sets the clock. The clock is used to determine if the to ken has expired, if so we will try to
97 /// to refresh it. 97 /// refresh it. The default value is <seealso cref="SystemClock.Defa ult"/>.
98 /// Default value is <seealso cref="SystemClock.Default"/>.
99 /// </summary> 98 /// </summary>
100 public IClock Clock { get; set; } 99 public IClock Clock { get; set; }
101 100
102 /// <summary>Constructs a new initializer.</summary> 101 /// <summary>Constructs a new initializer.</summary>
103 /// <param name="authorizationServerUrl">Authorization server URL</p aram> 102 /// <param name="authorizationServerUrl">Authorization server URL</p aram>
104 /// <param name="tokenServerUrl">Token server URL</param> 103 /// <param name="tokenServerUrl">Token server URL</param>
105 public Initializer(string authorizationServerUrl, string tokenServer Url) 104 public Initializer(string authorizationServerUrl, string tokenServer Url)
106 { 105 {
107 AuthorizationServerUrl = authorizationServerUrl; 106 AuthorizationServerUrl = authorizationServerUrl;
108 TokenServerUrl = tokenServerUrl; 107 TokenServerUrl = tokenServerUrl;
(...skipping 14 matching lines...) Expand all
123 private readonly string authorizationServerUrl; 122 private readonly string authorizationServerUrl;
124 private readonly ClientSecrets clientSecrets; 123 private readonly ClientSecrets clientSecrets;
125 private readonly IDataStore dataStore; 124 private readonly IDataStore dataStore;
126 private readonly IEnumerable<string> scopes; 125 private readonly IEnumerable<string> scopes;
127 private readonly ConfigurableHttpClient httpClient; 126 private readonly ConfigurableHttpClient httpClient;
128 private readonly IClock clock; 127 private readonly IClock clock;
129 128
130 #endregion 129 #endregion
131 130
132 /// <summary>Gets the token server URL.</summary> 131 /// <summary>Gets the token server URL.</summary>
133 public string TokenServerEncodedUrl { get { return tokenServerUrl; } } 132 public string TokenServerUrl { get { return tokenServerUrl; } }
134 133
135 /// <summary>Gets the authorization code server URL.</summary> 134 /// <summary>Gets the authorization code server URL.</summary>
136 public string AuthorizationServerUrl { get { return authorizationServerU rl; } } 135 public string AuthorizationServerUrl { get { return authorizationServerU rl; } }
137 136
138 /// <summary>Gets the client secrets which includes the client identifie r and its secret.</summary> 137 /// <summary>Gets the client secrets which includes the client identifie r and its secret.</summary>
139 public ClientSecrets ClientSecrets { get { return clientSecrets; } } 138 public ClientSecrets ClientSecrets { get { return clientSecrets; } }
140 139
141 /// <summary>Gets the data store used to store the credentials.</summary > 140 /// <summary>Gets the data store used to store the credentials.</summary >
142 public IDataStore DataStore { get { return dataStore; } } 141 public IDataStore DataStore { get { return dataStore; } }
143 142
144 /// <summary>Gets the scopes.</summary> 143 /// <summary>Gets the scopes which indicate the API access your applicat ion is requesting.</summary>
145 public IEnumerable<string> Scopes { get { return scopes; } } 144 public IEnumerable<string> Scopes { get { return scopes; } }
146 145
147 /// <summary>Gets the HTTP client used to make authentication requests t o the server.</summary> 146 /// <summary>Gets the HTTP client used to make authentication requests t o the server.</summary>
148 public ConfigurableHttpClient HttpClient { get { return httpClient; } } 147 public ConfigurableHttpClient HttpClient { get { return httpClient; } }
149 148
150 /// <summary>Constructs a new flow using the initializer's properties.</ summary> 149 /// <summary>Constructs a new flow using the initializer's properties.</ summary>
151 public AuthorizationCodeFlow(Initializer initializer) 150 public AuthorizationCodeFlow(Initializer initializer)
152 { 151 {
153 clientSecrets = initializer.ClientSecrets; 152 clientSecrets = initializer.ClientSecrets;
154 if (clientSecrets == null) 153 if (clientSecrets == null)
155 { 154 {
156 if (initializer.ClientSecretsStream == null) 155 if (initializer.ClientSecretsStream == null)
157 { 156 {
158 throw new ArgumentException( 157 throw new ArgumentException("You MUST set ClientSecret or Cl ientSecretStream on the initializer");
159 "At least one of the client secret or client secret stre am MUST be set");
160 } 158 }
161 159
162 try 160 using (initializer.ClientSecretsStream)
163 { 161 {
164 using (initializer.ClientSecretsStream) 162 clientSecrets = GoogleClientSecrets.Load(initializer.ClientS ecretsStream).Secrets;
165 {
166 clientSecrets = GoogleClientSecrets.Load(initializer.Cli entSecretsStream).Secrets;
167 }
168 } 163 }
169 catch (Exception ex) 164 }
170 { 165
171 throw new ArgumentException("Can't read the client secrets f rom the given stream", ex); 166 accessMethod = initializer.AccessMethod.ThrowIfNull("Initializer.Acc essMethod");
172 } 167 clock = initializer.Clock.ThrowIfNull("Initializer.Clock");
173 } 168 tokenServerUrl = initializer.TokenServerUrl.ThrowIfNullOrEmpty("Init ializer.TokenServerUrl");
174 initializer.AccessMethod.ThrowIfNull("AccessMethod");
175 initializer.ClientSecrets.ThrowIfNull("Clock");
176
177 accessMethod = initializer.AccessMethod;
178 tokenServerUrl = initializer.TokenServerUrl.ThrowIfNullOrEmpty("Toke nServerUrl");
179 authorizationServerUrl = initializer.AuthorizationServerUrl.ThrowIfN ullOrEmpty 169 authorizationServerUrl = initializer.AuthorizationServerUrl.ThrowIfN ullOrEmpty
180 ("AuthorizationServerUrl"); 170 ("Initializer.AuthorizationServerUrl");
181 clock = initializer.Clock;
182 171
183 dataStore = initializer.DataStore; 172 dataStore = initializer.DataStore;
184 if (dataStore == null) 173 if (dataStore == null)
185 { 174 {
186 Logger.Warning("Datastore is null, as a result the user's creden tial will not be stored"); 175 Logger.Warning("Datastore is null, as a result the user's creden tial will not be stored");
187 } 176 }
188 scopes = initializer.Scopes; 177 scopes = initializer.Scopes;
189 178
190 // Set the HTTP client. 179 // Set the HTTP client.
191 var httpArgs = new CreateHttpClientArgs(); 180 var httpArgs = new CreateHttpClientArgs();
192 181
193 // Add exponential back-off initializer if necessary. 182 // Add exponential back-off initializer if necessary.
194 if (initializer.DefaultExponentialBackOffPolicy != ExponentialBackOf fPolicy.None) 183 if (initializer.DefaultExponentialBackOffPolicy != ExponentialBackOf fPolicy.None)
195 { 184 {
196 httpArgs.Initializers.Add( 185 httpArgs.Initializers.Add(
197 new ExponentialBackOffInitializer(initializer.DefaultExponen tialBackOffPolicy, 186 new ExponentialBackOffInitializer(initializer.DefaultExponen tialBackOffPolicy,
198 () => new BackOffHandler(new ExponentialBackOff()))); 187 () => new BackOffHandler(new ExponentialBackOff())));
199 } 188 }
200 httpClient = (initializer.HttpClientFactory ?? new HttpClientFactory ()).CreateHttpClient(httpArgs); 189 httpClient = (initializer.HttpClientFactory ?? new HttpClientFactory ()).CreateHttpClient(httpArgs);
201 } 190 }
202 191
203 #region IAuthorizationCodeFlow overrides 192 #region IAuthorizationCodeFlow overrides
204 193
205 public IAccessMethod AccessMethod { get { return accessMethod; } } 194 public IAccessMethod AccessMethod { get { return accessMethod; } }
206 195
207 public IClock Clock { get { return clock; } } 196 public IClock Clock { get { return clock; } }
208 197
209 public async Task<TokenResponse> LoadToken(string userId, CancellationTo ken taskCancellationToken) 198 public async Task<TokenResponse> LoadTokenAsync(string userId, Cancellat ionToken taskCancellationToken)
210 { 199 {
211 taskCancellationToken.ThrowIfCancellationRequested(); 200 taskCancellationToken.ThrowIfCancellationRequested();
212 if (DataStore == null) 201 if (DataStore == null)
213 { 202 {
214 return null; 203 return null;
215 } 204 }
216 return await DataStore.Get<TokenResponse>(userId).ConfigureAwait(fal se); 205 return await DataStore.GetAsync<TokenResponse>(userId).ConfigureAwai t(false);
217 } 206 }
218 207
219 public async Task DeleteToken(string userId, CancellationToken taskCance llationToken) 208 public async Task DeleteTokenAsync(string userId, CancellationToken task CancellationToken)
220 { 209 {
221 taskCancellationToken.ThrowIfCancellationRequested(); 210 taskCancellationToken.ThrowIfCancellationRequested();
222 if (DataStore != null) 211 if (DataStore != null)
223 { 212 {
224 await DataStore.Delete<TokenResponse>(userId).ConfigureAwait(fal se); 213 await DataStore.DeleteAsync<TokenResponse>(userId).ConfigureAwai t(false);
225 } 214 }
226 } 215 }
227 216
228 public virtual AuthorizationCodeRequestUrl CreateAuthorizationCodeReques t(string redirectUri) 217 public virtual AuthorizationCodeRequestUrl CreateAuthorizationCodeReques t(string redirectUri)
229 { 218 {
230 return new AuthorizationCodeRequestUrl(new Uri(AuthorizationServerUr l)) 219 return new AuthorizationCodeRequestUrl(new Uri(AuthorizationServerUr l))
231 { 220 {
232 ClientId = ClientSecrets.ClientId, 221 ClientId = ClientSecrets.ClientId,
233 Scope = string.Join(" ", Scopes), 222 Scope = string.Join(" ", Scopes),
234 RedirectUri = redirectUri 223 RedirectUri = redirectUri
235 }; 224 };
236 } 225 }
237 226
238 public async Task<TokenResponse> ExchangeCodeForToken(string userId, str ing code, string redirectUri, 227 public async Task<TokenResponse> ExchangeCodeForTokenAsync(string userId , string code, string redirectUri,
239 CancellationToken taskCancellationToken) 228 CancellationToken taskCancellationToken)
240 { 229 {
241 taskCancellationToken.ThrowIfCancellationRequested();
242 var authorizationCodeTokenReq = new AuthorizationCodeTokenRequest 230 var authorizationCodeTokenReq = new AuthorizationCodeTokenRequest
243 { 231 {
244 Scope = string.Join(" ", Scopes), 232 Scope = string.Join(" ", Scopes),
245 RedirectUri = redirectUri, 233 RedirectUri = redirectUri,
246 Code = code, 234 Code = code,
247 }; 235 };
248 236
249 var token = await FetchToken(userId, authorizationCodeTokenReq, task CancellationToken).ConfigureAwait(false); 237 var token = await FetchTokenAsync(userId, authorizationCodeTokenReq, taskCancellationToken)
250 await StoreToken(userId, token, taskCancellationToken).ConfigureAwai t(false); 238 .ConfigureAwait(false);
239 await StoreTokenAsync(userId, token, taskCancellationToken).Configur eAwait(false);
251 return token; 240 return token;
252 } 241 }
253 242
254 public async Task<TokenResponse> RefreshToken(string userId, string refr eshToken, 243 public async Task<TokenResponse> RefreshTokenAsync(string userId, string refreshToken,
255 CancellationToken taskCancellationToken) 244 CancellationToken taskCancellationToken)
256 { 245 {
257 taskCancellationToken.ThrowIfCancellationRequested();
258 var refershTokenReq = new RefreshTokenRequest 246 var refershTokenReq = new RefreshTokenRequest
259 { 247 {
260 RefreshToken = refreshToken, 248 RefreshToken = refreshToken,
261 }; 249 };
262 var token = await FetchToken(userId, refershTokenReq, taskCancellati onToken).ConfigureAwait(false); 250 var token = await FetchTokenAsync(userId, refershTokenReq, taskCance llationToken).ConfigureAwait(false);
263 251
264 // The new token doesn't contain a refresh token, so set it with the given refresh token. 252 // The new token may not contain a refresh token, so set it with the given refresh token.
265 if (token.RefreshToken == null) 253 if (token.RefreshToken == null)
266 { 254 {
267 token.RefreshToken = refreshToken; 255 token.RefreshToken = refreshToken;
268 } 256 }
269 257
270 await StoreToken(userId, token, taskCancellationToken).ConfigureAwai t(false); 258 await StoreTokenAsync(userId, token, taskCancellationToken).Configur eAwait(false);
271 return token; 259 return token;
272 } 260 }
273 261
274 #endregion 262 #endregion
275 263
276 /// <summary>Stores the token in the <see cref="DataStore"/>.</summary> 264 /// <summary>Stores the token in the <see cref="DataStore"/>.</summary>
277 /// <param name="userId">User identifier</param> 265 /// <param name="userId">User identifier</param>
278 /// <param name="token">Token to store</param> 266 /// <param name="token">Token to store</param>
279 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param> 267 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param>
280 private async Task StoreToken(string userId, TokenResponse token, Cancel lationToken taskCancellationToken) 268 private async Task StoreTokenAsync(string userId, TokenResponse token, C ancellationToken taskCancellationToken)
281 { 269 {
282 taskCancellationToken.ThrowIfCancellationRequested(); 270 taskCancellationToken.ThrowIfCancellationRequested();
283 if (DataStore != null) 271 if (DataStore != null)
284 { 272 {
285 await DataStore.Store<TokenResponse>(userId, token).ConfigureAwa it(false); 273 await DataStore.StoreAsync<TokenResponse>(userId, token).Configu reAwait(false);
286 } 274 }
287 } 275 }
288 276
289 /// <summary>Retrieve a new token from the server using the specified re quest.</summary> 277 /// <summary>Retrieve a new token from the server using the specified re quest.</summary>
290 /// <param name="userId">User identifier</param> 278 /// <param name="userId">User identifier</param>
291 /// <param name="request">Token request</param> 279 /// <param name="request">Token request</param>
292 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param> 280 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param>
293 /// <returns>Token response with the new access token</returns> 281 /// <returns>Token response with the new access token</returns>
294 [VisibleForTestOnly] 282 [VisibleForTestOnly]
295 internal async Task<TokenResponse> FetchToken(string userId, TokenReques t request, 283 internal async Task<TokenResponse> FetchTokenAsync(string userId, TokenR equest request,
296 CancellationToken taskCancellationToken) 284 CancellationToken taskCancellationToken)
297 { 285 {
298 // Add client id and client secret to requests. 286 // Add client id and client secret to requests.
299 request.ClientId = ClientSecrets.ClientId; 287 request.ClientId = ClientSecrets.ClientId;
300 request.ClientSecret = ClientSecrets.ClientSecret; 288 request.ClientSecret = ClientSecrets.ClientSecret;
301 289
302 var httpRequest = new HttpRequestMessage(HttpMethod.Post, TokenServe rEncodedUrl); 290 TokenResponseException tokenException = null;
303 httpRequest.Content = ParameterUtils.CreateFormUrlEncodedContent(req uest); 291 try
304 292 {
305 var response = await HttpClient.SendAsync(httpRequest, taskCancellat ionToken).ConfigureAwait(false); 293 var tokenResponse = await request.Execute(httpClient, TokenServe rUrl, taskCancellationToken, Clock);
306 294 return tokenResponse;
307 taskCancellationToken.ThrowIfCancellationRequested(); 295 }
308 296 catch (TokenResponseException ex)
309 if (!response.IsSuccessStatusCode) 297 {
310 { 298 // In case there is an exception during getting the token, we de lete any user's token information from·
311 var error = NewtonsoftJsonSerializer.Instance.Deserialize<TokenE rrorResponse>( 299 // the data store.
312 await response.Content.ReadAsStringAsync().ConfigureAwait(fa lse)); 300 tokenException = ex;
313 301 }
314 await DeleteToken(userId, taskCancellationToken); 302 await DeleteTokenAsync(userId, taskCancellationToken);
315 303 throw tokenException;
316 throw new TokenResponseException(error);
317 }
318
319 // gets the token and sets its issued time
320 var token = NewtonsoftJsonSerializer.Instance.Deserialize<TokenRespo nse>(
321 await response.Content.ReadAsStringAsync().ConfigureAwait(false) );
322 token.Issued = clock.Now;
323
324 return token;
325 } 304 }
326 305
327 public void Dispose() 306 public void Dispose()
328 { 307 {
329 if (HttpClient != null) 308 if (HttpClient != null)
330 { 309 {
331 HttpClient.Dispose(); 310 HttpClient.Dispose();
332 } 311 }
333 } 312 }
334 } 313 }
335 } 314 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b