Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AcquireTokenInteractive parent param is not intuitive #918

Closed
1 of 7 tasks
bgavrilMS opened this issue Feb 27, 2019 · 18 comments
Closed
1 of 7 tasks

AcquireTokenInteractive parent param is not intuitive #918

bgavrilMS opened this issue Feb 27, 2019 · 18 comments

Comments

@bgavrilMS
Copy link
Member

bgavrilMS commented Feb 27, 2019

Which Version of MSAL are you using ?
MSAL 3 preview

Platform
Android

What authentication flow has the issue?

  • Desktop / Mobile
    • Interactive
    • Integrated Windows Auth
    • Username Password
    • Device code flow (browserless)
  • Web App
    • Authorization code
    • OBO
  • Web API
    • OBO

Repro

  1. Migrate an interactive request from MSAL 2 to MSAL 3. In MSAL3, the builder API requires you to pass two parameters:

AcquireTokenIntrective(IEnumerable scopes, object parent)

  1. The "object parent" is not intuitive. If you come from MSAL2, you will pass a UIParent. MSAL3 will throw an InvalidOperationException on Android and net45.

Expected behavior
a. Better code docs
b. Throw an MSALClientException
c. Rename the second param to "windowOrActivity"
d. windowOrActivity is available on the ClientApplication if specified on the AquireToken call it takes priority
e. continue throwing exception if not specified on platforms where it's needed. exception should tell where it can be set
f. Let Activity and Window be required param on AcquireToken, but allowing null if specified on the CA object. Otherwise throw!

@jmprieur
Copy link
Contributor

Maybe the overrides should be different and explicity depending on the platforms / reference library:

  • Activity on Android
  • Window on .NET FW
  • object on .NET standard?
    what do you think, @bgavrilMS ?

@jmprieur jmprieur added this to the 3.1 milestone Feb 28, 2019
@bgavrilMS
Copy link
Member Author

We can "shape" the public API like you describe, but we need to keep the overload with "object parent" on .NetStandard

@jmprieur
Copy link
Contributor

yes @bgavrilMS : that's what I meant by "object on .NET standard".

@bgavrilMS
Copy link
Member Author

bgavrilMS commented Feb 28, 2019

Sounds good. How about an API like:

//NetStandard (this will be on all platforms at runtime, but only on NetStandard at build time)
AquireTokenInteractive(IEnumerable<string> scopes, object windowOrActivity)

//Android 
AquireTokenInteractive(IEnumerable<string> scopes, Activity activity)

//net45 
AquireTokenInteractive(IEnumerable<string> scopes)
AquireTokenInteractive(IEnumerable<string> scopes, IntPtr windowPtr)
AquireTokenInteractive(IEnumerable<string> scopes, IWin32Window window)

//Mac
AquireTokenInteractive(IEnumerable<string> scopes)
AquireTokenInteractive(IEnumerable<string> scopes, NSWindow window)

// iOS
AquireTokenInteractive(IEnumerable<string> scopes)

// UWP
AquireTokenInteractive(IEnumerable<string> scopes)

@jmprieur
Copy link
Contributor

jmprieur commented Feb 28, 2019

this looks perfect, @bgavrilMS !
Clear and non-ambiguous

@henrik-me : given that this is a breaking change for UWP and IOS, I'd like to take this before we remove the -preview (3.1) ?

@dansiegel
Copy link

dansiegel commented Mar 11, 2019

I think this is entirely the WRONG place to be requiring the Window/Activity... this really should be done in the setup of client. What I would think is that you might have:

var pca = PublicClientApplicationBuilder.Create(options.ClientId)
                    .WithB2CAuthority(authority)
                    .WithActivity(someActivity) // Or other platform specific type
                    .Build();

// Authority only required if its intentional to override the initial authority from the PCA Builder
var result = await pca.AquireTokenInteractive(scopes)
                      .WithAuthority(someAuthority)
                      .WithAccount(account)
                      .ExecuteAsync();
          

@jmprieur
Copy link
Contributor

thanks @dansiegel this makes sense.
Don't we think that we should be able to center the sign-in dialog on a particular part of the UI (and therefore also an override of acquire token interactive)

