Skip to content
This repository was archived by the owner on Oct 2, 2024. It is now read-only.

Commit 5322c88

Browse files
committed
Merge pull request #53 from OneDrive/dev
Authentication and exception handling bug fixes
2 parents d63f213 + 39de388 commit 5322c88

33 files changed

+807
-244
lines changed

samples/OneDriveApiBrowser/FormBrowser.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ private async Task SignIn(ClientType clientType)
330330
}
331331
else
332332
{
333-
throw;
333+
PresentOneDriveException(exception);
334334
}
335335
}
336336
}
@@ -473,10 +473,15 @@ await this.oneDriveClient.Drive.Items[this.SelectedItem.Id].Children.Request()
473473

474474
private static void PresentOneDriveException(Exception exception)
475475
{
476-
string message = exception.Message;
477-
if (string.IsNullOrEmpty(message) && exception.InnerException != null)
476+
string message = null;
477+
var oneDriveException = exception as OneDriveException;
478+
if (oneDriveException == null)
478479
{
479-
message = exception.InnerException.Message;
480+
message = exception.Message;
481+
}
482+
else
483+
{
484+
message = string.Format("{0}{1}", Environment.NewLine, oneDriveException.ToString());
480485
}
481486

482487
MessageBox.Show(string.Format("OneDrive reported the following error: {0}", message));

src/OneDriveSdk.Common/Authentication/AdalAuthenticationProviderBase.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace Microsoft.OneDrive.Sdk
2727
using System.Net.Http;
2828
using System.Net.Http.Headers;
2929
using System.Threading.Tasks;
30+
using Microsoft.IdentityModel.Clients.ActiveDirectory;
3031

3132
public abstract class AdalAuthenticationProviderBase : IAuthenticationProvider
3233
{
@@ -161,6 +162,13 @@ protected void DeleteUserCredentialsFromCache(AccountSession accountSession)
161162
}
162163
}
163164

