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

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: 2nd round Created 10 years, 10 months ago
Right Patch Set: minor Created 10 years, 9 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 token res ponse.</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.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 private readonly string authorizationServerUrl; 122 private readonly string authorizationServerUrl;
123 private readonly ClientSecrets clientSecrets; 123 private readonly ClientSecrets clientSecrets;
124 private readonly IDataStore dataStore; 124 private readonly IDataStore dataStore;
125 private readonly IEnumerable<string> scopes; 125 private readonly IEnumerable<string> scopes;
126 private readonly ConfigurableHttpClient httpClient; 126 private readonly ConfigurableHttpClient httpClient;
127 private readonly IClock clock; 127 private readonly IClock clock;
128 128
129 #endregion 129 #endregion
130 130
131 /// <summary>Gets the token server URL.</summary> 131 /// <summary>Gets the token server URL.</summary>
132 public string TokenServerEncodedUrl { get { return tokenServerUrl; } } 132 public string TokenServerUrl { get { return tokenServerUrl; } }
133 133
134 /// <summary>Gets the authorization code server URL.</summary> 134 /// <summary>Gets the authorization code server URL.</summary>
135 public string AuthorizationServerUrl { get { return authorizationServerU rl; } } 135 public string AuthorizationServerUrl { get { return authorizationServerU rl; } }
136 136
137 /// <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>
138 public ClientSecrets ClientSecrets { get { return clientSecrets; } } 138 public ClientSecrets ClientSecrets { get { return clientSecrets; } }
139 139
140 /// <summary>Gets the data store used to store the credentials.</summary > 140 /// <summary>Gets the data store used to store the credentials.</summary >
141 public IDataStore DataStore { get { return dataStore; } } 141 public IDataStore DataStore { get { return dataStore; } }
142 142
143 /// <summary>Gets the scopes.</summary> 143 /// <summary>Gets the scopes which indicate the API access your applicat ion is requesting.</summary>
144 public IEnumerable<string> Scopes { get { return scopes; } } 144 public IEnumerable<string> Scopes { get { return scopes; } }
145 145
146 /// <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>
147 public ConfigurableHttpClient HttpClient { get { return httpClient; } } 147 public ConfigurableHttpClient HttpClient { get { return httpClient; } }
148 148
149 /// <summary>Constructs a new flow using the initializer's properties.</ summary> 149 /// <summary>Constructs a new flow using the initializer's properties.</ summary>
150 public AuthorizationCodeFlow(Initializer initializer) 150 public AuthorizationCodeFlow(Initializer initializer)
151 { 151 {
152 clientSecrets = initializer.ClientSecrets; 152 clientSecrets = initializer.ClientSecrets;
153 if (clientSecrets == null) 153 if (clientSecrets == null)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 public virtual AuthorizationCodeRequestUrl CreateAuthorizationCodeReques t(string redirectUri) 217 public virtual AuthorizationCodeRequestUrl CreateAuthorizationCodeReques t(string redirectUri)
218 { 218 {
219 return new AuthorizationCodeRequestUrl(new Uri(AuthorizationServerUr l)) 219 return new AuthorizationCodeRequestUrl(new Uri(AuthorizationServerUr l))
220 { 220 {
221 ClientId = ClientSecrets.ClientId, 221 ClientId = ClientSecrets.ClientId,
222 Scope = string.Join(" ", Scopes), 222 Scope = string.Join(" ", Scopes),
223 RedirectUri = redirectUri 223 RedirectUri = redirectUri
224 }; 224 };
225 } 225 }
226 226
227 public async Task<TokenResponse> ExchangeCodeForTokenAsync(string userId , string code, string redirectUri, 227 public async Task<TokenResponse> ExchangeCodeForTokenAsync(string userId , string code, string redirectUri,
class 2013/10/02 17:37:18 Missing <summary>
peleyal 2013/10/02 18:24:45 on the interface :) On 2013/10/02 17:37:18, class
228 CancellationToken taskCancellationToken) 228 CancellationToken taskCancellationToken)
229 { 229 {
230 var authorizationCodeTokenReq = new AuthorizationCodeTokenRequest 230 var authorizationCodeTokenReq = new AuthorizationCodeTokenRequest
231 { 231 {
232 Scope = string.Join(" ", Scopes), 232 Scope = string.Join(" ", Scopes),
233 RedirectUri = redirectUri, 233 RedirectUri = redirectUri,
234 Code = code, 234 Code = code,
235 }; 235 };
236 236
237 var token = await FetchTokenAsync(userId, authorizationCodeTokenReq, taskCancellationToken) 237 var token = await FetchTokenAsync(userId, authorizationCodeTokenReq, taskCancellationToken)
238 .ConfigureAwait(false); 238 .ConfigureAwait(false);
239 await StoreTokenAsync(userId, token, taskCancellationToken).Configur eAwait(false); 239 await StoreTokenAsync(userId, token, taskCancellationToken).Configur eAwait(false);
240 return token; 240 return token;
241 } 241 }
242 242
243 public async Task<TokenResponse> RefreshTokenAsync(string userId, string refreshToken, 243 public async Task<TokenResponse> RefreshTokenAsync(string userId, string refreshToken,
class 2013/10/02 17:37:18 Missing <summary>
peleyal 2013/10/02 18:24:45 on the interface :) On 2013/10/02 17:37:18, class
244 CancellationToken taskCancellationToken) 244 CancellationToken taskCancellationToken)
245 { 245 {
246 var refershTokenReq = new RefreshTokenRequest 246 var refershTokenReq = new RefreshTokenRequest
247 { 247 {
248 RefreshToken = refreshToken, 248 RefreshToken = refreshToken,
249 }; 249 };
250 var token = await FetchTokenAsync(userId, refershTokenReq, taskCance llationToken).ConfigureAwait(false); 250 var token = await FetchTokenAsync(userId, refershTokenReq, taskCance llationToken).ConfigureAwait(false);
251 251
252 // The new token may not 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.
253 if (token.RefreshToken == null) 253 if (token.RefreshToken == null)
(...skipping 26 matching lines...) Expand all
280 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param> 280 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param>
281 /// <returns>Token response with the new access token</returns> 281 /// <returns>Token response with the new access token</returns>
282 [VisibleForTestOnly] 282 [VisibleForTestOnly]
283 internal async Task<TokenResponse> FetchTokenAsync(string userId, TokenR equest request, 283 internal async Task<TokenResponse> FetchTokenAsync(string userId, TokenR equest request,
284 CancellationToken taskCancellationToken) 284 CancellationToken taskCancellationToken)
285 { 285 {
286 // Add client id and client secret to requests. 286 // Add client id and client secret to requests.
287 request.ClientId = ClientSecrets.ClientId; 287 request.ClientId = ClientSecrets.ClientId;
288 request.ClientSecret = ClientSecrets.ClientSecret; 288 request.ClientSecret = ClientSecrets.ClientSecret;
289 289
290 var httpRequest = new HttpRequestMessage(HttpMethod.Post, TokenServe rEncodedUrl); 290 TokenResponseException tokenException = null;
291 httpRequest.Content = ParameterUtils.CreateFormUrlEncodedContent(req uest); 291 try
292 292 {
293 var response = await HttpClient.SendAsync(httpRequest, taskCancellat ionToken).ConfigureAwait(false); 293 var tokenResponse = await request.Execute(httpClient, TokenServe rUrl, taskCancellationToken, Clock);
294 294 return tokenResponse;
295 var content = await response.Content.ReadAsStringAsync().ConfigureAw ait(false); 295 }
296 if (!response.IsSuccessStatusCode) 296 catch (TokenResponseException ex)
297 { 297 {
298 var error = NewtonsoftJsonSerializer.Instance.Deserialize<TokenE rrorResponse>(content); 298 // In case there is an exception during getting the token, we de lete any user's token information from·
299 await DeleteTokenAsync(userId, taskCancellationToken); 299 // the data store.
300 throw new TokenResponseException(error); 300 tokenException = ex;
301 } 301 }
302 302 await DeleteTokenAsync(userId, taskCancellationToken);
303 // Get the token and sets its issued time. 303 throw tokenException;
304 var token = NewtonsoftJsonSerializer.Instance.Deserialize<TokenRespo nse>(content);
305 token.Issued = clock.Now;
306
307 return token;
308 } 304 }
309 305
310 public void Dispose() 306 public void Dispose()
311 { 307 {
312 if (HttpClient != null) 308 if (HttpClient != null)
313 { 309 {
314 HttpClient.Dispose(); 310 HttpClient.Dispose();
315 } 311 }
316 } 312 }
317 } 313 }
318 } 314 }
LEFTRIGHT

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