Office 365 + IMAP + OAuth2 [Solved]
-
We currently have an intranet portal which uses IMAP to read email from a shared mailbox on Office365, using the excellent MailKit[^] library. I've just been made aware that Microsoft is going to disable basic authentication for IMAP clients. Originally, this was going to happen in October, but it's since been pushed back to the second half of 2021. Basic Auth and Exchange Online – February 2020 Update - Microsoft Tech Community - 1191282[^] After some panicked reading and experimentation (and much swearing), I've managed to get the MSAL[^] library to return an OAuth2 access token:
const string ClientId = "...";
const string Username = "...";
SecureString password = ...;var scopes = new[] { "https://outlook.office365.com/.default" };
var app = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs).Build();
var tokenResult = await app.AcquireTokenByUsernamePassword(scopes, Username, password).ExecuteAsync(cancellationToken);After configuring the application as a "public client" in the Azure portal, giving it
Mail.ReadWriteAll
andMail.SendAll
permissions, and granting admin consent for my organisation, this code now returns a seemingly-valid access token. According to the author of the MailKit library[^], all I need to do now is use the token to authenticate:using var client = new ImapClient();
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto, cancellationToken);
await client.AuthenticateAsync(new SaslMechanismOAuth2(Username, tokenResult.AccessToken), cancellationToken);Unfortunately, that simply throws an "authentication failed"<
-
We currently have an intranet portal which uses IMAP to read email from a shared mailbox on Office365, using the excellent MailKit[^] library. I've just been made aware that Microsoft is going to disable basic authentication for IMAP clients. Originally, this was going to happen in October, but it's since been pushed back to the second half of 2021. Basic Auth and Exchange Online – February 2020 Update - Microsoft Tech Community - 1191282[^] After some panicked reading and experimentation (and much swearing), I've managed to get the MSAL[^] library to return an OAuth2 access token:
const string ClientId = "...";
const string Username = "...";
SecureString password = ...;var scopes = new[] { "https://outlook.office365.com/.default" };
var app = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs).Build();
var tokenResult = await app.AcquireTokenByUsernamePassword(scopes, Username, password).ExecuteAsync(cancellationToken);After configuring the application as a "public client" in the Azure portal, giving it
Mail.ReadWriteAll
andMail.SendAll
permissions, and granting admin consent for my organisation, this code now returns a seemingly-valid access token. According to the author of the MailKit library[^], all I need to do now is use the token to authenticate:using var client = new ImapClient();
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto, cancellationToken);
await client.AuthenticateAsync(new SaslMechanismOAuth2(Username, tokenResult.AccessToken), cancellationToken);Unfortunately, that simply throws an "authentication failed"<
Thanks to "paulflo150" on GitHub, I was able to authenticate with the token by changing the scopes to:
var scopes = new[] { "https://outlook.office365.com/IMAP.AccessAsUser.All" };
Now I need to find out how to connect to a shared mailbox. The usual trick of appending
"\shared-mailbox-alias"
to the username results in the same "authentication failed" error, and if I authenticate without it there are no "shared namespaces" available.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
We currently have an intranet portal which uses IMAP to read email from a shared mailbox on Office365, using the excellent MailKit[^] library. I've just been made aware that Microsoft is going to disable basic authentication for IMAP clients. Originally, this was going to happen in October, but it's since been pushed back to the second half of 2021. Basic Auth and Exchange Online – February 2020 Update - Microsoft Tech Community - 1191282[^] After some panicked reading and experimentation (and much swearing), I've managed to get the MSAL[^] library to return an OAuth2 access token:
const string ClientId = "...";
const string Username = "...";
SecureString password = ...;var scopes = new[] { "https://outlook.office365.com/.default" };
var app = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs).Build();
var tokenResult = await app.AcquireTokenByUsernamePassword(scopes, Username, password).ExecuteAsync(cancellationToken);After configuring the application as a "public client" in the Azure portal, giving it
Mail.ReadWriteAll
andMail.SendAll
permissions, and granting admin consent for my organisation, this code now returns a seemingly-valid access token. According to the author of the MailKit library[^], all I need to do now is use the token to authenticate:using var client = new ImapClient();
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto, cancellationToken);
await client.AuthenticateAsync(new SaslMechanismOAuth2(Username, tokenResult.AccessToken), cancellationToken);Unfortunately, that simply throws an "authentication failed"<
Finally managed to get the code to access a shared mailbox, with help from Sivaprakash Saripalli at Microsoft. It's simply a case of passing the email address of the mailbox instead of the username to the
SaslMechanismOAuth2
constructor.const string ClientId = "..."; // The "Application (client) ID" from the Azure apps portal
const string UserName = "..."; // The Office365 account username - user@domain.tld
SecureString Password = ...; // The Office365 account password
const string Mailbox = "..."; // The shared mailbox name - mailbox@domain.tld// Get an OAuth token:
var scopes = new[] { "https://outlook.office365.com/IMAP.AccessAsUser.All" };
var app = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs).Build();
var authenticationResult = await app.AcquireTokenByUsernamePassword(scopes, UserName, Password).ExecuteAsync(cancellationToken);// Authenticate the IMAP client:
using var client = new ImapClient();
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto, cancellationToken);
await client.AuthenticateAsync(new SaslMechanismOAuth2(Mailbox, authenticationResult.AccessToken), cancellationToken);
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
We currently have an intranet portal which uses IMAP to read email from a shared mailbox on Office365, using the excellent MailKit[^] library. I've just been made aware that Microsoft is going to disable basic authentication for IMAP clients. Originally, this was going to happen in October, but it's since been pushed back to the second half of 2021. Basic Auth and Exchange Online – February 2020 Update - Microsoft Tech Community - 1191282[^] After some panicked reading and experimentation (and much swearing), I've managed to get the MSAL[^] library to return an OAuth2 access token:
const string ClientId = "...";
const string Username = "...";
SecureString password = ...;var scopes = new[] { "https://outlook.office365.com/.default" };
var app = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs).Build();
var tokenResult = await app.AcquireTokenByUsernamePassword(scopes, Username, password).ExecuteAsync(cancellationToken);After configuring the application as a "public client" in the Azure portal, giving it
Mail.ReadWriteAll
andMail.SendAll
permissions, and granting admin consent for my organisation, this code now returns a seemingly-valid access token. According to the author of the MailKit library[^], all I need to do now is use the token to authenticate:using var client = new ImapClient();
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto, cancellationToken);
await client.AuthenticateAsync(new SaslMechanismOAuth2(Username, tokenResult.AccessToken), cancellationToken);Unfortunately, that simply throws an "authentication failed"<
-
We currently have an intranet portal which uses IMAP to read email from a shared mailbox on Office365, using the excellent MailKit[^] library. I've just been made aware that Microsoft is going to disable basic authentication for IMAP clients. Originally, this was going to happen in October, but it's since been pushed back to the second half of 2021. Basic Auth and Exchange Online – February 2020 Update - Microsoft Tech Community - 1191282[^] After some panicked reading and experimentation (and much swearing), I've managed to get the MSAL[^] library to return an OAuth2 access token:
const string ClientId = "...";
const string Username = "...";
SecureString password = ...;var scopes = new[] { "https://outlook.office365.com/.default" };
var app = PublicClientApplicationBuilder.Create(ClientId).WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs).Build();
var tokenResult = await app.AcquireTokenByUsernamePassword(scopes, Username, password).ExecuteAsync(cancellationToken);After configuring the application as a "public client" in the Azure portal, giving it
Mail.ReadWriteAll
andMail.SendAll
permissions, and granting admin consent for my organisation, this code now returns a seemingly-valid access token. According to the author of the MailKit library[^], all I need to do now is use the token to authenticate:using var client = new ImapClient();
await client.ConnectAsync("outlook.office365.com", 993, SecureSocketOptions.Auto, cancellationToken);
await client.AuthenticateAsync(new SaslMechanismOAuth2(Username, tokenResult.AccessToken), cancellationToken);Unfortunately, that simply throws an "authentication failed"<
Yes, most asynchronous development, are proposed to be antelope in the forms of rule, when AJAX overrule its dynamic system.
-
Yes, most asynchronous development, are proposed to be antelope in the forms of rule, when AJAX overrule its dynamic system.
I don't know if you have a problem with English or if you are trying to increase your reputation by randomly posting irrelevant crap; either way please stop or it will be treated as site abuse and the BanHammer will descend upon you. If it's a problem with English, write your message in your native language then use Google Translate to get an English version. If it's a reputation thing, then stop immediately.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
-
I don't know if you have a problem with English or if you are trying to increase your reputation by randomly posting irrelevant crap; either way please stop or it will be treated as site abuse and the BanHammer will descend upon you. If it's a problem with English, write your message in your native language then use Google Translate to get an English version. If it's a reputation thing, then stop immediately.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
The BanHammer is already swinging[^]. :)
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer