jstedfast/MailKit

OAuth2 With Exchange "Authentication failed."

catmanjan opened this issue · 12 comments

Hello I've followed https://github.com/jstedfast/MailKit/blob/master/ExchangeOAuth2.md in particular "Authenticating a Web Service with OAuth2"

I've registed my app registration, given it the appropriate API permissions, I've created a service principal and added the mailbox permission to my user's mailbox, still no matter what I do I get a generic "Authentication failed." at the client.AuthenticateAsync(oauth2); line. Is there any way to diagnose further? The access token looks right to me:

{
  "typ": "JWT",
  "nonce": "z6RNs4rI6lgkV2gM6Ic6x54meALfNB2cCdiypGvs-vY",
  "alg": "RS256",
  "x5t": "H9nj5AOSswMphg1SFx7jaV-lB9w",
  "kid": "H9nj5AOSswMphg1SFx7jaV-lB9w"
}
{
  "aud": "https://ps.outlook.com",
  "iss": "https://sts.windows.net/2371829a-0c4d-422b-870f-b47456bf4d0c/",
  "iat": 1725836252,
  "nbf": 1725836252,
  "exp": 1725840152,
  "aio": "E2dgYChhlFnkFXLt67O/dpa/r3zeDwA=",
  "app_displayname": "ExternalActivityNotifier",
  "appid": "3706d681-d8a2-4996-b41a-2426890b46be",
  "appidacr": "1",
  "idp": "https://sts.windows.net/2371829a-0c4d-422b-870f-b47456bf4d0c/",
  "idtyp": "app",
  "oid": "461d0ba8-d852-4be0-99c3-28a4ead90fc0",
  "rh": "0.AUIAmoJxI00MK0KHD7R0Vr9NDAIAAAAAAPEPzgAAAAAAAADqAAA.",
  "roles": [
    "IMAP.AccessAsApp",
    "SMTP.SendAsApp"
  ],
  "sid": "d6e0f34c-3e27-47a6-89d3-80c1e9d5a514",
  "sub": "461d0ba8-d852-4be0-99c3-28a4ead90fc0",
  "tid": "2371829a-0c4d-422b-870f-b47456bf4d0c",
  "uti": "CMTQ-blf3Eyu2yCphR1QAA",
  "ver": "1.0",
  "wids": [
    "0997a1d0-0d1d-4acb-b408-d5ca73121e90"
  ],
  "xms_idrel": "7 22"
}

Here is my code, the main difference is I am using .WithClientSecret() instead of .WithCertificate()

var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create("snip")
	.WithAuthority ($"https://login.microsoftonline.com/snip/v2.0")
	.WithClientSecret ("snip")
	.Build ();

string[] scopes = ["https://ps.outlook.com/.default"];

var result = await confidentialClientApplication.AcquireTokenForClient (scopes).ExecuteAsync (cancellationToken);

var oauth2 = new SaslMechanismOAuth2 ("username@outlook.com", result.AccessToken);

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

Okay I got it working, using a hint from #1624 (comment)

In my case changing the scope to https://outlook.office365.com/.default even for IMAP made it suddenly work, I think maybe the docs need to be updated to remove the https://ps.outlook.com/.default scope (maybe its required for POP3 only?)

That's interesting. Microsoft's docs still say to use ps.outlook.com, though: https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth

I wonder if it's because you've enabled IMAP and SMTP?

@jstedfast quite possibly, I think the most reliable solution is to just always request both scopes - I can confirm that asking for both works with all 3 protocols

Good to know, thanks for experimenting a bit and letting me know!

Hey everyone, I’m encountering the same error and wanted to check with you—could the "Authentication Failed" issue be due to insufficient permissions? I’ve added the required permissions for IMAP in Azure for my application, but when I generate the bearer token and convert it to JWT, it doesn’t show the roles as @catmanjan mentioned above. Any ideas why I don't see them here:

