Giter Club home page Giter Club logo

Comments (17)

github-actions avatar github-actions commented on June 22, 2024

Thank you for your feedback. Tagging and routing to the team member best able to assist.

from azure-sdk-for-net.

christothes avatar christothes commented on June 22, 2024

Hi @WolfgangHG
Yes, it seems MSAL did make a change, which only affects apps targeting netx.x--windows - it is described in their changelog here

Would you mind trying to use our Broker package, which uses the Web Account Manager? I think it will work with the embedded browser option.

After adding the reference, you would change your options code to this:

 // get the window handle of the form
 IntPtr hwnd = this.Handle;

 InteractiveBrowserCredentialBrokerOptions options = new InteractiveBrowserCredentialBrokerOptions(parentWindowHandle: hwnd)
 {
     TenantId = this.textBoxTenant.Text,
     ClientId = this.textBoxClientID.Text,
     AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
     RedirectUri = new Uri("http://localhost"),
     BrowserCustomization = customizationOptions
 };

from azure-sdk-for-net.

github-actions avatar github-actions commented on June 22, 2024

Hi @WolfgangHG. Thank you for opening this issue and giving us the opportunity to assist. To help our team better understand your issue and the details of your scenario please provide a response to the question asked above or the information requested above. This will help us more accurately address your issue.

from azure-sdk-for-net.

WolfgangHG avatar WolfgangHG commented on June 22, 2024

@christothes I got it working after having added a new redirect URI in Azure (specifying "http://localhost" in InteractiveBrowserCredentialBrokerOptions does not seem to have an effect) :

AADSTS50011: The redirect URI 'ms-appx-web://Microsoft.AAD.BrokerPlugin/<my_app_id>' specified in the request does not match the redirect URIs configured for the application '<my_app_id>'. Make sure the redirect URI sent in the request matches one added to your application in the Azure portal. Navigate to https://aka.ms/redirectUriMismatchError to learn more about how to fix this.

Just for the records: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity.Broker/README.md#redirect-uris

This is bad, as we would have to tell all of our customers to add a new redirect uri to their azure configuration - and the url is specific for each customer.

The "BrowserCustomizationOptions.UseEmbeddedWebView" option does not seem to have any effect, it is always a login dialog. But it does not show the list of previously used logins (and probably does not allow selecting an already logged in user). This worked with Azure.Identity 1.11.3.
The login form does not seem to be really modal to my sample, though I set the window handle argument - at least while debugging. When switching to a different application while the login dialog is shown, I cannot click my app in taskbar to activate the login form again.

from azure-sdk-for-net.

christothes avatar christothes commented on June 22, 2024

Glad you got it working.

The "BrowserCustomizationOptions.UseEmbeddedWebView" option does not seem to have any effect, it is always a login dialog. But it does not show the list of previously used logins (and probably does not allow selecting an already logged in user). This worked with Azure.Identity 1.11.3. The login form does not seem to be really modal to my sample, though I set the window handle argument - at least while debugging. When switching to a different application while the login dialog is shown, I cannot click my app in taskbar to activate the login form again.

Yes, you are correct. In the case of the broker based login, the window is owned by the operating system. The window handle is only used to ensure it appears above the window related to the handle.

from azure-sdk-for-net.

github-actions avatar github-actions commented on June 22, 2024

Hi @WolfgangHG. Thank you for opening this issue and giving us the opportunity to assist. We believe that this has been addressed. If you feel that further discussion is needed, please add a comment with the text "/unresolve" to remove the "issue-addressed" label and continue the conversation.

from azure-sdk-for-net.

WolfgangHG avatar WolfgangHG commented on June 22, 2024

@christothes Do you internally use a "PublicClientApplicationBuilder"? If yes: is there any chance to use the "PublicClientApplicationBuilder.WithWindowsEmbeddedBrowserSupport" extension method approach suggested by Microsoft.Identity.Client? I hope that this one causes less trouble than the Broker approach (change to the redirect url required, clunky modality)?

You set the status to "issue-addressed", but currently we have only found a workaround that I don't like ;-).

from azure-sdk-for-net.

WolfgangHG avatar WolfgangHG commented on June 22, 2024

/unresolve

from azure-sdk-for-net.

christothes avatar christothes commented on June 22, 2024

@christothes Do you internally use a "PublicClientApplicationBuilder"? If yes: is there any chance to use the "PublicClientApplicationBuilder.WithWindowsEmbeddedBrowserSupport" extension method approach suggested by Microsoft.Identity.Client? I hope that this one causes less trouble than the Broker approach (change to the redirect url required, clunky modality)?

We don't intend to expose the functionality for WithWindowsEmbeddedBrowserSupport for the same reason this behavior changed in MSAL - it requires a dependency on Windows Forms to work properly, and we don't want everyone to require that.

from azure-sdk-for-net.

github-actions avatar github-actions commented on June 22, 2024

Hi @WolfgangHG. Thank you for opening this issue and giving us the opportunity to assist. To help our team better understand your issue and the details of your scenario please provide a response to the question asked above or the information requested above. This will help us more accurately address your issue.

from azure-sdk-for-net.

WolfgangHG avatar WolfgangHG commented on June 22, 2024

@christothes I took a look at the code. It seems I cannot extend InteractiveBrowserCredential and call PublicClientApplicationBuilder.WithWindowsEmbeddedBrowserSupport myself. Or do you see a change to do so?

It might work if the interface Azure.Identity.IMsalPublicClientInitializerOptions was public and the BeforeBuildClient property would be a Func instead of an action. Then I could subclass InteractiveBrowserCredential and additionally implement this interface.

Attached is a diff of the necessary changes to Azure.Identity. What do you think?
diff.txt

With this code, I could create my own options subclass:

    public class MyMsalPublicClientInitializerOptions : InteractiveBrowserCredentialOptions, IMsalPublicClientInitializerOptions
    {
      Func<PublicClientApplicationBuilder, PublicClientApplicationBuilder> IMsalPublicClientInitializerOptions.BeforeBuildClient
      {
        get
        {
          return new Func<PublicClientApplicationBuilder, PublicClientApplicationBuilder>(builder => builder.WithWindowsEmbeddedBrowserSupport());
        }
      }

      bool IMsalPublicClientInitializerOptions.UseDefaultBrokerAccount { get; set; }
    }

But I assume the interface "IMsalPublicClientInitializerOptions" is more of an internal hack for some testing purposes, so I am not sure whether this is the proper place to extend Azure.Identity.

I would prefer to move "BeforeBuildClient" to "InteractiveBrowserCredentialOptions", so that "IMsalPublicClientInitializerOptions" could be kept internal.

from azure-sdk-for-net.

WolfgangHG avatar WolfgangHG commented on June 22, 2024

Another option could be to subclass Azure.Identity.MsalPublicClient (also not public) and enhance InteractiveBrowserCredential so that the Client can be specified in some constructor. But this seems to be a lot more code changes.

from azure-sdk-for-net.

christothes avatar christothes commented on June 22, 2024

Hi @WolfgangHG -
We avoid exposing any MSAL types in our public API surface, so I'm afraid there is no way for us to expose this functionality. If you require full control of the underlying MSAL APIs, I'd recommend using Microsoft.Identity.Client directly in your application.

from azure-sdk-for-net.

WolfgangHG avatar WolfgangHG commented on June 22, 2024

@christothes This is unfortunately not possible I fear. I start from the Microsoft Graph .NET Client Library, and the https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/src/Microsoft.Graph/GraphServiceClient.cs has only constructors that accept TokenCredential or IAuthenticationProvider.
They suggest in their doc to use Azure.Identity.

Do you have a suggestion or a sample how to create a winforms login without Azure.Identity? I actually don't want to copy a lot of lines of code to call builder.WithWindowsEmbeddedBrowserSupport.

What about my suggestion to move the "BeforeBuildClient" property to "InteractiveBrowserCredentialOptions", so that "IMsalPublicClientInitializerOptions" could be kept internal? This does not expose MSAL classes I think.

from azure-sdk-for-net.

christothes avatar christothes commented on June 22, 2024

One option would be to create your own implementation of TokenCredential and in the implementation, use the PublicClientApplication, similar to how the InteractiveBrowserCredential does in Azure.Identity. See this example

from azure-sdk-for-net.

WolfgangHG avatar WolfgangHG commented on June 22, 2024

Well, I got it to work, but I don't like the solution:

string[] scopes = new string[] { "Calendars.Read" };

var app = PublicClientApplicationBuilder.Create(this.textBoxClientID.Text)
    .WithDefaultRedirectUri()
    .WithTenantId(this.textBoxTenant.Text)
    .WithWindowsEmbeddedBrowserSupport()
    .Build();

AuthenticationResult result = await app.AcquireTokenInteractive(scopes).ExecuteAsync();

MyTokenCredential mtc = new MyTokenCredential(result);
GraphServiceClient graphClient = new GraphServiceClient(mtc);
         
Calendar cal = await graphClient.Me.Calendar.GetAsync();
MessageBox.Show(this, "Calendar ID: " + cal.Id);

Class "MyTokenCredential" is simple:

public class MyTokenCredential : TokenCredential
{
  AuthenticationResult result;
  public MyTokenCredential(AuthenticationResult result)
  {
    this.result = result;
  }
  public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
  {
    AccessToken token = new AccessToken(this.result.AccessToken, this.result.ExpiresOn);
    return new ValueTask<AccessToken>(token);
  }

  public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
  {
    throw new NotImplementedException();
  }
}

Could you comment on whether this is reasonable? Fortunately, our app does not need features like token refresh, as we use the interactive login only for short term operations and get a fresh token before each operation (at least I hope our usage works like this).

But with this code, we probably loose all the features of Azure.Identity.

from azure-sdk-for-net.

christothes avatar christothes commented on June 22, 2024

Your MyTokenCredential implementation should be acquiring the token from the PublicClientApplication inside GetTokenAsync, and initializing the builder in the constructor. I wouldn't recommend just passing the AuthenticationResult to MyTokenCredential and having it use that static value.

I'd also recommend you acquire the token similar to how the example linked in my previous response does it so that you only get prompted for credentials the first time GetTokenAsync is called. MSAL will handle caching and token refresh automatically.

from azure-sdk-for-net.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.