OAuth 2.0 with Gmail over IMAP for service account
- OAuth 2.0 with Gmail over IMAP for web applications (Google.Apis)
- OAuth 2.0 with Gmail over IMAP for installed applications (Google.Apis)
- OAuth 2.0 with Gmail over IMAP for service account (Google.Apis)
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
Use Nuget to download “Google.Apis.Auth” package.
Import namespaces:
// c#
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Responses;
using System.Security.Cryptography.X509Certificates;
using Limilabs.Client.Authentication.Google;
using Limilabs.Client.IMAP;
' VB.NET
Imports Google.Apis.Auth.OAuth2
Imports Google.Apis.Auth.OAuth2.Flows
Imports Google.Apis.Auth.OAuth2.Requests
Imports Google.Apis.Auth.OAuth2.Responses
Imports System.Security.Cryptography.X509Certificates
Imports Limilabs.Client.Authentication.Google
Imports Limilabs.Client.IMAP
Google Cloud
First you need to visit Google Cloud Console and create a project:
Now create a new service account:
Add a service name and remember an email address assigned to your service:
Then you need to create a private key for this service:
Download and save this private key (XYZ.p12), you’ll need that later:
Google Domain administration
Final part is to allow this service to access your domain. You’ll perform this steps in your domain administration panel.
Remember the Client ID first, and go to your domain administration panel:
In the main menu select Security / Access and data control / API controls
Then Manage domain wide delegation
Use previously remembered Client ID and https://mail.google.com/
, which is IMAP/SMTP API scope:
Alternatively you can use https://www.googleapis.com/auth/gmail.imap_admin
scope.
When authorized with this scope, IMAP connections behave differently:
- All labels are shown via IMAP, even if users disabled “Show in IMAP” for the label in the Gmail settings.
- All messages are shown via IMAP, regardless of what the user set in “Folder Size Limits” in the Gmail settings.
Access IMAP/SMTP server
// C#
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[] { "https://mail.google.com/" },
// Scopes = new[] { "https://www.googleapis.com/auth/gmail.imap_admin" },
User = userEmail
}.FromCertificate(certificate));
bool success = await credential.RequestAccessTokenAsync(
CancellationToken.None);
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
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 { _
.Scopes = {"https://mail.google.com/"}, _
' .Scopes = {"https://www.googleapis.com/auth/gmail.imap_admin"}, _
.User = userEmail _
}.FromCertificate(certificate))
Dim success As Boolean = credential.RequestAccessTokenAsync(
CancellationToken.None).Result
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