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

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: minor 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 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)
154 { 154 {
155 if (initializer.ClientSecretsStream == null) 155 if (initializer.ClientSecretsStream == null)
156 { 156 {
157 throw new ArgumentException("You MUST set ClientSecret or Cl ientSecretStream on the initializer"); 157 throw new ArgumentException("You MUST set ClientSecret or Cl ientSecretStream on the initializer");
158 } 158 }
159 159
160 using (initializer.ClientSecretsStream) 160 using (initializer.ClientSecretsStream)
161 { 161 {
162 clientSecrets = GoogleClientSecrets.Load(initializer.ClientS ecretsStream).Secrets; 162 clientSecrets = GoogleClientSecrets.Load(initializer.ClientS ecretsStream).Secrets;
163 } 163 }
164 } 164 }
165
166
167 165
168 accessMethod = initializer.AccessMethod.ThrowIfNull("Initializer.Acc essMethod"); 166 accessMethod = initializer.AccessMethod.ThrowIfNull("Initializer.Acc essMethod");
169 clock = initializer.Clock.ThrowIfNull("Initializer.Clock"); 167 clock = initializer.Clock.ThrowIfNull("Initializer.Clock");
170 tokenServerUrl = initializer.TokenServerUrl.ThrowIfNullOrEmpty("Init ializer.TokenServerUrl"); 168 tokenServerUrl = initializer.TokenServerUrl.ThrowIfNullOrEmpty("Init ializer.TokenServerUrl");
171 authorizationServerUrl = initializer.AuthorizationServerUrl.ThrowIfN ullOrEmpty 169 authorizationServerUrl = initializer.AuthorizationServerUrl.ThrowIfN ullOrEmpty
172 ("Initializer.AuthorizationServerUrl"); 170 ("Initializer.AuthorizationServerUrl");
173 171
174 dataStore = initializer.DataStore; 172 dataStore = initializer.DataStore;
175 if (dataStore == null) 173 if (dataStore == null)
176 { 174 {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param> 280 /// <param name="taskCancellationToken">Cancellation token to cancel ope ration</param>
283 /// <returns>Token response with the new access token</returns> 281 /// <returns>Token response with the new access token</returns>
284 [VisibleForTestOnly] 282 [VisibleForTestOnly]
285 internal async Task<TokenResponse> FetchTokenAsync(string userId, TokenR equest request, 283 internal async Task<TokenResponse> FetchTokenAsync(string userId, TokenR equest request,
286 CancellationToken taskCancellationToken) 284 CancellationToken taskCancellationToken)
287 { 285 {
288 // Add client id and client secret to requests. 286 // Add client id and client secret to requests.
289 request.ClientId = ClientSecrets.ClientId; 287 request.ClientId = ClientSecrets.ClientId;
290 request.ClientSecret = ClientSecrets.ClientSecret; 288 request.ClientSecret = ClientSecrets.ClientSecret;
291 289
292 var httpRequest = new HttpRequestMessage(HttpMethod.Post, TokenServe rEncodedUrl); 290 TokenResponseException tokenException = null;
293 httpRequest.Content = ParameterUtils.CreateFormUrlEncodedContent(req uest); 291 try
294 292 {
295 var response = await HttpClient.SendAsync(httpRequest, taskCancellat ionToken).ConfigureAwait(false); 293 var tokenResponse = await request.Execute(httpClient, TokenServe rUrl, taskCancellationToken, Clock);
296 294 return tokenResponse;
297 taskCancellationToken.ThrowIfCancellationRequested(); 295 }
298 296 catch (TokenResponseException ex)
299 var content = await response.Content.ReadAsStringAsync().ConfigureAw ait(false); 297 {
300 if (!response.IsSuccessStatusCode) 298 // In case there is an exception during getting the token, we de lete any user's token information from·
301 { 299 // the data store.
302 var error = NewtonsoftJsonSerializer.Instance.Deserialize<TokenE rrorResponse>(content); 300 tokenException = ex;
303 await DeleteTokenAsync(userId, taskCancellationToken); 301 }
304 throw new TokenResponseException(error); 302 await DeleteTokenAsync(userId, taskCancellationToken);
305 } 303 throw tokenException;
306
307 // Get the token and sets its issued time.
308 var token = NewtonsoftJsonSerializer.Instance.Deserialize<TokenRespo nse>(content);
309 token.Issued = clock.Now;
310
311 return token;
312 } 304 }
313 305
314 public void Dispose() 306 public void Dispose()
315 { 307 {
316 if (HttpClient != null) 308 if (HttpClient != null)
317 { 309 {
318 HttpClient.Dispose(); 310 HttpClient.Dispose();
319 } 311 }
320 } 312 }
321 } 313 }
322 } 314 }
LEFTRIGHT

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