Posts Tagged ‘OAuth 2.0’

OAuth 2.0 with Gmail over IMAP for service account

Thursday, September 11th, 2014

In this article I’ll show how to access Gmail account of any domain user, using OAuth 2.0, .NET IMAP component and service accounts. The basic idea is that domain administrator can use this method to access user email without knowing user’s password.

This scenario is very similar to 2-legged OAuth, which uses OAuth 1.0a. Although it still works, it has been deprecated by Google and OAuth 2.0 service accounts were introduced.

The following describes how to use XOAUTH2 and OAuth 2.0 to achieve the equivalent of 2-legged OAuth.

Google APIs console

First you need to visit the Google Developers Console and create a service account:

console_0

console_1

console_2

Download and save this private key (XYZ.p12), you’ll need that later:

console_3

Go to “Service accounts” and click “View Client ID”:

console_4

Make a note of the Client ID and Email address (Service account).

Google Apps Dashboard

Next step is to authorize access for newly created service account.

Visit your domain administration panel:
https://www.google.com/a/cpanel/yourdomain.com/ManageOauthClients

Then click “Advanced tools”, “Authentication” and “Manage third party OAuth Client access”.

On this screen you can authorize service account to access email scope:

cpanel_1

Use previously remembered Client ID and “https://mail.google.com/”, which is IMAP/SMTP API scope:

Client Name: 1234567890
One or More API Scopes: https://mail.google.com/

Google.Apis

Use Nuget to download “Google.Apis.Auth.Mvc” and “Google.Apis.Auth” packages.

Access IMAP/SMTP server

// C#

using System.Security.Cryptography.X509Certificates;
using System;
using System.Threading;
using Limilabs.Client.IMAP;
using Limilabs.Test.Constants;
using Google.Apis.Auth.OAuth2;
using Limilabs.Client.Authentication.Google;


const string serviceAccountEmail = "name@xxxxxxxxxx.gserviceaccount.com";
const string serviceAccountCertPath = @"c:\XYZ.p12";
const string serviceAccountCertPassword = "notasecret";
const string userEmail = "user@your-domain.com";

X509Certificate2 certificate = new X509Certificate2(
    serviceAccountCertPath, 
    serviceAccountCertPassword, 
    X509KeyStorageFlags.Exportable);

ServiceAccountCredential credential = new ServiceAccountCredential(
    new ServiceAccountCredential.Initializer(serviceAccountEmail)
    {
        Scopes = new[] { GoogleScope.ImapAndSmtp.Name },
        User = userEmail
    }.FromCertificate(certificate));

bool success = credential.RequestAccessTokenAsync(CancellationToken.None).Result;
Assert.IsTrue(success);

using (Imap imap = new Imap())
{
    imap.ConnectSSL("imap.gmail.com");
    imap.LoginOAUTH2(userEmail, credential.Token.AccessToken);

    imap.SelectInbox();

    foreach (long uid in uids)
    {
        var eml = client.GetMessageByUID(uid);
        IMail email = new MailBuilder().CreateFromEml(eml);
        Console.WriteLine(email.Subject);
    }

    imap.Close();
}
' VB.NET

Imports System.Security.Cryptography.X509Certificates
Imports System.Threading
Imports Limilabs.Client.IMAP
Imports Limilabs.Test.Constants
Imports Google.Apis.Auth.OAuth2
Imports Limilabs.Client.Authentication.Google


Const  serviceAccountEmail As String = "name@xxxxxxxxxx.gserviceaccount.com"
Const  serviceAccountCertPath As String = "c:\XYZ.p12"
Const  serviceAccountCertPassword As String = "notasecret"
Const  userEmail As String = "user@your-domain.com"

Dim certificate As New X509Certificate2(serviceAccountCertPath, serviceAccountCertPassword, X509KeyStorageFlags.Exportable)

Dim credential As New ServiceAccountCredential(New ServiceAccountCredential.Initializer(serviceAccountEmail) With { _
	Key .Scopes = New () {GoogleScope.ImapAndSmtp.Name}, _
	Key .User = userEmail _
}.FromCertificate(certificate))

Dim success As Boolean = credential.RequestAccessTokenAsync(CancellationToken.None).Result
Assert.IsTrue(success)

