Click or drag to resize
MimeKit

SaslMechanismOAuth2 Class

The OAuth2 SASL mechanism.
Inheritance Hierarchy
SystemObject
  MailKit.SecuritySaslMechanism
    MailKit.SecuritySaslMechanismOAuth2

Namespace: MailKit.Security
Assembly: MailKit (in MailKit.dll) Version: 4.7.1
Syntax
C#
public class SaslMechanismOAuth2 : SaslMechanism

The SaslMechanismOAuth2 type exposes the following members.

Constructors
 NameDescription
Public methodSaslMechanismOAuth2(NetworkCredential) Initializes a new instance of the SaslMechanismOAuth2 class.
Public methodCode exampleSaslMechanismOAuth2(String, String) Initializes a new instance of the SaslMechanismOAuth2 class.
Top
Properties
 NameDescription
Public propertyCredentials Get the user's credentials.
(Inherited from SaslMechanism)
Public propertyIsAuthenticated Get or set whether the SASL mechanism has finished authenticating.
(Inherited from SaslMechanism)
Public propertyMechanismName Get the name of the SASL mechanism.
(Overrides SaslMechanismMechanismName)
Public propertyNegotiatedChannelBinding Get whether or not channel-binding was negotiated by the SASL mechanism.
(Inherited from SaslMechanism)
Public propertyNegotiatedSecurityLayer Get whether or not a security layer was negotiated by the SASL mechanism.
(Inherited from SaslMechanism)
Public propertySupportsChannelBinding Get whether or not the SASL mechanism supports channel binding.
(Inherited from SaslMechanism)
Public propertySupportsInitialResponse Get whether or not the mechanism supports an initial response (SASL-IR).
(Overrides SaslMechanismSupportsInitialResponse)
Top
Methods
 NameDescription
Public methodChallenge(String, CancellationToken) Decode the base64-encoded server challenge and return the next challenge response encoded in base64.
(Inherited from SaslMechanism)
Protected methodChallenge(Byte, Int32, Int32, CancellationToken) Parse the server's challenge token and return the next challenge response.
(Overrides SaslMechanismChallenge(Byte, Int32, Int32, CancellationToken))
Public methodChallengeAsync(String, CancellationToken) Asynchronously decode the base64-encoded server challenge and return the next challenge response encoded in base64.
(Inherited from SaslMechanism)
Protected methodChallengeAsync(Byte, Int32, Int32, CancellationToken) Asynchronously parse the server's challenge token and return the next challenge response.
(Inherited from SaslMechanism)
Public methodEquals
(Inherited from Object)
Protected methodFinalize
(Inherited from Object)
Public methodGetHashCode
(Inherited from Object)
Public methodGetType
(Inherited from Object)
Protected methodMemberwiseClone
(Inherited from Object)
Public methodReset Reset the state of the SASL mechanism.
(Inherited from SaslMechanism)
Public methodToString
(Inherited from Object)
Protected methodTryGetChannelBindingToken Try to get a channel-binding token.
(Inherited from SaslMechanism)
Top
Remarks
A SASL mechanism used by Google that makes use of a short-lived OAuth 2.0 access token.
Example
C#
using System;
using System.Threading;
using System.Threading.Tasks;

using Google.Apis.Util;
using Google.Apis.Util.Store;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;

using MailKit;
using MailKit.Net.Imap;
using MailKit.Security;

namespace OAuth2GMailExample {
    class Program
    {
        const string GMailAccount = "username@gmail.com";

        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"))
                    AuthenticateAsync (client).GetAwaiter ().GetResult ();
                client.Disconnect (true);
            }
        }

        static async Task AuthenticateAsync (ImapClient client)
        {
            var clientSecrets = new ClientSecrets {
                ClientId = "XXX.apps.googleusercontent.com",
                ClientSecret = "XXX"
            };

            var codeFlow = new GoogleAuthorizationCodeFlow (new GoogleAuthorizationCodeFlow.Initializer {
                DataStore = new FileDataStore ("CredentialCacheFolder", false),
                Scopes = new [] { "https://mail.google.com/" },
                ClientSecrets = clientSecrets
            });

            // Note: For a web app, you'll want to use AuthorizationCodeWebApp instead.
            var codeReceiver = new LocalServerCodeReceiver ();
            var authCode = new AuthorizationCodeInstalledApp (codeFlow, codeReceiver);

            var credential = await authCode.AuthorizeAsync (GMailAccount, CancellationToken.None);

            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
            // different GMail account when presented with the browser window during the authentication process.
            SaslMechanism oauth2;

            if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER"))
                oauth2 = new SaslMechanismOAuthBearer (credential.UserId, credential.Token.AccessToken);
            else
                oauth2 = new SaslMechanismOAuth2 (credential.UserId, credential.Token.AccessToken);

            await client.AuthenticateAsync (oauth2);
        }
    }
}
C#
using System;
using System.Threading;
using System.Threading.Tasks;

using MailKit;
using MailKit.Net.Imap;
using MailKit.Security;

using Microsoft.Identity.Client;

namespace OAuth2ExchangeExample {
    class Program
    {
        const string ExchangeAccount = "username@office365.com";

        public static void Main (string[] args)
        {
            using (var client = new ImapClient ()) {
                client.Connect ("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
                if (client.AuthenticationMechanisms.Contains ("OAUTHBEARER") || client.AuthenticationMechanisms.Contains ("XOAUTH2"))
                    AuthenticateAsync (client).GetAwaiter ().GetResult ();
                client.Disconnect (true);
            }
        }

        static async Task AuthenticateAsync (ImapClient client)
        {
            var options = new PublicClientApplicationOptions {
                ClientId = "Application (client) ID",
                TenantId = "Directory (tenant) ID",
                RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient"
            };

            var publicClientApplication = PublicClientApplicationBuilder
                .CreateWithApplicationOptions (options)
                .Build ();

            var scopes = new string[] {
                "email",
                "offline_access",
                "https://outlook.office.com/IMAP.AccessAsUser.All", // Only needed for IMAP
                //"https://outlook.office.com/POP.AccessAsUser.All",  // Only needed for POP
                //"https://outlook.office.com/SMTP.AccessAsUser.All", // Only needed for SMTP
            };

            AuthenticationResult? result;

            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 (result.Account.Username, result.AccessToken);
            else
                oauth2 = new SaslMechanismOAuth2 (result.Account.Username, result.AccessToken);

            await client.AuthenticateAsync (oauth2);
        }
    }
}
See Also