Search code examples
wpfauthenticationoauthgoogle-oauthmailkit

Interface Between Google Sign-in and MailKit


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.

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.

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

I have created and downloaded a JSON file for OAuth 2.0 from Google.

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.

(Please see the code below.)

For "password", would that be the password for the account?

I'm not sure as to what to give for "[email protected]".

.........................................................

https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog .........................................................

From the Q & A:

How can I log in to a GMail account using OAuth 2.0?

The first thing you need to do is follow Google's instructions for obtaining OAuth 2.0 credentials for your application.

Once you've done that, the easiest way to obtain an access token is to use Google's Google.Apis.Auth library:

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

var credential = new ServiceAccountCredential (new ServiceAccountCredential
    .Initializer ("[email protected]") {

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

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

    User = "[email protected]"

}.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 ("[email protected]", credential.Token.AccessToken);
}

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

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?

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

Would Google Sign-In be a better approach?

I've downloaded the example code for .NET from Google: https://github.com/googlesamples/oauth-apps-for-windows

I've built and ran ran "OAuthConsoleApp", as well as "OAuthDesktopApp".

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

.........................................................

redirect URI: http 127.0.0.1:64003

Listening..

Authorization code: qwerty ...

Exchanging code for tokens...

Send the request ...

GetRequestStream ...

await stream.WriteAsync ...

Get the response ...

responseText ...

{

"access_token": "qwerty ...",

"token_type": "Bearer",

"expires_in": 3600,

"refresh_token": "qwerty ...",

"id_token": "qwerty ..."

}

Making API Call to Userinfo...

+++ userinfoResponseText : {

"sub": "117108120545711995673",

"name": "My Name",

"given_name": "My",

"family_name": "Name",

"picture": "qwerty ...",

"locale": "en"

}

.....................................................

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):

string access_token = tokenEndpointDecoded["access_token"];

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

client.Authenticate ("[email protected]", access_token);

It threw an exception:

.....................................................

"POP3 server did not respond with a +OK response to the AUTH command."

at MailKit.Net.Pop3.Pop3Client.Authenticate(Encoding encoding, ICredentials credentials, CancellationToken cancellationToken)

at MailKit.MailService.Authenticate(String userName, String password, CancellationToken cancellationToken)

at NS_MailKit_01.Pop3.cls_mailKit_Pop3_01.connect_and_authenticate(Object p3_client, String p_access_token)

in :\Software_Develpoment_Sys_03_K\MIME_EMail\TEST_02\Mail_Kit_01\MailKit_01.cs:line

465

at LIB1_01_G_Mail_Auth.cls_G_mail_authorization.str_token_NTRF.invoke_access_token(String p_access_token)

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 95

at LIB1_01_G_Mail_Auth.cls_G_mail_authorization.d__13.MoveNext()

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

343

.....................................................

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

Any help would be appreciated.

Thanks!


Solution

  • For "password", would that be the password for the account?

    No. It would be the password for your PKCS12 file containing your X.509 Certificate and your private key.

    I'm not sure as to what to give for "[email protected]".

    You need to register yourself and your application with Google's Developer program which will give you a developer id to use. You need to follow their directions.