Interface Between Google Sign-in and MailKit
<p>I am writing an app in WPF (Windows 10 desktop) that should
include a component where the user can download message headers
and messages from G-Mail.</p>

<p>I am trying to use MailKit to interface with G-Mail via a secure
connection (without having to turn on "allow less-secure apps"
for G-Mail) and download messages with POP3. I am a bit confused
as to the proper procedure.</p>

<p>FYI: I know next to nothing about OAuth and TLS, so KISS please.</p>

<p>I have created and downloaded a JSON file for OAuth 2.0 from Google.</p>

<p>I have visited the FAQ for MailKit, and the following section
seems relevant, but I'm not sure as to what I should plug in
to the interface.</p>

<p>(Please see the code below.)</p>

<p>For "password", would that be the password for the account?</p>

<p>I'm not sure as to what to give for
"your-developer-id@developer.gserviceaccount.com".</p>

<blockquote>
  <p>.........................................................</p>
  
  <p><a href="https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog" rel="nofollow">https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog</a>
  .........................................................</p>
  
  <p>From the Q &amp; A:</p>
  
  <p>How can I log in to a GMail account using OAuth 2.0?</p>
  
  <p>The first thing you need to do is follow Google's instructions for
  obtaining  OAuth 2.0 credentials for your application.</p>
  
  <p>Once you've done that, the easiest way to obtain an access token is to
  use  Google's Google.Apis.Auth library:</p>
</blockquote>

<pre><code>var certificate = new X509Certificate2 (@"C:\path\to\certificate.p12", "password",
         X509KeyStorageFlags.Exportable);

var credential = new ServiceAccountCredential (new ServiceAccountCredential
    .Initializer ("your-developer-id@developer.gserviceaccount.com") {

    // Note: other scopes can be found here: [links]

    Scopes = new[] { "https  mail google com " },

    User = "username@gmail.com"

}.FromCertificate (certificate));

bool result = await credential.RequestAccessTokenAsync (CancellationToken.None);

// Note: result will be true if the access token was received successfully

// Now that you have an access token (credential.Token.AccessToken), you can
// use it with MailKit as if it were the password:

using (var client = new ImapClient ()) {

    client.Connect ("imap.gmail.com", 993, true);

    // use the access token as the password string

    client.Authenticate ("username@gmail.com", credential.Token.AccessToken);
}
</code></pre>

<p>My next question: Would the user be able to access their own account(s)
with my app without having to follow the same procedure?</p>

<p>IOW: Will the credentials that I've downloaded work for any account?
  ... or allow access only to the account from which the credentials
were created?</p>

<p>If the credentials are only good for my own account, then I'll have to
do something else.</p>

<p>Would Google Sign-In be a better approach?</p>

<p>I've downloaded the example code for .NET from Google:
<a href="https://github.com/googlesamples/oauth-apps-for-windows" rel="nofollow">https://github.com/googlesamples/oauth-apps-for-windows</a></p>

<p>I've built and ran ran "OAuthConsoleApp", as well as "OAuthDesktopApp".</p>

<p>It would seem that I am getting a secure connection from those,
as I have gotten the following output:</p>

<blockquote>
  <p>.........................................................</p>
  
  <p>redirect URI: http  127.0.0.1:64003 </p>
  
  <p>Listening..</p>
  
  <p>Authorization code: qwerty ...</p>
  
  <p>Exchanging code for tokens...</p>
  
  <p>Send the request ...</p>
  
  <p>GetRequestStream ...</p>
  
  <p>await stream.WriteAsync ...</p>
  
  <p>Get the response ...</p>
  
  <p>responseText ...</p>
  
  <p>{</p>
  
  <p>"access_token": "qwerty ...",</p>
  
  <p>"token_type": "Bearer",</p>
  
  <p>"expires_in": 3600,</p>
  
  <p>"refresh_token": "qwerty ...",</p>
  
  <p>"id_token": "qwerty ..."</p>
  
  <p>}</p>
  
  <p>Making API Call to Userinfo...</p>
  
  <p>+++ userinfoResponseText : {</p>
  
  <p>"sub": "117108120545711995673",</p>
  
  <p>"name": "My Name",</p>
  
  <p>"given_name": "My",</p>
  
  <p>"family_name": "Name",</p>
  
  <p>"picture": "qwerty ...",</p>
  
  <p>"locale": "en"</p>
  
  <p>}</p>
  
  <p>.....................................................</p>
</blockquote>

<p>I see that I have an "access_token" in the response and I thought
that I could plug that in to the "client.Authenticate" method for
MailKit as the password (as mentioned in the docs for MailKit):</p>

<pre><code>string access_token = tokenEndpointDecoded["access_token"];

client.Connect ("pop.gmail.com", 995, SecureSocketOptions.SslOnConnect);

client.Authenticate ("username@gmail.com", access_token);
</code></pre>

<p>It threw an exception:</p>

<blockquote>
  <p>.....................................................</p>
  
  <p>"POP3 server did not respond with a +OK response to the AUTH command."</p>
  
  <p>at MailKit.Net.Pop3.Pop3Client.Authenticate(Encoding encoding,
  ICredentials credentials, CancellationToken cancellationToken)</p>
  
  <p>at MailKit.MailService.Authenticate(String userName, String
  password, CancellationToken cancellationToken)</p>
  
  <p>at
  NS_MailKit_01.Pop3.cls_mailKit_Pop3_01.connect_and_authenticate(Object
  p3_client, String p_access_token)</p>

<pre><code>in :\Software_Develpoment_Sys_03_K\MIME_EMail\TEST_02\Mail_Kit_01\MailKit_01.cs:line
</code></pre>
  
  <p>465</p>
  
  <p>at
  LIB1_01_G_Mail_Auth.cls_G_mail_authorization.str_token_NTRF.invoke_access_token(String
  p_access_token)</p>

<pre><code>in K:\Software_Develpoment_Sys_03_K\MIME_EMail\TEST_02\OAuth\oauth-apps-for-windows\OAuthConsoleApp\LIB1_01_G_Mail_Auth\G_Mail_Auth_01.cs:
</code></pre>
  
  <p>line 95</p>
  
  <p>at
  LIB1_01_G_Mail_Auth.cls_G_mail_authorization.d__13.MoveNext()</p>

<pre><code>in K:\Software_Develpoment_Sys_03_K\MIME_EMail\TEST_02\OAuth\oauth-apps-for-windows\OAuthConsoleApp\LIB1_01_G_Mail_Auth\G_Mail_Auth_01.cs:line
</code></pre>
  
  <p>343</p>
  
  <p>.....................................................</p>
</blockquote>

<p>Does anyone know how I could get a "credential" object from
the Google interface that I could use with MailKit?</p>

<p>Any help would be appreciated.</p>

<p>Thanks!</p>