OLD | NEW |
(Empty) | |
| 1 /* |
| 2 Copyright 2014 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.Threading; |
| 19 using System.Threading.Tasks; |
| 20 using Windows.Security.Authentication.Web; |
| 21 using Windows.ApplicationModel.Core; |
| 22 using Windows.UI.Core; |
| 23 |
| 24 using Google.Apis.Auth.OAuth2.Requests; |
| 25 using Google.Apis.Auth.OAuth2.Responses; |
| 26 using Google.Apis.Util.Store; |
| 27 |
| 28 namespace Google.Apis.Auth.OAuth2 |
| 29 { |
| 30 /// <summary> |
| 31 /// OAuth 2.0 verification code receiver for Windows Phone 8.1 application t
hat opens a Google account form so the |
| 32 /// users can enter their credentials and accept the application access to t
heir token. |
| 33 ///· |
| 34 /// This broker's most important method is <see cref="ReceiveCodeAsync"/>. |
| 35 /// The first time it is being called, it calls <code>WebAuthenticationBroke
r.AuthenticateAndContinue</code> |
| 36 /// so the users can authorize the app to access their private resources. Wh
ile calling this method the app is |
| 37 /// suspended. |
| 38 ///· |
| 39 /// When the app is being activated again, the developer MUST store the auth
result (which may contain the access |
| 40 /// code or an error) in the storage with the <code>SerializableWebAuthResul
t.Name</code> key. |
| 41 /// Then when the auth framework calls again the <see cref="ReceiveCodeAsync
"/> it looks in the storage to find |
| 42 /// the auth result, and if a code was received the framework will convert i
t in turn to access and refresh tokens. |
| 43 /// </summary> |
| 44 public class AuthorizationCodeBroker : ICodeReceiver |
| 45 { |
| 46 #region ICodeReceiver Members |
| 47 |
| 48 public string RedirectUri |
| 49 { |
| 50 get { return GoogleAuthConsts.LocalhostRedirectUri; } |
| 51 } |
| 52 |
| 53 public async Task<AuthorizationCodeResponseUrl> ReceiveCodeAsync(Authori
zationCodeRequestUrl url, |
| 54 CancellationToken taskCancellationToken) |
| 55 { |
| 56 TaskCompletionSource<AuthorizationCodeResponseUrl> tcs = |
| 57 new TaskCompletionSource<AuthorizationCodeResponseUrl>(); |
| 58 await ReceiveCodeAsync(url, tcs); |
| 59 return tcs.Task.Result; |
| 60 } |
| 61 |
| 62 #endregion |
| 63 |
| 64 private async Task InvokeFromUIThread(Action action) |
| 65 { |
| 66 await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDi
spatcherPriority.Normal, |
| 67 () => action()); |
| 68 } |
| 69 |
| 70 /// <summary>Asynchronously receives the authorization code.</summary> |
| 71 /// <param name="url">The authorization code request URL.</param> |
| 72 /// <param name="tcs">Task completion source whose result will be set to
the authorization code.</param> |
| 73 private async Task ReceiveCodeAsync(AuthorizationCodeRequestUrl url, |
| 74 TaskCompletionSource<AuthorizationCodeResponseUrl> tcs) |
| 75 { |
| 76 var result = await PasswordVaultDataStore.Default.GetAsync<Serializa
bleWebAuthResult>( |
| 77 SerializableWebAuthResult.Name); |
| 78 if (result == null) |
| 79 { |
| 80 // We should run WebAuthenticationBroker.AuthenticateAndContinue
from the UI thread ONLY. |
| 81 await InvokeFromUIThread(() => WebAuthenticationBroker.Authentic
ateAndContinue(url.Build(), |
| 82 new Uri(GoogleAuthConsts.LocalhostRedirectUri), null, WebAut
henticationOptions.None)); |
| 83 ················ |
| 84 // No need to return anything, cause the application is going to
be suspended now. |
| 85 return; |
| 86 } |
| 87 |
| 88 const string Code = "code="; |
| 89 const string Error = "error="; |
| 90 // Get the index of the error or the code. |
| 91 var index = result.ResponseData.IndexOf(Code); |
| 92 index = index != -1 ? index : result.ResponseData.IndexOf(Error); |
| 93 |
| 94 if (index != -1) |
| 95 { |
| 96 tcs.SetResult(new AuthorizationCodeResponseUrl(result.ResponseDa
ta.Substring(index))); |
| 97 return; |
| 98 } |
| 99 |
| 100 tcs.SetException(new TokenResponseException( |
| 101 new TokenErrorResponse |
| 102 { |
| 103 Error = result.ResponseStatus.ToString(), |
| 104 ErrorDescription = "The WebAuthenticationBroker didn't retur
n a code or an error. Details: " + |
| 105 result.ResponseErrorDetail, |
| 106 })); |
| 107 } |
| 108 } |
| 109 } |
OLD | NEW |