Using imap As New Imap()
	imap.ConnectSSL("imap.gmail.com")
	imap.LoginOAUTH2(userEmail, credential.Token.AccessToken)

	imap.SelectInbox()

	For Each uid As Long In uids
		Dim eml = client.GetMessageByUID(uid)
		Dim email As IMail = New MailBuilder().CreateFromEml(eml)
		Console.WriteLine(email.Subject)
	Next

	imap.Close()
End Using

OAuth 2.0 with Outlook.com over IMAP for installed applications

Saturday, September 14th, 2013
You can also read how to use:

Outlook

OAuth is an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.

This article describes using OAuth 2.0 to access Outlook.com IMAP and SMTP servers using .NET IMAP component in installed applications scenario. You can also use OAuth 2.0 with Outlook.com for web applications.

DotNetOpenAuth

First download the latest version of DotNetOpenAuth – it’s free, open source library that implements OAuth 2.0: http://www.dotnetopenauth.net

Register Application

Before you can use OAuth 2.0, you must register your application using the application management site. After you’ve registered, go to the My applications and create new application. On “API Settings” page, copy “Client ID” and “Client secret” values and specify “Redirect domain“, which you’ll need later.

Outlook_AddAppKeys

Redirect domain must be valid domain address. For installed applications you can use domain address provided by Microsoft:
“https://login.live.com/oauth20_desktop.srf”

Now we can define clientID, clientSecret and scope variables, as well as Outlook.com OAuth 2.0 server addresses. Scope basically specifies what services we want to have access to. In our case it is user’s email address and IMAP/SMTP access:

string clientID = "000000014810009D";
string clientSecret = "wiRCccXnq1uyKcXnq1uyK";

AuthorizationServerDescription server = new AuthorizationServerDescription
{
    AuthorizationEndpoint = new Uri("https://login.live.com/oauth20_authorize.srf"),
    TokenEndpoint = new Uri("https://login.live.com/oauth20_token.srf"),
    ProtocolVersion = ProtocolVersion.V20,
};
List<string> scope = new List<string> { OutlookScope.ImapAndSmtp.Name, OutlookScope.EmailAddress.Name };

Obtain an OAuth 2.0 access token

As we are using installed applications scenario we’ll use NativeApplicationClient class.

Because of a small issue in DotNetOpenAuth we can not use UserAgentClient directly. NativeApplicationClient inherits UserAgentClient and workarounds this issue. You can find the implementation of NativeApplicationClient on the bottom of this article.

NativeApplicationClient consumer = new NativeApplicationClient(server, clientID, clientSecret);
Uri userAuthorizationUri = consumer.RequestUserAuthorization(scope);

Process.Start(userAuthorizationUri.AbsoluteUri);

We are using Process.Start here, but you can also embed WebBrowser control in your application.

At this point user is redirected to Microsoft to authorize the access:

Outlook_2Confirm

After this step user is presented a code that needs to be pasted to your application:

Outlook_3Redirect

Please note that this code also appears in the title of the browser:

  • It is possible to monitor processes on your machine and act automatically when it is there.
  • If you use embedded WebBrowser control in your application, you can monitor the HTML document title after any redirect.

Following is a code that reads this code and contacts Outlook.com to exchange it for a refresh-token and an access-token:

string authCode = Console.ReadLine();

consumer.ClientCredentialApplicator = 
    ClientCredentialApplicator.PostParameter(clientSecret);

IAuthorizationState grantedAccess = consumer.ProcessUserAuthorization(authCode);

string accessToken = grantedAccess.AccessToken;

An access token is usually short lived, and allows you to access the user’s data. You may also received a refresh token. A refresh token can be used to request a new access token once the previous expired.

Access IMAP/SMTP server

Finally we’ll ask Microsoft for user’s email and use LoginOAUTH2 method to access Outlook.com IMAP server:

IAuthorizationState grantedAccess = consumer.ProcessUserAuthorization(authCode);
string accessToken = grantedAccess.AccessToken;

OutlookApi api = new OutlookApi(accessToken);
string user = api.GetEmail();

using (Imap client = new Imap())
{
    client.ConnectSSL("imap-mail.outlook.com");

    imap.LoginOAUTH2(user, accessToken);

    imap.SelectInbox();
    List<long> uids = imap.Search(Flag.Unseen);

    foreach (long uid in uids)
    {
        var eml = imap.GetMessageByUID(uid);
        IMail email = new MailBuilder().CreateFromEml(eml);
        Console.WriteLine(email.Subject);
    }
    imap.Close();
}