@henrik-me
Copy link
Contributor

@dansiegel : thanks a lot for the feedback. To me this makes a lot of sense for a specific platform. Also it makes a lot of sense to specify the UI parameters at the ClientApplication level, with an option to override the behavior at the interactive call if needed.

I'm not currently able to see how code written in a shared module which is used both on Android, Windows, and iOS would handle this platform specific elements if not having some compiler flags or similar. Are you having something special in mind for this scenario?

@bgavrilMS @jmprieur : does it make sense to add .WithActivityOrWindow, .WithUiParent, or similar to the PCA as well as the ATI ? And then allowing overriding it in the AquireTokenInteractive builder? I suppose the reason we don't do this in the ATI call is that it's a required param and we have designed the interface to have required params in the c'tor.

@jmprieur
Copy link
Contributor

@henrik-me : this makes sense to me. even .WithParentActivityOrWindow and strongly typed overrides in the case of the window (and at both levels). Now there is also the case of .NET Standard, and I believe that @bgavrilMS had some thought on this. We'll discuss it today together.

We have a precedent of exclusive required parameters: AcquireTokenSilent accepts requires either an IAccount (which can be null) or a loginHint.

cc: @dansiegel

@dansiegel
Copy link

It seems to me that really the client has to be constructed from Platform code... how exactly you might go about that would probably depend on your architecture... for me I'd use a DI Container... if there is a need to know something platform specific like the Activity or Current Window then I don't see this as something that we should ever need to be able to override from the specific authorization call like AquireTokenInteractive.

Also if any of you will be at the MVP Summit, I'd be happy to sit down with you next week and discuss more in detail. As well as to cover some of the difficulties that I've been encountering.

@jmprieur jmprieur added the v3 label Mar 14, 2019
@henrik-me
Copy link
Contributor

@jennyf19 says : the iOS suggestion is missing the ViewController

triage: updating description to include what's discussed

@henrik-me henrik-me modified the milestones: 3.0.1, 3.0.2 Mar 14, 2019
@jmprieur
Copy link
Contributor

jmprieur commented Apr 2, 2019

@henrik-me @bgavrilMS @jennyf19 @MarkZuber @trwalke
I would like us not to postpone this one again :)

@HappyNomad
Copy link

I'm putting all the MSAL client code in my view-model. Because of that, I won't have a reference to any view objects. I'm hoping that the API you decide on doesn't require me to break the MVVM design pattern. Please keep this scenario in mind.

@bgavrilMS
Copy link
Member Author

@ChainReactive - MSAL pops up a UI and on some frameworks we need a parent view , i.e. on Xamarin.Android you need to pass in the Activity. You need not do this on any other platform. You may pass a reference to the window on .net desktop (e.g. WPF) and we will use it to center the browser, but nothing more.

I understand the advantages of MVVM / MVC and one of the ways to overcome this is to abstract getting the current view in a service. For example on Android you can use https://github.com/jamesmontemagno/CurrentActivityPlugin

@jmprieur jmprieur modified the milestones: 3.0.3, 3.0.4 Apr 4, 2019
@bgavrilMS
Copy link
Member Author

bgavrilMS commented Apr 10, 2019

#1059

This exposes both platform specific and a shared (netstandard) way for passing in the UI parent.

We discussed about exposing this on the PCA level as well as the AcquireTokenInteractive level, and decided to expose it only on AcquireTokenInteractive level. The reason is that on Android, and (soon) on iOS, developers NEED to pass the Activity / ViewController that started the authentication flow. The PCA Activity / ViewController will likely NOT be that one. This will lead to bugs.

I don't think this goes against DI or prevents having all auth in platform specific code. Developers need to keep track of the current Activity or ViewController that would kick off interactive auth. Interactive auth is a builder API, you can create a partial builder at the start of the app and then finalize it by passing the Activity.

@jmprieur
Copy link
Contributor

jmprieur commented Apr 11, 2019

@bgavrilMS
Copy link
Member Author

Can I do any work to help with the tutorials and quickstarts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants