msgraph-sdk-javascript icon indicating copy to clipboard operation
msgraph-sdk-javascript copied to clipboard

Defer `AccountInfo` for easier `AuthCodeMSALBrowserAuthenticationProvider` initialization

Open snebjorn opened this issue 4 years ago • 2 comments

Feature Request

Is your feature request related to a problem? Please describe

AuthCodeMSALBrowserAuthenticationProvider requires AccountInfo to be initialized

new AuthCodeMSALBrowserAuthenticationProvider(msalInstance, {
      account: someAccountInfo, // <------
      scopes: ['...'],
      interactionType: InteractionType.Redirect,
});

This is problematic when setting up the Client in the constructor of a service. Because the AccountInfo might not be ready at this point.

Example:

class MyGraphService {
  readonly graphClient: Client;

  constructor(msalService: MsalService) {
    // Create an authentication provider for the current user
    const authProvider = new AuthCodeMSALBrowserAuthenticationProvider(
      msalService.instance as PublicClientApplication,
      {
        account: msalService.instance.getActiveAccount()!, // <---- 👀
        scopes: OAuthSettings.scopes,
        interactionType: InteractionType.Popup,
      }
    );

    // Initialize the Graph client
    this.graphClient = Client.initWithMiddleware({
      authProvider: authProvider,
    });
  }
}

Describe the solution you'd like

I don't believe the AccountInfo is needed before an actual request to the Graph API is made.

// Get the user from Graph (GET /me)
  const graphUser: MicrosoftGraph.User = await this.graphClient
    .api('/me')
    .select('displayName,mail,mailboxSettings,userPrincipalName')
    .get();

It would be helpful if setting the account used for the request could be deferred. It could be done multiple ways.

By changing the options bag to accept a function for fetching the account when it's needed.

interface AuthCodeMSALBrowserAuthenticationProviderOptions {
  account: AccountInfo | () => AccountInfo;
}

// would allow for
new AuthCodeMSALBrowserAuthenticationProvider(
      msalService.instance as PublicClientApplication,
      {
        account: () => msalService.instance.getActiveAccount()!,
        // ...

Another approach would be to make the account option optional and rely on PublicClientApplication.getActiveAccount() when the account option was omitted.

interface AuthCodeMSALBrowserAuthenticationProviderOptions {
  account: AccountInfo // constant
    | () => AccountInfo // deferred and called when a request goes out
    | undefined; // deferred like above, but uses PublicClientApplication.getActiveAccount()
}

AB#10956

snebjorn avatar Aug 31 '21 15:08 snebjorn

I am kinda stuck in the same place. Do you by any chance have any example for this?

r4hulp avatar Nov 18 '21 09:11 r4hulp

@r4hulp can you try this workaround?

  1. Set account as null during initialization.
const options:AuthCodeMSALBrowserAuthenticationProviderOptions: {
        account: null, // set it null first
        interactionType: InteractionType.PopUp ,
        scopes: ["user.read", "mail.send"]
    }

    // Pass the PublicClientApplication instance from step 2 to create AuthCodeMSALBrowserAuthenticationProvider instance
    const authProvider: new AuthCodeMSALBrowserAuthenticationProvider(publicClientApplication, options),


    // Initialize the Graph client
    const graphClient = Client.initWithMiddleware({
        authprovider
    });

  1. Once you have the accountInfo, can you try setting it as follows before making the Graph API call
options.account =  accountInfo;

And then call the Graph API.

const response  = await client.api(`URL`).get();

nikithauc avatar Nov 18 '21 22:11 nikithauc

Closing stale issue.

ddyett avatar Jul 25 '23 05:07 ddyett

I had to add a ts-ignore to get the work-around to work. Could it be possible to include a complete example here?

https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/AuthCodeMSALBrowserAuthenticationProvider.md

It makes no explanation of how to create the account and publicClientApplication vars

quinn avatar Jan 21 '24 23:01 quinn