NativeApplicationClient class

The OAuth 2.0 client for use by native applications. It’s main purpose is to build a generic URL containing the auth code, because DotNetOpenAuth library only allows parsing an URL as a method of retrieving the AuthorizationState.

/// <summary>
/// The OAuth2 client for use by native applications. 
/// This is a partial implementation which  should be used until 
/// the feature has been fully implemented in DotNetOpenAuth.
/// </summary>
public class NativeApplicationClient : UserAgentClient
{
    /// <summary>
    /// Represents a callback URL which points to a special out of band page 
    /// used for native OAuth2 authorization. This URL will cause the authorization 
    /// code to appear in the title of the window.
    /// </summary>
    public string OutOfBandCallbackUrl = "https://login.live.com/oauth20_desktop.srf"; // Outlook

    /// <summary>
    /// Initializes a new instance of the <see cref="UserAgentClient"/> class.
    /// </summary>
    /// <param name="authorizationServer">The token issuer.</param>
    /// <param name="clientIdentifier">The client identifier.</param>
    /// <param name="clientSecret">The client secret.</param>
    public NativeApplicationClient(
        AuthorizationServerDescription authorizationServer,
        string clientIdentifier,
        string clientSecret)
        : base(authorizationServer, clientIdentifier, clientSecret)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="UserAgentClient"/> class.
    /// </summary>
    /// <param name="authorizationServer">The token issuer.</param>
    public NativeApplicationClient(
        AuthorizationServerDescription authorizationServer)
        : this(authorizationServer, null, null)
    {
    }

    /// <summary>
    /// Creates the URL which should be used by the user to request the initial 
    /// authorization. Uses the default Out-of-band-URI as a callback.
    /// </summary>
    /// <param name="scope">Set of requested scopes</param>
    /// <returns>URI pointing to the authorization server</returns>
    public Uri RequestUserAuthorization(IEnumerable<string> scope)
    {
        var state = new AuthorizationState(scope);
        state.Callback = new Uri(OutOfBandCallbackUrl);
        return RequestUserAuthorization(state, false, null);
    }

    /// <summary>
    /// Uses the provided authorization code to create an authorization state.
    /// </summary>
    /// <param name="authCode">The authorization code for getting an access token.</param>
    /// <param name="authorizationState">The authorization.  Optional.</param>
    /// <returns>The granted authorization, or <c>null</c> if the authorization was null or rejected.</returns>
    public IAuthorizationState ProcessUserAuthorization(
        string authCode, 
        IAuthorizationState authorizationState)
    {
        if (authorizationState == null)
        {
            authorizationState = new AuthorizationState(null);
            authorizationState.Callback = new Uri(OutOfBandCallbackUrl);
        }

        // Build a generic URL containing the auth code.
        // This is done here as we cannot modify the DotNetOpenAuth library 
        // and the underlying method only allows parsing an URL as a method 
        // of retrieving the AuthorizationState.
        string url = "http://example.com/?code=" + authCode;
        return ProcessUserAuthorization(new Uri(url), authorizationState);
    }

    /// <summary>
    /// Uses the provided authorization code to create an authorization state.
    /// </summary>
    /// <param name="authCode">The authorization code for getting an access token.</param>
    /// <returns>The granted authorization, or <c>null</c> if the authorization was null or rejected.</returns>
    public IAuthorizationState ProcessUserAuthorization(string authCode)
    {
        return ProcessUserAuthorization(authCode, null);
    }
};

Refreshing access token

An access token is usually short lived. The main reason behind this is security and prevention of replay attacks. This means that for long-lived applications you need to refresh the access token. To force sending refresh token you need to add “wl.offline_access” to requested scopes:


List<string> scope = new List<string> { OutlookScope.ImapAndSmtp.Name, OutlookScope.EmailAddress.Name, OutlookScope.OfflineAccess.Name };

Refreshing access token

We recommend storing entire IAuthorizationState object received from WebServerClient.ProcessUserAuthorization method call. This object contains both: refresh token and access token, along with its expiration time.

The process of refreshing access token is simple:

IAuthorizationState grantedAccess = ...
consumer.RefreshAuthorization(grantedAccess, TimeSpan.FromMinutes(20));

In the example above the access token will not be refreshed if its remaining lifetime exceeds 20 minutes.

Apps and services you’ve given access

