–1 vote

I'm developing a desktop app.

It is already created without OAuth 2.0 we have used Imap.UseBestLogin before. Our goal is to connect with Office365 and OAuth 2.0 (Imap.LoginOAUTH2 ) to maintain the desktop app.

This is what I tried:

// LIMILABS SUPPORT WARNING: THIS CODE IS INVALID - DO NOT USE

string clientId = "client id";
string email = "testmail@contoso.com";

var app = PublicClientApplicationBuilder
    .Create(clientId)
    //.WithTenantId(tenantId)
    .WithAuthority(
        AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount)
    .WithDefaultRedirectUri()
    .Build();
// This allows saving access/refresh tokens to some storage
TokenCacheHelper.EnableSerialization(app.UserTokenCache);

var scopes = new string[]
{
    "offline_access",
    "email",
    "https://outlook.office.com/IMAP.AccessAsUser.All",
    "https://outlook.office.com/POP.AccessAsUser.All",
    "https://outlook.office.com/SMTP.Send",
};

string userName;
string accessToken;

var account = app.GetAccountsAsync().Result.FirstOrDefault();

try
{
    AuthenticationResult refresh = app
        .AcquireTokenSilent(scopes, account)
        .ExecuteAsync().Result;

    userName = refresh.Account.Username;
    accessToken = refresh.AccessToken;
}
//catch (MsalUiRequiredException ex)
catch (AggregateException ex)
{
    var result = app.AcquireTokenSilent(scopes, email)
        .ExecuteAsync().Result;

    userName = result.Account.Username;
    accessToken = result.AccessToken;
}

// LIMILABS SUPPORT WARNING: THIS CODE IS INVALID - DO NOT USE

even I use await still I cannot get a token. or the issue is in the azure ad?

by (780 points)
reopened by

1 Answer

0 votes

Please follow the steps described here:
https://www.limilabs.com/blog/oauth2-office365-exchange-imap-pop3-smtp

To handle accounts in any Azure AD and Microsoft Personal accounts you need to use:

.WithAuthority(
    AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount
)

instead of :

.WithTenantId(tenantId)

When creating the app:

var app = PublicClientApplicationBuilder
    .Create(clientId)
    .WithAuthority(
        AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount
        )
    .WithDefaultRedirectUri()
    .Build();

Your code is incorrect and completely different from the one in the article:
https://www.limilabs.com/blog/oauth2-office365-exchange-imap-pop3-smtp

  • You are missing AcquireTokenInteractive method.

  • You catch a different exception: AggregateException instead of MsalUiRequiredException.

  • You are not using await.

I strongly advise creating a new console app first.
I strongly advise going through every step in the article and making sure everything is configured exactly the same - for example: redirect urls in the AD.

by (301k points)
edited by
Yes, I followed the instruction from the URL. please the code above it seems that I used it correctly except to the catch block. I use the login hint.

Is this correct allowing those two from AD app reg authentication?

Live SDK support
Allow direct integration with the Microsoft account service (login.live.com).
Required for integration with Microsoft account SDKs such as Xbox or Bing Ads​ - YES

Allow public client flows
Enable the following mobile and desktop flows:
No keyboard (Device Code Flow) - YES
No, your code is different and makes no sense.

You are missing AcquireTokenInteractive method.

You catch AggregateException instead of MsalUiRequiredException.
Yes it doesn't make sense even if I use the MsalUiRequiredException It doesn't catch the exception but when I use the AggregateException It goes to the catch block. I got this error (System.AggregateException One or more errors occurred.

Inner Exception
MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call. ) from:

AuthenticationResult refresh = app
                    .AcquireTokenSilent(scopes, account)
                    .ExecuteAsync().Result;

Then it doesn't go to the catch block. It will just close the entire app.
You should be getting MsalUiRequiredException only.

If you are getting an AggregateException - something is not right - examine all exception that are in the InnerExceptions collection.

You may skip loading account from cache for testing purposes (users will need to log-in every time) and use AcquireTokenInteractive only:

    string userName;
    string accessToken;

    var result = await app.AcquireTokenInteractive(scopes)
        .ExecuteAsync();
 
    userName = result.Account.Username;
    accessToken = result.AccessToken;

I use the below code:

string userName;
string accessToken;

//var account = (await app.GetAccountsAsync()).FirstOrDefault();
// var account = app.GetAccountsAsync().Result.FirstOrDefault();

try
{
    //AuthenticationResult refresh = app
    //    .AcquireTokenSilent(scopes, account)
    //    .ExecuteAsync().Result;

    //userName = refresh.Account.Username;
    //accessToken = refresh.AccessToken;

    var result = app.AcquireTokenInteractive(scopes).ExecuteAsync().Result; // It stuck in here no reponse.

    userName = result.Account.Username;
    accessToken = result.AccessToken;
}
catch (MsalUiRequiredException ex)
    //catch (AggregateException ex)
{
    var result = app.AcquireTokenInteractive(scopes).ExecuteAsync().Result;

    userName = result.Account.Username;
    accessToken = result.AccessToken;
}

It stuck in AcquireTokenInteractive. Do you have any idea?

Remove comments and format your code properly.
Create a new, clean console app.
Use await.
Ask new question instead of using comments.
Please note were are not MSAL.NET support.

...