From 814603350b702fe88c17dc8936543a488823bc2f Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Fri, 2 Aug 2024 15:14:33 -0400 Subject: [PATCH] More OAuth2 example improvements --- Documentation/Examples/OAuth2ExchangeExample.cs | 17 ++++++++++++----- Documentation/Examples/OAuth2GMailExample.cs | 6 +++--- ExchangeOAuth2.md | 15 +++++---------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Documentation/Examples/OAuth2ExchangeExample.cs b/Documentation/Examples/OAuth2ExchangeExample.cs index 3661351fbc..8e3be0b6c4 100644 --- a/Documentation/Examples/OAuth2ExchangeExample.cs +++ b/Documentation/Examples/OAuth2ExchangeExample.cs @@ -43,17 +43,24 @@ static async Task AuthenticateAsync (ImapClient client) //"https://outlook.office.com/SMTP.AccessAsUser.All", // Only needed for SMTP }; - var authToken = await publicClientApplication.AcquireTokenInteractive (scopes).WithLoginHint (ExchangeAccount).ExecuteAsync (cancellationToken); - await publicClientApplication.AcquireTokenSilent (scopes, authToken.Account).ExecuteAsync (cancellationToken); + AuthenticationResult? result; - // Note: We use authToken.Account.Username here instead of ExchangeAccount because the user *may* have chosen a + try { + // First, check the cache for an auth token. + result = await publicClientApplication.AcquireTokenSilent (scopes, username).ExecuteAsync (); + } catch (MsalUiRequiredException) { + // If that fails, then try getting an auth token interactively. + result = await publicClientApplication.AcquireTokenInteractive (scopes).WithLoginHint (username).ExecuteAsync (); + } + + // Note: We use result.Account.Username here instead of ExchangeAccount because the user *may* have chosen a // different Microsoft Exchange account when presented with the browser window during the authentication process. SaslMechanism oauth2; if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER")) - oauth2 = new SaslMechanismOAuthBearer (authToken.Account.Username, authToken.AccessToken); + oauth2 = new SaslMechanismOAuthBearer (result.Account.Username, result.AccessToken); else - oauth2 = new SaslMechanismOAuth2 (authToken.Account.Username, authToken.AccessToken); + oauth2 = new SaslMechanismOAuth2 (result.Account.Username, result.AccessToken); await client.AuthenticateAsync (oauth2); } diff --git a/Documentation/Examples/OAuth2GMailExample.cs b/Documentation/Examples/OAuth2GMailExample.cs index a1da1f2ac1..95ad1dc03a 100644 --- a/Documentation/Examples/OAuth2GMailExample.cs +++ b/Documentation/Examples/OAuth2GMailExample.cs @@ -21,12 +21,12 @@ public static void Main (string[] args) using (var client = new ImapClient ()) { client.Connect ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect); if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER") || client.AuthenticationMechanisms.Contains ("XOAUTH2")) - OAuthAsync (client).GetAwaiter ().GetResult (); + AuthenticateAsync (client).GetAwaiter ().GetResult (); client.Disconnect (true); } } - static async Task OAuthAsync (ImapClient client) + static async Task AuthenticateAsync (ImapClient client) { var clientSecrets = new ClientSecrets { ClientId = "XXX.apps.googleusercontent.com", @@ -45,7 +45,7 @@ static async Task OAuthAsync (ImapClient client) var credential = await authCode.AuthorizeAsync (GMailAccount, CancellationToken.None); - if (credential.Token.IsExpired (SystemClock.Default)) + if (credential.Token.IsStale) await credential.RefreshTokenAsync (CancellationToken.None); // Note: We use credential.UserId here instead of GMailAccount because the user *may* have chosen a diff --git a/ExchangeOAuth2.md b/ExchangeOAuth2.md index c1bc538fc9..4318dd5c49 100644 --- a/ExchangeOAuth2.md +++ b/ExchangeOAuth2.md @@ -64,18 +64,13 @@ AuthenticationResult? result; try { // First, check the cache for an auth token. - result = await publicClientApplication - .AcquireTokenSilent (scopes, EmailAddress) - .ExecuteAsync (); + result = await publicClientApplication.AcquireTokenSilent (scopes, EmailAddress).ExecuteAsync (); } catch (MsalUiRequiredException) { // If that fails, then try getting an auth token interactively. - result = await publicClientApplication - .AcquireTokenInteractive (scopes) - .WithLoginHint (EmailAddress) - .ExecuteAsync (); + result = await publicClientApplication.AcquireTokenInteractive (scopes).WithLoginHint (EmailAddress).ExecuteAsync (); } -// Note: We always use authToken.Account.Username instead of `Username` because the user may have selected an alternative account. +// Note: We always use result.Account.Username instead of `Username` because the user may have selected an alternative account. var oauth2 = new SaslMechanismOAuth2 (result.Account.Username, result.AccessToken); using (var client = new ImapClient ()) { @@ -86,11 +81,11 @@ using (var client = new ImapClient ()) { ``` Note: Once you've acquired an auth token using the interactive method above, you can avoid prompting the user -if you cache the `authToken.Account` information and then silently reacquire auth tokens in the future using +if you cache the `result.Account` information and then silently reacquire auth tokens in the future using the following code: ```csharp -var authToken = await publicClientApplication.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken); +var result = await publicClientApplication.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken); ``` ## Web Services