Users can manage consent for applications and services that can access some of their data on consent panel

OAuth 2.0 with Outlook.com over IMAP for web applications

Saturday, September 14th, 2013
You can also read how to use:

Outlook

OAuth is an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.

This article describes using OAuth 2.0 to access Outlook.com IMAP and SMTP servers using .NET IMAP component in web application scenario (ASP.NET/ASP.NET MVC). You can also use OAuth 2.0 with Outlook.com for installed/native applications.

DotNetOpenAuth

First download the latest version of DotNetOpenAuth – it’s free, open source library that implements OAuth 2.0: http://www.dotnetopenauth.net

Add it as a reference and import namespaces:

// c#

using DotNetOpenAuth.OAuth2;
' VB.NET 

Imports DotNetOpenAuth.OAuth2

Register Application

Before you can use OAuth 2.0, you must register your application using the application management site. After you’ve registered, go to the My applications and create new application. On “API Settings” page, copy “Client ID” and “Client secret” values and specify “Redirect domain“, which you’ll need later.

Outlook_AddAppKeys

Redirect domain must be valid domain address. You can’t use localhost, which is problematic during development phase. For testing purposes you can use fake domain. You just need to modify your computer’s hosts file (c:\Windows\System32\drivers\etc\hosts) so it redirects to localhost:
127.0.0.1 fake-domain-9065436322.com

Now we can define clientID, clientSecret, redirect url and scope variables, as well as Outlook.com OAuth 2.0 server addresses. Scope basically specifies what services we want to have access to. In our case it is user’s email address and IMAP/SMTP access:

string clientID = "000000014810009D";
string clientSecret = "wiRCccXnq1uyKcXnq1uyK";
string redirectUri = "http://fake-domain-9650932456.com/OAuth2.aspx";

AuthorizationServerDescription server = new AuthorizationServerDescription
{
    AuthorizationEndpoint = new Uri("https://login.live.com/oauth20_authorize.srf"),
    TokenEndpoint = new Uri("https://login.live.com/oauth20_token.srf"),
    ProtocolVersion = ProtocolVersion.V20,
};

List<string> scope = new List<string> 
    { 
        OutlookScope.ImapAndSmtp.Name, 
        OutlookScope.EmailAddress.Name 
    };

Obtain an OAuth 2.0 access token

As we are using ASP.NET we’ll use WebServerClient class:

WebServerClient consumer = new WebServerClient(server, clientID, clientSecret);

// Here redirect to authorization site occurs
consumer.RequestUserAuthorization(scope, new Uri(redirectUri));

If you use ASP.NET MVC the last line is different:

// Here redirect to authorization site occurs
OutgoingWebResponse response = consumer.PrepareRequestUserAuthorization(
    scope, new Uri(redirectUri));
return response.AsActionResult();

At this point user is redirected to Microsoft to authorize the access:

Outlook_2Confirm

