msgraph-sdk-javascript
msgraph-sdk-javascript copied to clipboard
Defer `AccountInfo` for easier `AuthCodeMSALBrowserAuthenticationProvider` initialization
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()
}
I am kinda stuck in the same place. Do you by any chance have any example for this?
@r4hulp can you try this workaround?
- 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
});
- 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();
Closing stale issue.
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