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

Side by Side Diff: Src/GoogleApis.Auth.Tests/OAuth2/AuthorizationCodeFlowTests.cs

Issue 13972043: Issue 351: Reimplement OAuth2 (Step 3 - Tests, Flows and Credential) (Closed) Base URL: https://google-api-dotnet-client.googlecode.com/hg/
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:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 Copyright 2013 Google Inc
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.Linq;
20 using System.Net.Http;
21 using System.Text;
22 using System.Threading;
23 using System.Threading.Tasks;
24
25 using Moq;
26 using NUnit.Framework;
27
28 using Google.Apis.Auth.OAuth2.Requests;
29 using Google.Apis.Auth.OAuth2.Responses;
30 using Google.Apis.Http;
31 using Google.Apis.Json;
32 using Google.Apis.Testing;
33 using Google.Apis.Tests;
34 using Google.Apis.Util;
35 using Google.Apis.Util.Store;
36
37 namespace Google.Apis.Auth.OAuth2
38 {
39 /// <summary>Tests for <see cref="Google.Apis.Auth.OAuth2.AuthorizationCodeF low"/>.</summary>
40 [TestFixture]
41 public class AuthorizationCodeFlowTests
42 {
43 private const string TokenUrl = "https://token.com";
44 private const string AuthorizationCodeUrl = "https://authorization.com";
45
46 #region Constructor
47
48 [Test]
49 public void TestConstructor_ArgumentException()
50 {
51 // ClientSecrets are missing.
52 try
53 {
54 new AuthorizationCodeFlow(new AuthorizationCodeFlow.Initializer(
55 "https://authorization_code.com", "https://token.com"));
56 Assert.Fail();
57 }
58 catch (ArgumentException ex)
59 {
60 Assert.True(ex.Message.Contains("You MUST set ClientSecret or Cl ientSecretStream"));
61 }
62 }
63
64 [Test]
65 public void TestConstructor_DefaultValues()
66 {
67 var flow = CreateFlow();
68 Assert.NotNull(flow.AccessMethod);
69 Assert.That(flow.AccessMethod, Is.InstanceOf<BearerToken.Authorizati onHeaderAccessMethod>());
70 Assert.That(flow.AuthorizationServerUrl, Is.EqualTo("https://authori zation.com"));
71 Assert.NotNull(flow.ClientSecrets);
72 Assert.That(flow.ClientSecrets.ClientId, Is.EqualTo("id"));
73 Assert.That(flow.ClientSecrets.ClientSecret, Is.EqualTo("secret"));
74 Assert.That(flow.Clock, Is.InstanceOf<SystemClock>());
75 Assert.Null(flow.DataStore);
76 Assert.NotNull(flow.HttpClient);
77 Assert.NotNull(flow.Scopes);
78 Assert.That(flow.TokenServerUrl, Is.EqualTo("https://token.com"));
79
80 Assert.That(flow.HttpClient.MessageHandler.UnsuccessfulResponseHandl ers.Count(), Is.EqualTo(1));
81 Assert.That(flow.HttpClient.MessageHandler.UnsuccessfulResponseHandl ers.First(),
82 Is.InstanceOf<BackOffHandler>());
83 }
84
85 #endregion
86
87 #region LoadToken
88
89 [Test]
90 public void LoadTokenAsync_NoDataStore()
91 {
92 var flow = CreateFlow();
93 Assert.Null(flow.LoadTokenAsync("user", CancellationToken.None).Resu lt);
94 }
95
96 [Test]
97 public void LoadTokenAsync_NullResponse()
98 {
99 TaskCompletionSource<TokenResponse> tcs = new TaskCompletionSource<T okenResponse>();
100 tcs.SetResult(null);
101 Assert.Null(SubtestLoadTokenAsync(tcs));
102 }
103
104 [Test]
105 public void LoadTokenAsync_TokenResponse()
106 {
107 TokenResponse response = new TokenResponse
108 {
109 AccessToken = "access"
110 };
111
112 TaskCompletionSource<TokenResponse> tcs = new TaskCompletionSource<T okenResponse>();
113 tcs.SetResult(response);
114 var result = SubtestLoadTokenAsync(tcs);
115 Assert.That(result, Is.EqualTo(response));
116 }
117
118 private TokenResponse SubtestLoadTokenAsync(TaskCompletionSource<TokenRe sponse> tcs)
119 {
120 var mock = new Mock<IDataStore>();
121 mock.Setup(ds => ds.GetAsync<TokenResponse>("user")).Returns(tcs.Tas k);
122 var flow = CreateFlow(dataStore: mock.Object);
123 var result = flow.LoadTokenAsync("user", CancellationToken.None).Res ult;
124 mock.Verify(ds => ds.GetAsync<TokenResponse>("user"));
125 return result;
126 }
127
128 #endregion
129
130 #region CreateAuthorizationCodeRequest
131
132 [Test]
133 public void TestCreateAuthorizationCodeRequest()
134 {
135 var request = CreateFlow(scopes: new[] { "a", "b" }).CreateAuthoriza tionCodeRequest("redirect");
136 Assert.That(request.AuthorizationServerUrl, Is.EqualTo(new Uri(Autho rizationCodeUrl)));
137 Assert.That(request.ClientId, Is.EqualTo("id"));
138 Assert.That(request.RedirectUri, Is.EqualTo("redirect"));
139 Assert.That(request.ResponseType, Is.EqualTo("code"));
140 Assert.That(request.Scope, Is.EqualTo("a b"));
141 Assert.Null(request.State);
142 }
143
144 #endregion
145
146 [Test]
147 public void TestExchangeCodeForTokenAsync()
148 {
149 var mock = new Mock<IDataStore>();
150 var handler = new FetchTokenMessageHandler();
151 handler.AuthorizationCodeTokenRequest = new AuthorizationCodeTokenRe quest()
152 {
153 Code = "c0de",
154 RedirectUri = "redIrect",
155 Scope = "a"
156 };
157 MockHttpClientFactory mockFactory = new MockHttpClientFactory(handle r);
158
159 TaskCompletionSource<object> tcs = new TaskCompletionSource<object>( );
160 tcs.SetResult(null);
161 mock.Setup(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>())).R eturns(tcs.Task);
162
163 var flow = CreateFlow(httpClientFactory: mockFactory, scopes: new[] { "a" }, dataStore: mock.Object);
164 var response = flow.ExchangeCodeForTokenAsync("uSer", "c0de", "redIr ect", CancellationToken.None).Result;
165 SubtestTokenResponse(response);
166
167 mock.Verify(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>()));
168 }
169
170 [Test]
171 public void TestRefreshTokenAsync()
172 {
173 var mock = new Mock<IDataStore>();
174 var handler = new FetchTokenMessageHandler();
175 handler.RefreshTokenRequest = new RefreshTokenRequest()
176 {
177 RefreshToken = "REFRESH",
178 Scope = "a"
179 };
180 MockHttpClientFactory mockFactory = new MockHttpClientFactory(handle r);
181
182 TaskCompletionSource<object> tcs = new TaskCompletionSource<object>( );
183 tcs.SetResult(null);
184 mock.Setup(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>())).R eturns(tcs.Task);
185
186 var flow = CreateFlow(httpClientFactory: mockFactory, scopes: new[] { "a" }, dataStore: mock.Object);
187 var response = flow.RefreshTokenAsync("uSer", "REFRESH", Cancellatio nToken.None).Result;
188 SubtestTokenResponse(response);
189
190
191 mock.Verify(ds => ds.StoreAsync("uSer", It.IsAny<TokenResponse>()));
192 }
193
194 #region FetchToken
195
196 /// <summary>
197 /// Fetch token message handler, which expects an authorization code tok en request or a refresh token request.
198 /// It verifies all the query parameters are valid and return an error r esponse in case <see cref="Error"/>·
199 /// is <c>true</c>.
200 /// </summary>
201 public class FetchTokenMessageHandler : CountableMessageHandler
202 {
203 internal AuthorizationCodeTokenRequest AuthorizationCodeTokenRequest { get; set; }
204 internal RefreshTokenRequest RefreshTokenRequest { get; set; }
205 internal bool Error { get; set; }
206
207 protected override async Task<HttpResponseMessage> SendAsyncCore(Htt pRequestMessage request,
208 CancellationToken taskCancellationToken)
209 {
210 Assert.That(request.RequestUri, Is.EqualTo(new Uri(TokenUrl)));
211
212 if (AuthorizationCodeTokenRequest != null)
213 {
214 // Verify right parameters.
215 var content = await request.Content.ReadAsStringAsync();
216 foreach (var parameter in content.Split('&'))
217 {
218 var keyValue = parameter.Split('=');
219 switch (keyValue[0])
220 {
221 case "code":
222 Assert.That(keyValue[1], Is.EqualTo("c0de"));
223 break;
224 case "redirect_uri":
225 Assert.That(keyValue[1], Is.EqualTo("redIrect")) ;
226 break;
227 case "scope":
228 Assert.That(keyValue[1], Is.EqualTo("a"));
229 break;
230 case "grant_type":
231 Assert.That(keyValue[1], Is.EqualTo("authorizati on_code"));
232 break;
233 case "client_id":
234 Assert.That(keyValue[1], Is.EqualTo("id"));
235 break;
236 case "client_secret":
237 Assert.That(keyValue[1], Is.EqualTo("secret"));
238 break;
239 default:
240 throw new ArgumentOutOfRangeException("Invalid p arameter!");
241 }
242 }
243 }
244 else
245 {
246 // Verify right parameters.
247 var content = await request.Content.ReadAsStringAsync();
248 foreach (var parameter in content.Split('&'))
249 {
250 var keyValue = parameter.Split('=');
251 switch (keyValue[0])
252 {
253 case "refresh_token":
254 Assert.That(keyValue[1], Is.EqualTo("REFRESH"));
255 break;
256 case "scope":
257 Assert.That(keyValue[1], Is.EqualTo("a"));
258 break;
259 case "grant_type":
260 Assert.That(keyValue[1], Is.EqualTo("refresh_tok en"));
261 break;
262 case "client_id":
263 Assert.That(keyValue[1], Is.EqualTo("id"));
264 break;
265 case "client_secret":
266 Assert.That(keyValue[1], Is.EqualTo("secret"));
267 break;
268 default:
269 throw new ArgumentOutOfRangeException("Invalid p arameter!");
270 }
271 }
272 }
273
274 var response = new HttpResponseMessage();
275 if (Error)
276 {
277 response.StatusCode = System.Net.HttpStatusCode.BadRequest;
278 var serializedObject = NewtonsoftJsonSerializer.Instance.Ser ialize(new TokenErrorResponse
279 {
280 Error = "error",
281 ErrorDescription = "desc",
282 ErrorUri = "uri"
283 });
284 response.Content = new StringContent(serializedObject, Encod ing.UTF8);
285 }
286 else
287 {
288 var serializedObject = NewtonsoftJsonSerializer.Instance.Ser ialize(new TokenResponse
289 {
290 AccessToken = "a",
291 RefreshToken = "r",
292 ExpiresInSeconds = 100,
293 Scope = "b",
294 });
295 response.Content = new StringContent(serializedObject, Encod ing.UTF8);
296 }
297
298 return response;
299 }
300 }
301
302 [Test]
303 public void TestFetchTokenAsync_AuthorizationCodeRequest()
304 {
305 var handler = new FetchTokenMessageHandler();
306 handler.AuthorizationCodeTokenRequest = new AuthorizationCodeTokenRe quest()
307 {
308 Code = "c0de",
309 RedirectUri = "redIrect",
310 Scope = "a"
311 };
312 MockHttpClientFactory mockFactory = new MockHttpClientFactory(handle r);
313
314 var flow = CreateFlow(httpClientFactory: mockFactory);
315 var response = flow.FetchTokenAsync("user", handler.AuthorizationCod eTokenRequest,
316 CancellationToken.None).Result;
317 SubtestTokenResponse(response);
318 }
319
320 [Test]
321 public void TestFetchTokenAsync_RefreshTokenRequest()
322 {
323 var handler = new FetchTokenMessageHandler();
324 handler.RefreshTokenRequest = new RefreshTokenRequest()
325 {
326 RefreshToken = "REFRESH",
327 Scope = "a"
328 };
329
330 MockHttpClientFactory mockFactory = new MockHttpClientFactory(handle r);
331
332 var flow = CreateFlow(httpClientFactory: mockFactory);
333 var response = flow.FetchTokenAsync("user", handler.RefreshTokenRequ est, CancellationToken.None).Result;
334 SubtestTokenResponse(response);
335 }
336
337 [Test]
338 public void TestFetchTokenAsync_AuthorizationCodeRequest_Error()
339 {
340 var handler = new FetchTokenMessageHandler();
341 handler.AuthorizationCodeTokenRequest = new AuthorizationCodeTokenRe quest()
342 {
343 Code = "c0de",
344 RedirectUri = "redIrect",
345 Scope = "a"
346 };
347 handler.Error = true;
348 SubtestFetchTokenAsync_Error(handler);
349 }
350
351 [Test]
352 public void TestFetchTokenAsync_RefreshTokenRequest_Error()
353 {
354 var handler = new FetchTokenMessageHandler();
355 handler.RefreshTokenRequest = new RefreshTokenRequest()
356 {
357 RefreshToken = "REFRESH",
358 Scope = "a"
359 };
360 handler.Error = true;
361 SubtestFetchTokenAsync_Error(handler);
362 }
363
364 /// <summary>Subtest for receiving an error token response.</summary>
365 /// <param name="handler">The message handler.</param>
366 private void SubtestFetchTokenAsync_Error(FetchTokenMessageHandler handl er)
367 {
368 MockHttpClientFactory mockFactory = new MockHttpClientFactory(handle r);
369 var flow = CreateFlow(httpClientFactory: mockFactory);
370 try
371 {
372 var request =
373 (TokenRequest)handler.AuthorizationCodeTokenRequest ?? (Toke nRequest)handler.RefreshTokenRequest;
374 var result = flow.FetchTokenAsync("user", request, CancellationT oken.None).Result;
375 Assert.Fail();
376 }
377 catch (AggregateException aex)
378 {
379 var ex = aex.InnerException as TokenResponseException;
380 Assert.IsNotNull(ex);
381 var result = ex.Error;
382 Assert.That(result.Error, Is.EqualTo("error"));
383 Assert.That(result.ErrorDescription, Is.EqualTo("desc"));
384 Assert.That(result.ErrorUri, Is.EqualTo("uri"));
385 }
386 }
387
388 #endregion
389
390 /// <summary>Creates an authorization code flow with the given parameter s.</summary>
391 /// <param name="dataStore">The data store.</param>
392 /// <param name="scopes">The Scopes.</param>
393 /// <param name="httpClientFactory">The HTTP client factory. If not set the default will be used.</param>
394 /// <returns>Authorization code flow</returns>
395 private AuthorizationCodeFlow CreateFlow(IDataStore dataStore = null, IE numerable<string> scopes = null,
396 IHttpClientFactory httpClientFactory = null)
397 {
398 var secrets = new ClientSecrets() { ClientId = "id", ClientSecret = "secret" };
399 var initializer = new AuthorizationCodeFlow.Initializer(Authorizatio nCodeUrl, TokenUrl)
400 {
401 ClientSecrets = secrets,
402 HttpClientFactory = httpClientFactory
403 };
404
405 if (dataStore != null)
406 {
407 initializer.DataStore = dataStore;
408 }
409 if (scopes != null)
410 {
411 initializer.Scopes = scopes;
412 }
413 return new AuthorizationCodeFlow(initializer);
414 }
415
416 /// <summary>Verifies that the token response contains the expected data .</summary>
417 /// <param name="response">The token response</param>
418 private void SubtestTokenResponse(TokenResponse response)
419 {
420 Assert.That(response.RefreshToken, Is.EqualTo("r"));
421 Assert.That(response.ExpiresInSeconds, Is.EqualTo(100));
422 Assert.That(response.Scope, Is.EqualTo("b"));
423 }
424 }
425 }
OLDNEW
« no previous file with comments | « Src/GoogleApis.Auth.Tests/GoogleApis.Auth.Tests.csproj ('k') | Src/GoogleApis.Auth.Tests/OAuth2/BearerTokenTests.cs » ('j') | no next file with comments »

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