Skip to content

Commit e3ed36b

Browse files
committed
Refactored to SimpleTest and OAuthPKCE program file differences were minimal and germane to the different approaches.
1 parent b5b2763 commit e3ed36b

File tree

2 files changed

+187
-162
lines changed

2 files changed

+187
-162
lines changed

dropbox-sdk-dotnet/Examples/OAuthPKCE/Program.cs

Lines changed: 81 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ private async Task<int> Run()
4444
Console.WriteLine("Example OAuth PKCE Application");
4545
DropboxCertHelper.InitializeCertPinning();
4646

47-
var uid = await AcquireOAuthTokens(null, IncludeGrantedScopes.None);
48-
if (string.IsNullOrEmpty(uid))
47+
string accessToken = await GetOAuthTokens(null, IncludeGrantedScopes.None);
48+
if (string.IsNullOrEmpty(accessToken))
4949
{
5050
return 1;
5151
}
@@ -68,11 +68,8 @@ private async Task<int> Run()
6868
};
6969

7070
var client = new DropboxClient(Settings.Default.RefreshToken, Settings.Default.ApiKey, config);
71+
await GetCurrentAccount(client); // This call should succeed since the correct scope has been acquired
7172

72-
// This call should succeed since the correct scope has been acquired
73-
await GetCurrentAccount(client);
74-
75-
Console.WriteLine("Oauth PKCE Test Complete!");
7673
Console.WriteLine("Exit with any key");
7774
Console.ReadKey();
7875
}
@@ -90,6 +87,7 @@ private async Task<int> Run()
9087
return 0;
9188
}
9289

90+
9391
/// <summary>
9492
/// Handles the redirect from Dropbox server. Because we are using token flow, the local
9593
/// http server cannot directly receive the URL fragment. We need to return a HTML page with
@@ -135,9 +133,7 @@ private async Task<Uri> HandleJSRedirect(HttpListener http)
135133
context = await http.GetContextAsync();
136134
}
137135

138-
var redirectUri = new Uri(context.Request.QueryString["url_with_fragment"]);
139-
140-
return redirectUri;
136+
return new Uri(context.Request.QueryString["url_with_fragment"]);
141137
}
142138

