LEFT | RIGHT |
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 Loading... |
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 Loading... |
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 } |
LEFT | RIGHT |