After this step user is redirected back to your website (http://fake-domain-9650932456.com/OAuth2.aspx). Following is this callback code. Its purpose is to get a refresh-token and an access-token:

WebServerClient consumer = new WebServerClient(server, clientID, clientSecret);
IAuthorizationState grantedAccess = consumer.ProcessUserAuthorization(null);

string accessToken = grantedAccess.AccessToken;

An access token is usually short lived, and allows you to access the user’s data. You also received a refresh token. A refresh token can be used to request a new access token once the previous expired.

Access IMAP/SMTP server

Finally we’ll ask Microsoft for user’s email and use LoginOAUTH2 method to access Outlook.com IMAP server:

OutlookApi api = new OutlookApi(accessToken);
string user = api.GetEmail();

using (Imap imap = new Imap())
{
    imap.ConnectSSL("imap-mail.outlook.com");
    imap.LoginOAUTH2(user, accessToken);

    imap.SelectInbox();
    List<long> uids = imap.Search(Flag.Unseen);

    foreach (long uid in uids)
    {
        var eml = imap.GetMessageByUID(uid);
        IMail email = new MailBuilder().CreateFromEml(eml);
        Console.WriteLine(email.Subject);
    }
    imap.Close();
}

Refreshing access token

An access token is usually short lived. The main reason behind this is security and prevention of replay attacks. This means that for long-lived applications you need to refresh the access token.

In most cases web applications don’t need to refresh access token (they request new one every time), thus when using WebServerClient refresh token is not sent. To force sending refresh token you need to add “wl.offline_access” to requested scopes:


List<string> scope = new List<string> 
    { 
        OutlookScope.ImapAndSmtp.Name, 
        OutlookScope.EmailAddress.Name, 
        OutlookScope.OfflineAccess.Name 
    };

Your refresh token will be sent only once – don’t loose it!

We recommend storing entire IAuthorizationState object received from WebServerClient.ProcessUserAuthorization method call. This object contains both: refresh token and access token, along with its expiration time.

The process of refreshing access token is simple:

IAuthorizationState grantedAccess = ...
consumer.RefreshAuthorization(grantedAccess, TimeSpan.FromMinutes(20));

In the example above the access token will not be refreshed if its remaining lifetime exceeds 20 minutes.

Apps and services you’ve given access

Users can manage consent for applications and services that can access some of their data on consent panel

Get Google contacts with OAuth 2.0

Wednesday, April 10th, 2013

Although neither POP3 nor IMAP protocol allows retrieving the list of user’s contacts, it is possible to use Google API for that.

As long as you are using one of OAuth 2.0 scenarios:

Mail.dll email component allows you to easy download Gmail contacts of a particular user.

Turn on Contacts API

Remember to turn on “Contacts API” in Google management console.

Remember to add request for calendar data access using GoogleScope.ContactsScope.

// C#

List<GoogleScope> scope = new List<GoogleScope>
    {
        GoogleScope.ImapAndSmtp.Name,
        GoogleScope.EmailScope,
        GoogleScope.ContactsScope
    };
' VB.NET

Dim scope As New List(Of GoogleScope)() { _
    GoogleScope.ImapAndSmtp.Name, _
    GoogleScope.EmailScope, _
    GoogleScope.ContactsScope _
}

// C#

GoogleApi api = new GoogleApi(accessToken);

XmlDocument contacts = api.GetContacts();

XmlNamespaceManager nsmgr = new XmlNamespaceManager(contacts.NameTable);
nsmgr.AddNamespace("gd", "http://schemas.google.com/g/2005");
nsmgr.AddNamespace("a", "http://www.w3.org/2005/Atom");

foreach (XmlNode contact in contacts.GetElementsByTagName("entry"))
{
    XmlNode title = contact.SelectSingleNode("a:title", nsmgr);
    XmlNode email = contact.SelectSingleNode("gd:email", nsmgr);

    Console.WriteLine("{0}: {1}", 
        title.InnerText, 
        email.Attributes["address"].Value);
}
' VB.NET

Dim api As New GoogleApi(accessToken)

Dim contacts As XmlDocument = api.GetContacts()

Dim nsmgr As New XmlNamespaceManager(contacts.NameTable)
nsmgr.AddNamespace("gd", "http://schemas.google.com/g/2005")
nsmgr.AddNamespace("a", "http://www.w3.org/2005/Atom")

For Each contact As XmlNode In contacts.GetElementsByTagName("entry")
	Dim title As XmlNode = contact.SelectSingleNode("a:title", nsmgr)
	Dim email As XmlNode = contact.SelectSingleNode("gd:email", nsmgr)
	Console.WriteLine("{0}: {1}", _
            title.InnerText, _
            email.Attributes("address").Value)
Next

OAuth 2.0 with Gmail over IMAP for web applications

Saturday, September 22nd, 2012

OAuth is an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.

This article describes using OAuth 2.0 to access Gmail IMAP and SMTP servers using .NET IMAP component in web application scenario (ASP.NET/ASP.NET MVC). You can also use OAuth 2.0 for installed applications.

DotNetOpenAuth

First download the latest version of DotNetOpenAuth – it’s free, open source library that implements OAuth 2.0: http://www.dotnetopenauth.net

Add it as a reference and import namespaces:

// c#

using DotNetOpenAuth.OAuth2;
using DotNetOpenAuth.OAuth2.Messages;
using DotNetOpenAuth.Messaging;
' VB.NET 

Imports DotNetOpenAuth.OAuth2
Imports DotNetOpenAuth.OAuth2.Messages
Imports DotNetOpenAuth.Messaging

Register Application

Before you can use OAuth 2.0, you must register your application using the Google Developers Console. After you’ve registered, go to the API Access tab and copy the “Client ID” and “Client secret” values and specify “Redirect URI“, which you’ll need later.

At least product name must be specified:

Now create credentials:

Specify redirect URI:

After you’ve registered, copy the “Client ID” and “Client secret” values, which you’ll need later:

Now we can define clientID, clientSecret, redirect url and scope variables, as well as Google OAuth 2.0 server addresses. Scope basically specifies what services we want to have access to. In our case it is user’s email address and IMAP/SMTP access:

const string clientID = "12345.apps.googleusercontent.com";
const string clientSecret = "XXXYYY111";
const string redirectUri = "http://www.yourdomain.com/oauth2callback";

AuthorizationServerDescription server = new AuthorizationServerDescription
    {
        AuthorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth"),
        TokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token"),
        ProtocolVersion = ProtocolVersion.V20,
    };
List<string> scope = new List<string> 
    { 
        GoogleScope.ImapAndSmtp.Name,
        GoogleScope.EmailScope.Name 
    };

Turn on Google+ API

Remember to turn on Google+ API:
Turn on Google+ API

It is required to obtain email address of the user.

Obtain an OAuth 2.0 access token

As we are using ASP.NET we’ll use WebServerClient class:

WebServerClient consumer = new WebServerClient(server, clientID, clientSecret);

// Here redirect to authorization site occurs
consumer.RequestUserAuthorization(scope, new Uri(redirectUri));

If you use ASP.NET MVC the last line is different:

// Here redirect to authorization site occurs
OutgoingWebResponse response = consumer.PrepareRequestUserAuthorization(
    scope, new Uri(redirectUri));
return response.AsActionResult();

At this point user is redirected to Google to authorize the access:

After this step user is redirected back to your website (http://www.yourdomain.com/oauth2callback). Following is this callback code. Its purpose is to get a refresh-token and an access-token:

WebServerClient consumer= new WebServerClient(server, clientID, clientSecret);
consumer.ClientCredentialApplicator =
    ClientCredentialApplicator.PostParameter(clientSecret);
IAuthorizationState grantedAccess = consumer.ProcessUserAuthorization(null);

string accessToken = grantedAccess.AccessToken;

An access token is usually valid for a maximum of one hour, and allows you to access the user’s data. You also received a refresh token. A refresh token can be used to request a new access token once the previous expired.

Access IMAP/SMTP server

Finally we’ll ask Google for user’s email and use LoginOAUTH2 method to access Gmail’s IMAP server:

GoogleApi api = new GoogleApi(accessToken);
string user = api.GetEmailPlus();

using (Imap imap = new Imap())
{
    imap.ConnectSSL("imap.gmail.com");
    imap.LoginOAUTH2(user, accessToken);

    imap.SelectInbox();
    List<long> uids = imap.Search(Flag.Unseen);

    foreach (long uid in uids)
    {
        var eml = imap.GetMessageByUID(uid);
        IMail email = new MailBuilder().CreateFromEml(eml);
        Console.WriteLine(email.Subject);
    }
    imap.Close();
}

Refreshing access token

An access token is usually short lived and valid for a maximum of one hour. The main reason behind this is security and prevention of replay attacks. This means that for long-lived applications you need to refresh the access token.

In most cases web applications don’t need to refresh access token (they request new one every time), thus when using WebServerClient refresh token is not sent. To force sending refresh token you need to set access_type url parameter to offline:

AuthorizationServerDescription authServer = new AuthorizationServerDescription
{
    AuthorizationEndpoint = 
        new Uri("https://accounts.google.com/o/oauth2/auth?access_type=offline"),
    ...
};

Your refresh token will be sent only once – don’t loose it!

We recommend storing entire IAuthorizationState object received from WebServerClient.ProcessUserAuthorization method call. This object contains both: refresh token and access token, along with its expiration time.

The process of refreshing access token is simple:

IAuthorizationState grantedAccess = ...
consumer.RefreshAuthorization(grantedAccess, TimeSpan.FromMinutes(20));

In the example above the access token will not be refreshed if its remaining lifetime exceeds 20 minutes.

Retrieving lost refresh token

When your application receives a refresh token, it is important to store that refresh token for future use. If your application loses the refresh token, it will have to re-prompt the user for consent before obtaining another refresh token.

You’ll need to add approval_prompt=force to your parameters:

 AuthorizationServerDescription authServer = new AuthorizationServerDescription
 {
     AuthorizationEndpoint = 
          new Uri("https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force"),
     ...
 };