165+
protected UserIdentifier GetUserIdentifierForAuthentication()
166+
{
167+
return string.IsNullOrEmpty(this.serviceInfo.UserId)
168+
? UserIdentifier.AnyUser
169+
: new UserIdentifier(this.serviceInfo.UserId, UserIdentifierType.OptionalDisplayableId);
170+
}
171+
164172
private async Task<string> GetAuthenticationTokenForResourceAsync(string resource)
165173
{
166174
var authenticationResult = await this.AuthenticateResourceAsync(resource);

src/OneDriveSdk.WinRT/Authentication/AdalAuthenticationProvider.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ public override async Task SignOutAsync()
6060
protected override async Task<IAuthenticationResult> AuthenticateResourceAsync(string resource)
6161
{
6262
IAuthenticationResult authenticationResult = null;
63+
var userIdentifier = this.GetUserIdentifierForAuthentication();
6364

6465
try
6566
{
66-
authenticationResult = await this.authenticationContextWrapper.AcquireTokenSilentAsync(resource, this.serviceInfo.AppId);
67+
authenticationResult = await this.authenticationContextWrapper.AcquireTokenSilentAsync(resource, this.serviceInfo.AppId, userIdentifier);
6768
}
6869
catch (Exception)
6970
{
@@ -78,7 +79,9 @@ protected override async Task<IAuthenticationResult> AuthenticateResourceAsync(s
7879
authenticationResult = await this.authenticationContextWrapper.AcquireTokenAsync(
7980
resource,
8081
this.ServiceInfo.AppId,
81-
new Uri(this.ServiceInfo.ReturnUrl));
82+
new Uri(this.ServiceInfo.ReturnUrl),
83+
PromptBehavior.Auto,
84+
userIdentifier);
8285

8386
if (authenticationResult == null || authenticationResult.Status != AuthenticationStatus.Success)
8487
{

src/OneDriveSdk.WinRT/Authentication/AuthenticationContextWrapper.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,37 @@ public AuthenticationContextWrapper(string serviceUrl, bool validateAuthority, T
4141
this.authenticationContext = new AuthenticationContext(serviceUrl, validateAuthority, tokenCache);
4242
}
4343

44-
public async Task<IAuthenticationResult> AcquireTokenSilentAsync(string resource, string clientId)
44+
/// <summary>
45+
/// Authenticates the user silently using <see cref="AuthenticationContext.AcquireToken(string, string, UserIdentifier)"/>.
46+
/// </summary>
47+
/// <param name="resource">The resource to authenticate against.</param>
48+
/// <param name="clientId">The client ID of the application.</param>
49+
/// <param name="userIdentifier">The <see cref="UserIdentifier"/> for authentication.</param>
50+
/// <returns>The <see cref="IAuthenticationResult"/>.</returns>
51+
public async Task<IAuthenticationResult> AcquireTokenSilentAsync(string resource, string clientId, UserIdentifier userIdentifier)
4552
{
46-
var result = await this.authenticationContext.AcquireTokenSilentAsync(resource, clientId);
53+
var result = await this.authenticationContext.AcquireTokenSilentAsync(resource, clientId, userIdentifier);
4754

4855
return result == null ? null : new AuthenticationResultWrapper(result);
4956
}
5057

51-
public async Task<IAuthenticationResult> AcquireTokenAsync(string resource, string clientId, Uri redirectUri)
58+
/// <summary>
59+
/// Authenticates the user using <see cref="AuthenticationContext.AcquireTokenAsync(string, string, Uri, PromptBehavior, UserIdentifier)"/>.
60+
/// </summary>
61+
/// <param name="resource">The resource to authenticate against.</param>
62+
/// <param name="clientId">The client ID of the application.</param>
63+
/// <param name="redirectUri">The redirect URI of the application.</param>
64+
/// <param name="promptBehavior">The <see cref="PromptBehavior"/> for authentication.</param>
65+
/// <param name="userIdentifier">The <see cref="UserIdentifier"/> for authentication.</param>
66+
/// <returns>The <see cref="IAuthenticationResult"/>.</returns>
67+
public async Task<IAuthenticationResult> AcquireTokenAsync(
68+
string resource,
69+
string clientId,
70+
Uri redirectUri,
71+
PromptBehavior promptBehavior,
72+
UserIdentifier userIdentifier)
5273
{
53-
var result = await this.authenticationContext.AcquireTokenAsync(resource, clientId, redirectUri);
74+
var result = await this.authenticationContext.AcquireTokenAsync(resource, clientId, redirectUri, promptBehavior, userIdentifier);
5475

5576
return result == null ? null : new AuthenticationResultWrapper(result);
5677
}

src/OneDriveSdk.WinRT/Authentication/IAuthenticationContextWrapper.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,30 @@
2222

2323
namespace Microsoft.OneDrive.Sdk
2424
{
25+
using IdentityModel.Clients.ActiveDirectory;
2526
using System;
2627
using System.Threading.Tasks;
2728

2829
public interface IAuthenticationContextWrapper
2930
{
30-
Task<IAuthenticationResult> AcquireTokenSilentAsync(string resource, string clientId);
31+
/// <summary>
32+
/// Authenticates the user silently using <see cref="AuthenticationContext.AcquireToken(string, string, UserIdentifier)"/>.
33+
/// </summary>
34+
/// <param name="resource">The resource to authenticate against.</param>
35+
/// <param name="clientId">The client ID of the application.</param>
36+
/// <param name="userIdentifier">The <see cref="UserIdentifier"/> for authentication.</param>
37+
/// <returns>The <see cref="IAuthenticationResult"/>.</returns>
38+
Task<IAuthenticationResult> AcquireTokenSilentAsync(string resource, string clientId, UserIdentifier userIdentifier);
3139

32-
Task<IAuthenticationResult> AcquireTokenAsync(string resource, string clientId, Uri redirectUri);
40+
/// <summary>
41+
/// Authenticates the user using <see cref="AuthenticationContext.AcquireTokenAsync(string, string, Uri, PromptBehavior, UserIdentifier)"/>.
42+
/// </summary>
43+
/// <param name="resource">The resource to authenticate against.</param>
44+
/// <param name="clientId">The client ID of the application.</param>
45+
/// <param name="redirectUri">The redirect URI of the application.</param>
46+
/// <param name="promptBehavior">The <see cref="PromptBehavior"/> for authentication.</param>
47+
/// <param name="userIdentifier">The <see cref="UserIdentifier"/> for authentication.</param>
48+
/// <returns>The <see cref="IAuthenticationResult"/>.</returns>
49+
Task<IAuthenticationResult> AcquireTokenAsync(string resource, string clientId, Uri redirectUri, PromptBehavior promptBehavior, UserIdentifier userIdentifier);
3350
}
3451
}

src/OneDriveSdk.WinStore/Authentication/WebAuthenticationBrokerAuthenticationProvider.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
namespace Microsoft.OneDrive.Sdk
2424
{
2525
using System;
26+
using System.Net;
2627
using System.Text;
2728
using System.Threading.Tasks;
2829
using Windows.Security.Authentication.Web;
@@ -65,28 +66,22 @@ protected override Task<AccountSession> GetAuthenticationResultAsync()
6566

6667
internal async Task<AccountSession> GetAccountSessionAsync()
6768
{
68-
var returnUrlForRequest = string.IsNullOrEmpty(this.ServiceInfo.ReturnUrl)
69+
var returnUrl = string.IsNullOrEmpty(this.ServiceInfo.ReturnUrl)
6970
? WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString()
7071
: this.ServiceInfo.ReturnUrl;
7172

72-
var requestUriStringBuilder = new StringBuilder();
73-
requestUriStringBuilder.Append(this.ServiceInfo.AuthenticationServiceUrl);
74-
requestUriStringBuilder.AppendFormat("?{0}={1}", Constants.Authentication.RedirectUriKeyName, returnUrlForRequest);
75-
requestUriStringBuilder.AppendFormat("&{0}={1}", Constants.Authentication.ClientIdKeyName, this.ServiceInfo.AppId);
76-
requestUriStringBuilder.AppendFormat("&{0}={1}", Constants.Authentication.ScopeKeyName, string.Join("%20", this.ServiceInfo.Scopes));
77-
requestUriStringBuilder.AppendFormat("&{0}={1}", Constants.Authentication.ResponseTypeKeyName, Constants.Authentication.TokenResponseTypeValueName);
78-
79-
var requestUri = new Uri(requestUriStringBuilder.ToString());
73+
// Log the user in if we haven't already pulled their credentials from the cache.
74+
var code = await this.GetAuthorizationCodeAsync(returnUrl);
8075

81-
var authenticationResponseValues = await this.ServiceInfo.WebAuthenticationUi.AuthenticateAsync(
82-
requestUri,
83-
string.IsNullOrEmpty(this.ServiceInfo.ReturnUrl)
84-
? null
85-
: new Uri(this.ServiceInfo.ReturnUrl));
76+
if (!string.IsNullOrEmpty(code))
77+
{
78+
var authResult = await this.SendTokenRequestAsync(this.GetCodeRedemptionRequestBody(code, returnUrl));
79+
authResult.CanSignOut = true;
8680

87-
OAuthErrorHandler.ThrowIfError(authenticationResponseValues);
81+
return authResult;
82+
}
8883

89-
return new AccountSession(authenticationResponseValues, this.ServiceInfo.AppId, AccountType.MicrosoftAccount) { CanSignOut = true };
84+
return null;
9085
}
9186
}
9287
}

src/OneDriveSdk.WinStore/Authentication/WebAuthenticationBrokerWebAuthenticationUi.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public async Task<IDictionary<string, string>> AuthenticateAsync(Uri requestUri,
4545
{
4646
result = await this.AuthenticateAsync(requestUri, callbackUri, WebAuthenticationOptions.SilentMode);
4747
}
48-
catch (Exception exception)
48+
catch (Exception)
4949
{
5050
// WebAuthenticationBroker can throw an exception in silent authentication mode when not using SSO and
5151
// silent authentication isn't available. Swallow it and try authenticating with user prompt. Even if

src/OneDriveSdk.WindowsForms/Authentication/AdalAuthenticationProvider.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,13 @@ protected override async Task<IAuthenticationResult> AuthenticateResourceAsync(s
6464
{
6565
IAuthenticationResult authenticationResult = null;
6666
var clientCredential = string.IsNullOrEmpty(this.serviceInfo.ClientSecret) ? null : new ClientCredential(this.serviceInfo.AppId, this.serviceInfo.ClientSecret);
67+
var userIdentifier = this.GetUserIdentifierForAuthentication();
6768

6869
try
6970
{
7071
authenticationResult = clientCredential == null
7172
? await this.authenticationContextWrapper.AcquireTokenSilentAsync(resource, this.serviceInfo.AppId)
72-
: await this.authenticationContextWrapper.AcquireTokenSilentAsync(resource, clientCredential, UserIdentifier.AnyUser);
73+
: await this.authenticationContextWrapper.AcquireTokenSilentAsync(resource, clientCredential, userIdentifier);
7374
}
7475
catch (Exception)
7576
{
@@ -88,7 +89,8 @@ protected override async Task<IAuthenticationResult> AuthenticateResourceAsync(s
8889
resource,
8990
this.ServiceInfo.AppId,
9091
new Uri(this.ServiceInfo.ReturnUrl),
91-
PromptBehavior.Always)
92+
PromptBehavior.Auto,
93+
userIdentifier)
9294
: await this.authenticationContextWrapper.AcquireTokenAsync(resource, clientCredential);
9395
}
9496
catch (AdalException adalException)

src/OneDriveSdk.WindowsForms/Authentication/AuthenticationContextWrapper.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,17 @@ public async Task<IAuthenticationResult> AcquireTokenSilentAsync(string resource
7979
}
8080

8181
/// <summary>
82-
/// Authenticates the user silently using <see cref="AuthenticationContext.AcquireToken(string, string, Uri, PromptBehavior)"/>.
82+
/// Authenticates the user using <see cref="AuthenticationContext.AcquireToken(string, string, Uri, PromptBehavior, UserIdentifier)"/>.
8383
/// </summary>
8484
/// <param name="resource">The resource to authenticate against.</param>
8585
/// <param name="clientId">The client ID of the application.</param>
8686
/// <param name="redirectUri">The redirect URI of the application.</param>
8787
/// <param name="promptBehavior">The <see cref="PromptBehavior"/> for authentication.</param>
88+
/// <param name="userIdentifier">The <see cref="UserIdentifier"/> for authentication.</param>
8889
/// <returns>The <see cref="IAuthenticationResult"/>.</returns>
89-
public IAuthenticationResult AcquireToken(string resource, string clientId, Uri redirectUri, PromptBehavior promptBehavior)
90+
public IAuthenticationResult AcquireToken(string resource, string clientId, Uri redirectUri, PromptBehavior promptBehavior, UserIdentifier userIdentifier)
9091
{
91-
var result = this.authenticationContext.AcquireToken(resource, clientId, redirectUri, promptBehavior);
92+
var result = this.authenticationContext.AcquireToken(resource, clientId, redirectUri, promptBehavior, userIdentifier);
9293

9394
return result == null ? null : new AuthenticationResultWrapper(result);
9495
}

src/OneDriveSdk.WindowsForms/Authentication/IAuthenticationContextWrapper.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@ public interface IAuthenticationContextWrapper
4747
Task<IAuthenticationResult> AcquireTokenSilentAsync(string resource, ClientCredential clientCredential, UserIdentifier userIdentifier);
4848

4949
/// <summary>
50-
/// Authenticates the user silently using <see cref="AuthenticationContext.AcquireToken(string, string, Uri, PromptBehavior)"/>.
50+
/// Authenticates the user silently using <see cref="AuthenticationContext.AcquireToken(string, string, Uri, PromptBehavior, UserIdentifier)"/>.
5151
/// </summary>
5252
/// <param name="resource">The resource to authenticate against.</param>
5353
/// <param name="clientId">The client ID of the application.</param>
5454
/// <param name="redirectUri">The redirect URI of the application.</param>
5555
/// <param name="promptBehavior">The <see cref="PromptBehavior"/> for authentication.</param>
56+
/// <param name="userIdentifier">The <see cref="UserIdentifier"/> for authentication.</param>
5657
/// <returns>The <see cref="IAuthenticationResult"/>.</returns>
57-
IAuthenticationResult AcquireToken(string resource, string clientId, Uri redirectUri, PromptBehavior promptBehavior);
58+
IAuthenticationResult AcquireToken(string resource, string clientId, Uri redirectUri, PromptBehavior promptBehavior, UserIdentifier userIdentifier);
5859

5960
/// <summary>
6061
/// Authenticates the user silently using <see cref="AuthenticationContext.AcquireTokenAsync(string, ClientCredential)"/>.

0 commit comments

Comments
 (0)