143139
/// <summary>
@@ -148,8 +144,8 @@ private async Task<Uri> HandleJSRedirect(HttpListener http)
148144
/// displayed to authorize the user.
149145
/// </para>
150146
/// </summary>
151-
/// <returns>A valid uid if a token was acquired or null.</returns>
152-
private async Task<string> AcquireOAuthTokens(string[] scopeList, IncludeGrantedScopes includeGrantedScopes)
147+
/// <returns>A valid access token if successful otherwise null.</returns>
148+
private async Task<string> GetOAuthTokens(string[] scopeList, IncludeGrantedScopes includeGrantedScopes)
153149
{
154150
Settings.Default.Upgrade();
155151
Console.Write("Reset settings (Y/N) ");
@@ -159,32 +155,34 @@ private async Task<string> AcquireOAuthTokens(string[] scopeList, IncludeGranted
159155
}
160156
Console.WriteLine();
161157

162-
string accessToken = Settings.Default.AccessToken;
163-
string uid = Settings.Default.Uid;
164-
165-
if (string.IsNullOrEmpty(accessToken))
158+
if (string.IsNullOrEmpty(Settings.Default.AccessToken))
166159
{
167160
string apiKey = GetApiKey();
168161

169162
using var http = new HttpListener();
170163
try
171164
{
172-
Console.WriteLine("Waiting for credentials.");
173165
string state = Guid.NewGuid().ToString("N");
174166
var OAuthFlow = new PKCEOAuthFlow();
175-
var authorizeUri = OAuthFlow.GetAuthorizeUri(OAuthResponseType.Code, apiKey, RedirectUri.ToString(), state: state, tokenAccessType: TokenAccessType.Offline, scopeList: scopeList, includeGrantedScopes: includeGrantedScopes);
167+
var authorizeUri = OAuthFlow.GetAuthorizeUri(
168+
OAuthResponseType.Code, apiKey, RedirectUri.ToString(),
169+
state: state, tokenAccessType: TokenAccessType.Offline,
170+
scopeList: scopeList, includeGrantedScopes: includeGrantedScopes);
171+
176172
http.Prefixes.Add(LoopbackHost);
177173

178174
http.Start();
179175

176+
// Use StartInfo to ensure default browser launches.
180177
ProcessStartInfo startInfo = new ProcessStartInfo(
181-
authorizeUri.ToString()){ UseShellExecute = true };
178+
authorizeUri.ToString())
179+
{ UseShellExecute = true };
182180

183181
try
184182
{
185183
// open browser for authentication
184+
Console.WriteLine("Waiting for credentials and authorization.");
186185
Process.Start(startInfo);
187-
Console.WriteLine("Waiting for authentication...");
188186
}
189187
catch (Exception)
190188
{
@@ -199,33 +197,24 @@ private async Task<string> AcquireOAuthTokens(string[] scopeList, IncludeGranted
199197

200198
http.Stop();
201199

202-
Console.WriteLine("Exchanging code for token");
203-
var tokenResult = await OAuthFlow.ProcessCodeFlowAsync(redirectUri, apiKey, RedirectUri.ToString(), state);
204-
Console.WriteLine("Finished Exchanging Code for Token");
205-
// Bring console window to the front.
206-
SetForegroundWindow(GetConsoleWindow());
207-
accessToken = tokenResult.AccessToken;
208-
string refreshToken = tokenResult.RefreshToken;
209-
uid = tokenResult.Uid;
210-
Console.WriteLine("Uid: {0}", uid);
211-
Console.WriteLine("AccessToken: {0}", accessToken);
212-
if (tokenResult.RefreshToken != null)
200+
// Exchanging code for token
201+
var result = await OAuthFlow.ProcessCodeFlowAsync(
202+
redirectUri, apiKey, RedirectUri.ToString(), state);
203+
if (result.State != state)
213204
{
214-
Console.WriteLine("RefreshToken: {0}", refreshToken);
215-
Settings.Default.RefreshToken = refreshToken;
205+
// NOTE: Rightly or wrongly?, state is not returned or else
206+
// we would return null here.
207+
// See issue https://github.com/dropbox/dropbox-sdk-dotnet/issues/248
208+
Console.WriteLine("The state in the response doesn't match the state in the request.");
216209
}
217-
if (tokenResult.ExpiresAt != null)
218-
{
219-
Console.WriteLine("ExpiresAt: {0}", tokenResult.ExpiresAt);
220-
}
221-
if (tokenResult.ScopeList != null)
222-
{
223-
Console.WriteLine("Scopes: {0}", String.Join(" ", tokenResult.ScopeList));
224-
}
225-
Settings.Default.AccessToken = accessToken;
226-
Settings.Default.Uid = uid;
227-
Settings.Default.Save();
228-
Settings.Default.Reload();
210+
Console.WriteLine("OAuth token aquire complete");
211+
212+
// Bring console window to the front.
213+
SetForegroundWindow(GetConsoleWindow());
214+
215+
DisplayOAuthResult(result);
216+
217+
UpdateSettings(result);
229218
}
230219
catch (Exception e)
231220
{
@@ -234,7 +223,32 @@ private async Task<string> AcquireOAuthTokens(string[] scopeList, IncludeGranted
234223
}
235224
}
236225

237-
return uid;
226+
return Settings.Default.AccessToken;
227+
}
228+
229+
private static void UpdateSettings(OAuth2Response result)
230+
{
231+
// Foreach Settting, save off the value retrieved from the result.
232+
foreach (System.Configuration.SettingsProperty item in Settings.Default.Properties)
233+
{
234+
if (typeof(OAuth2Response).GetProperty(item.Name) is System.Reflection.PropertyInfo property)
235+
{
236+
Settings.Default[item.Name] = property.GetValue(result);
237+
}
238+
}
239+
240+
Settings.Default.Save();
241+
Settings.Default.Reload();
242+
}
243+
244+
private static void DisplayOAuthResult(OAuth2Response result)
245+
{
246+
Console.WriteLine("OAuth Result:");
247+
Console.WriteLine("\tUid: {0}", result.Uid);
248+
Console.WriteLine("\tAccessToken: {0}", result.AccessToken);
249+
Console.WriteLine("\tRefreshToken: {0}", result.RefreshToken);
250+
Console.WriteLine("\tExpiresAt: {0}", result.ExpiresAt);
251+
Console.WriteLine("\tScopes: {0}", string.Join(" ", result.ScopeList?? new string[0]));
238252
}
239253

240254
/// <summary>
@@ -273,41 +287,33 @@ private static string GetApiKey()
273287
/// </summary>
274288
/// <param name="client">The Dropbox client.</param>
275289
/// <returns>An asynchronous task.</returns>
276-
private async Task GetCurrentAccount(DropboxClient client)
290+
static private async Task GetCurrentAccount(DropboxClient client)
277291
{
278-
try
292+
Console.WriteLine("Current Account:");
293+
var full = await client.Users.GetCurrentAccountAsync();
294+
295+
Console.WriteLine("Account id : {0}", full.AccountId);
296+
Console.WriteLine("Country : {0}", full.Country);
297+
Console.WriteLine("Email : {0}", full.Email);
298+
Console.WriteLine("Is paired : {0}", full.IsPaired ? "Yes" : "No");
299+
Console.WriteLine("Locale : {0}", full.Locale);
300+
Console.WriteLine("Name");
301+
Console.WriteLine(" Display : {0}", full.Name.DisplayName);
302+
Console.WriteLine(" Familiar : {0}", full.Name.FamiliarName);
303+
Console.WriteLine(" Given : {0}", full.Name.GivenName);
304+
Console.WriteLine(" Surname : {0}", full.Name.Surname);
305+
Console.WriteLine("Referral link : {0}", full.ReferralLink);
306+
307+
if (full.Team != null)
279308
{
280-
Console.WriteLine("Current Account:");
281-
var full = await client.Users.GetCurrentAccountAsync();
282-
283-
Console.WriteLine("Account id : {0}", full.AccountId);
284-
Console.WriteLine("Country : {0}", full.Country);
285-
Console.WriteLine("Email : {0}", full.Email);
286-
Console.WriteLine("Is paired : {0}", full.IsPaired ? "Yes" : "No");
287-
Console.WriteLine("Locale : {0}", full.Locale);
288-
Console.WriteLine("Name");
289-
Console.WriteLine(" Display : {0}", full.Name.DisplayName);
290-
Console.WriteLine(" Familiar : {0}", full.Name.FamiliarName);
291-
Console.WriteLine(" Given : {0}", full.Name.GivenName);
292-
Console.WriteLine(" Surname : {0}", full.Name.Surname);
293-
Console.WriteLine("Referral link : {0}", full.ReferralLink);
294-
295-
if (full.Team != null)
296-
{
297-
Console.WriteLine("Team");
298-
Console.WriteLine(" Id : {0}", full.Team.Id);
299-
Console.WriteLine(" Name : {0}", full.Team.Name);
300-
}
301-
else
302-
{
303-
Console.WriteLine("Team - None");
304-
}
309+
Console.WriteLine("Team");
310+
Console.WriteLine(" Id : {0}", full.Team.Id);
311+
Console.WriteLine(" Name : {0}", full.Team.Name);
305312
}
306-
catch (Exception e)
313+
else
307314
{
308-
throw e;
315+
Console.WriteLine("Team - None");
309316
}
310-
311317
}
312318
}
313319
}

0 commit comments

Comments
 (0)