4

I'm using the following code to get an access token and connect to the mail folder:

var confidentialClientApplicationBuilder = ConfidentialClientApplicationBuilder.Create(clientId).WithClientSecret(clientSecret).WithTenantId(tenantId).Build();

var scopes = new string[] { ".default" };

var authToken = await confidentialClientApplicationBuilder.AcquireTokenForClient(scopes).ExecuteAsync();

var oauth2 = new SaslMechanismOAuth2(username, authToken.AccessToken);

using (ImapClient client = new ImapClient())
{
    await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
    await client.AuthenticateAsync(oauth2);

    //TODO

    await client.DisconnectAsync(true);
}

Everything seems to work correctly here, the ImapClient is connected and I can see oauth2.Credentials.Password is populated with the access token. However, when I run it the AuthenticateAsync method throws the error:

MailKit.Security.AuthenticationException: 'Authentication failed.'

I have noticed that the authToken.Account is null and that's why I'm passing the account name in by the string username. Also it seems I have to use the .default scope as anything else causes an error on AcquireTokenForClient as per this question.

Any ideas what I'm doing wrong here?

TheLethalCoder
  • 6,668
  • 6
  • 34
  • 69
  • From the mailkit examples it looks like there's two different oauth2 classes: `SaslMechanismOauth2` and `SaslMechanismOauth2Bearer`. The examples also uses other scopes than `.default`. Maybe see if the example code works or if it also gives "Authentication failed", and if it works, adjust your code accordingly? https://github.com/jstedfast/MailKit/blob/master/Documentation/Examples/OAuth2ExchangeExample.cs – TheHvidsten Jul 04 '22 at 14:46
  • @GTHvidsten Even using the exact code from the sample linked I'm getting Authentication failed exceptions. unfortunately. – TheLethalCoder Jul 04 '22 at 15:01
  • The example works just fine on my end when I tried. How have you created your AppRegistration in Azure? What does the AccessToken contain when you use the example (decode token on jwt.io and obfuscate personal info)? I could recreate your error when I use your original way of getting AccessToken, which I expect is the cause of this. Using `ConfidentialClientApplicationBuilder` with ClientSecret lacks `Account` (as you discovered) and I assume that's the reason (together with scopes) that the authentication fails. – TheHvidsten Jul 04 '22 at 16:47
  • I am still getting Authenticatin Failed. Please help someone. I tried both Office365 and Microsoft.Graph Scope – Mit Jacob Apr 20 '23 at 18:42
  • @MitJacob I tried a few things and in the end went with a pure GraphAPI approach ignoring MailKit. However, I _think_ you need to follow the Powershell part in [this article](https://www.codewrecks.com/post/security/accessing-office-365-imap-with-oauth2/) to get this working. – TheLethalCoder Apr 24 '23 at 08:13

1 Answers1

4

It seems that what you want is not possible at this time. See this Github issue for details.

Basically, using ConfidentialClientApplicationBuilder can only use scopes defined as "API permissions" on your AppRegistration. If you have registered IMAP.AccessAsUser.All or Mail.Read Graph permissions, and requested them using the https://graph.microsoft.com/.default scope, you will get an access token, but it can only be used by the Graph API REST endpoints Microsoft has exposed.

MailKit does not support these Graph API endpoints (as the linked issue describes).

In order to use the IMAP support in MailKit it seems you must get an access token using PublicClientApplicationOptions as demonstrated in the MailKit example. This has the disadvantage of popping up the browser asking the user to authenticate themselves.

It is, however, uncertain how long this will work, as it seems Microsoft will deprecate their IMAP endpoints (as mentioned in the previously linked issue)

TheHvidsten
  • 4,028
  • 3
  • 29
  • 62
  • Unfortunately, this seems to be the case so accepting. I'll have to find another way of doing this, thanks for the help. – TheLethalCoder Jul 08 '22 at 08:43
  • @TheLethalCoder Did you find the solution for this? Can you share me your solution? – Rango Jun 22 '23 at 11:14
  • 2
    @Rango I ended up rolling the solution through Graph API myself instead of using MailKit/MimeKit. However, I believe [this article](https://www.codewrecks.com/post/security/accessing-office-365-imap-with-oauth2/) should help a bit. I _think_ I got it working after looking into the Powershell commands within it. – TheLethalCoder Jun 22 '23 at 11:22