- Setting up OAuth2 for use with Google Mail
- Authenticating a Desktop App with the OAuth2 Client ID and Secret
- Authenticating an ASP.NET Web App with the OAuth2 Client ID and Secret
Go to Google's Developer Console.
Click the Select A Project button in the Navigation Bar at the top of the screen.
Click the New Project button.
Fill in the name Project Name, and if appropriate, select the Organization that your program should be associated with. Then click Create.
Click the ☰ symbol, move down to APIs & Services and then select OAuth consent screen.
Select the External radio item and then click Create.
Fill in the Application name and any other fields that are appropriate for your application and then click Create.
Click + Create Credentials and then select OAuth client ID.
Select the Other radio item in the Application type section and then type in a name to use for the OAuth client ID. Once completed, click Create.
At this point, you will be presented with a web dialog that will allow you to copy the Client ID and Client Secret strings into your clipboard to paste them into your program.
Now that you have the Client ID and Client Secret strings, you'll need to plug those values into your application.
The following sample code uses the Google.Apis.Auth nuget package for obtaining the access token which will be needed by MailKit to pass on to the GMail server.
const string GMailAccount = "username@gmail.com";
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.IsExpired (SystemClock.Default))
await credential.RefreshTokenAsync (CancellationToken.None);
var oauth2 = new SaslMechanismOAuth2 (credential.UserId, credential.Token.AccessToken);
using (var client = new ImapClient ()) {
await client.ConnectAsync ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync (oauth2);
await client.DisconnectAsync (true);
}
Now that you have the Client ID and Client Secret strings, you'll need to plug those values into your application.
The following sample code uses the Google.Apis.Auth nuget package for obtaining the access token which will be needed by MailKit to pass on to the GMail server.
Add Google Authentication processor to your Program.cs.
builder.Services.AddAuthentication (options => {
// This forces challenge results to be handled by Google OpenID Handler, so there's no
// need to add an AccountController that emits challenges for Login.
options.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
// This forces forbid results to be handled by Google OpenID Handler, which checks if
// extra scopes are required and does automatic incremental auth.
options.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
// Default scheme that will handle everything else.
// Once a user is authenticated, the OAuth2 token info is stored in cookies.
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie (options => {
options.ExpireTimeSpan = TimeSpan.FromMinutes (5);
})
.AddGoogleOpenIdConnect (options => {
var secrets = GoogleClientSecrets.FromFile ("client_secret.json").Secrets;
options.ClientId = secrets.ClientId;
options.ClientSecret = secrets.ClientSecret;
});
Ensure that you are using Authorization and HttpsRedirection in your Program.cs:
app.UseHttpsRedirection ();
app.UseStaticFiles ();
app.UseRouting ();
app.UseAuthentication ();
app.UseAuthorization ();
Now, using the GoogleScopedAuthorizeAttribute, you can request scopes saved in a library as constants and request tokens for these scopes.
[GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)]
public async Task AuthenticateAsync ([FromServices] IGoogleAuthProvider auth)
{
GoogleCredential? googleCred = await _auth.GetCredentialAsync ();
string token = await googleCred.UnderlyingCredential.GetAccessTokenForRequestAsync ();
var oauth2 = new SaslMechanismOAuth2 ("UserEmail", token);
using var emailClient = new ImapClient ();
await emailClient.ConnectAsync ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
await emailClient.AuthenticateAsync (oauth2);
await emailClient.DisconnectAsync (true);
}
All of that and more has been described in Google's OAuth 2.0 documentation. However, be careful since Asp.Net MVC does not work for Asp.Net Core.