{ "aud": "https://outlook.office365.com", "iss": "https://sts.windows.net/4365e71d-3efd-4155-b4ab-121260c95ad6/", "iat": 1726852725, "nbf": 1726852725, "exp": 1726856625, "aio": "E2dgYFDa8/p70JMorjLBGUtPORgdBgA=", "app_displayname": "snip", "appid": "snip", "appidacr": "1", "idp": "https://sts.windows.net/4365e71d-3efd-4155-b4ab-121260c95ad6/", "idtyp": "app", "oid": "32b38117-78f1-45f5-b958-8db508f7cd21", "rh": "0.ATsAHedlQ_0-VUG0qxISYMla1gIAAAAAAPEPzgAAAAAAAAA7AAA.", "sid": "6068822f-3a54-42f5-ac70-98447ed52653", "sub": "32b38117-78f1-45f5-b958-8db508f7cd21", "tid": "4365e71d-3efd-4155-b4ab-121260c95ad6", "uti": "CD1oHbI2EEaM1rEqC0Q-AA", "ver": "1.0", "wids": [ "0997a1d0-0d1d-4acb-b408-d5ca73121e90" ], "xms_idrel": "7 28" }

What scopes are you requesting in your code? Did you also run the PowerShell commands that give the service principal permission to access the mailbox?

On Sat, 21 Sept 2024, 3:26 am ItsoDimitrov, @.> wrote: Hey everyone, I’m encountering the same error and wanted to check with you—could the "Authentication Failed" issue be due to insufficient permissions? I’ve added the required permissions for IMAP in Azure for my application, but when I generate the bearer token and convert it to JWT, it doesn’t show the roles as @catmanjan https://github.com/catmanjan mentioned above. Any ideas why I don't see them here: { "aud": "https://outlook.office365.com", "iss": " https://sts.windows.net/4365e71d-3efd-4155-b4ab-121260c95ad6/", "iat": 1726852725, "nbf": 1726852725, "exp": 1726856625, "aio": "E2dgYFDa8/p70JMorjLBGUtPORgdBgA=", "app_displayname": "snip", "appid": "snip", "appidacr": "1", "idp": " https://sts.windows.net/4365e71d-3efd-4155-b4ab-121260c95ad6/", "idtyp": "app", "oid": "32b38117-78f1-45f5-b958-8db508f7cd21", "rh": "0.ATsAHedlQ_0-VUG0qxISYMla1gIAAAAAAPEPzgAAAAAAAAA7AAA.", "sid": "6068822f-3a54-42f5-ac70-98447ed52653", "sub": "32b38117-78f1-45f5-b958-8db508f7cd21", "tid": "4365e71d-3efd-4155-b4ab-121260c95ad6", "uti": "CD1oHbI2EEaM1rEqC0Q-AA", "ver": "1.0", "wids": [ "0997a1d0-0d1d-4acb-b408-d5ca73121e90" ], "xms_idrel": "7 28" } — Reply to this email directly, view it on GitHub <#1811 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABBRBV6RFRQPO5E2X45ETLZXRLC3AVCNFSM6AAAAABN3MPKIGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNRUGE4DKMZWG4 . You are receiving this because you were mentioned.Message ID: @.>

The scope I'm using is:
string[] scopes = { "https://outlook.office365.com/.default" };

Regarding the service principal, I'm not able to execute 'New-ServicePrincipal'.
Note: I executed Connect-Exchange-Online command before that
image

After granting administrator consent on the API, I can now see the roles after transferring the generated bearer token to JWT. However, I still receive an "Authentication Failed" error.

image

var confidentialClientApplication = ConfidentialClientApplicationBuilder.Create(clientId)
.WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
.WithClientSecret(clientSecret)
.Build();

string[] scopes = { "https://outlook.office365.com/.default" };
var result = await confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync(CancellationToken.None);
return result;
var oauth2 = new SaslMechanismOAuth2(email, token.AccessToken);
await client.ConnectAsync(host, port, SecureSocketOptions.SslOnConnect);
await client.AuthenticateAsync(oauth2);

I haven't executed New-ServicePrincipal yet..

Hey again, @catmanjan, sorry for the delay, but unfortunately, I don’t have the necessary access to Azure and I'm waiting for my colleagues, which is why it’s taking so much time.
We tried executing the Add-MailboxPermission -Identity ... -AccessRights FullAccess command directly in Azure PowerShell, but it still wasn't successful. The command always says that it is not recognized, even though we installed Exchange Online and logged in.
Is it possible for these rights to be granted directly in the UI?

Update:

We managed to execute the New-Service Principal and the permission granting and this fixed the issue with the authentication
Thanks for the help