microsoft-graph-toolkit icon indicating copy to clipboard operation
microsoft-graph-toolkit copied to clipboard

Getting "Uncaught (in promise) null" with Microsoft Graph Toolkit

Open NickTheWilder opened this issue 2 years ago • 13 comments

Following the comment from Stack Overflow

Copying and pasting the question below from the link below.

Every once in awhile I get the error "Uncaught (in promise) null" when using MGT and I'm unable to access any of the toolkit components. I refresh the page and the error goes away.

Any reason that this could be happening? I'm guessing that the SDK isn't recognizing the login state? Below is the code where I initialize my provider. Maybe that is the issue?


image

This is our header template, it is used across all pages on the site, the user profile doesn't render. We also are working on a staff directory that uses MGT components that those do not render as well when this error is present.

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Staff Portal</title>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="https://use.typekit.net/ytq8cvk.css">
    <link rel="shortcut icon" href="https://company.com/favicon.ico" type="image/x-icon">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

    <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.17.0/js/msal-browser.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@microsoft/microsoft-graph-client/lib/graph-js-sdk.js"></script>

    <script src="/site/global_scripts" type="text/javascript"></script>
    <link href="/site/global_styles" type="text/css" rel="stylesheet">
</head>

<body>
    <script src="https://unpkg.com/@microsoft/mgt/dist/bundle/mgt-loader.js"></script> 
    <mgt-msal2-provider client-id="c9512d09-****-****-****-***********" 
            scopes="user.read,people.read"
            ></mgt-msal2-provider>

    <div class="site-contain">

        <div class="sidebar">
            <a href="https://staff.company.com">
                <div class="site-logo"></div>
            </a>

            <ul>
                <a href="https://staff.company.com">
                    <li>
                        <div class="sidebar-icon home-icon"></div><span class="sidebar-text">Home Feed</span>
                    </li>
                </a>
                <a href="">
                    <li>
                        <div class="sidebar-icon support-request-icon"></div><span class="sidebar-text">Support Requests</span>
                    </li>
                </a>
                <a href="">
                    <li>
                        <div class="sidebar-icon order-form-icon"></div><span class="sidebar-text">Order Forms</span>
                    </li>
                </a>
                <a href="">
                    <li>
                        <div class="sidebar-icon analytics-icon"></div><span class="sidebar-text">Analytics</span>
                    </li>
                </a>
            </ul>


        </div>

        <div class="main">
            <div class="secondary-nav">
                <div class="dropdown">
                    <div class="user-profile noselect">
                        <mgt-person class="white-text" person-query="me" view="oneline" caching-enabled="true">
                        </mgt-person>
                    </div>
                    <div class="dropdown-content">
                        <div class="org-signout">
                            <span class="content-attr-text">company</span>
                            <input type="button" class="signout" value="Sign Out" onclick="signOut()">
                        </div>
                        <div class="account-info">
                            <mgt-person person-query="me" caching-enabled="true">
                                <template>
                                    <div class="pfp-container">
                                        <mgt-person class="dropdown-pfp" person-query="me" avatar-size="large"></mgt-person>
                                    </div>
                                    <div class="accinfo-container">
                                        <span class="row">{{person.displayName}}</span>
                                        <span class="row">{{person.userPrincipalName}}</span>
                                        <span class="row">{{person.jobTitle}}</span>
                                        <a class="row" href="https://myaccount.microsoft.com/?ref=MeControl">View Account</a>
                                    </div>
                                </template>
                                <template data-type="loading">
                                    Loading
                                </template>
                            </mgt-person>
                        </div>
                    </div>
                </div>
            </div>

            <div class="main-content-contain">

NickTheWilder avatar Jan 12 '22 19:01 NickTheWilder

Hello NickTheWilder, thank you for opening an issue with us!

I have automatically added a "needs triage" label to help get things started. Our team will analyze and investigate the issue, and escalate it to the relevant team if possible. Other community members may also look into the issue and provide feedback 🙌

ghost avatar Jan 12 '22 19:01 ghost

Once refreshed the page works correctly.

image

NickTheWilder avatar Jan 12 '22 20:01 NickTheWilder

Is there any clue on what is happening on MGT? Are you performing Graph calls using the mgt.Providers.globalProvider.client before the client gets authenticated?

sebastienlevert avatar Jan 12 '22 21:01 sebastienlevert

I authenticate via MSALv2 on a Js application that I created. I was reading through the docs and I was reading about custom providers. Do I need to pass the access token to a custom provider?

I don't perform any calls directly using mgt.Providers.globalProvider.client before the client gets authenticated.

Correct me if I'm wrong, but I was understanding that using the provider component from here would handle this.

NickTheWilder avatar Jan 12 '22 21:01 NickTheWilder

Yes, the provider manages this, but you could still call Graph before you get logged in by using the client available as part of the Provider. I see you are referencing the Graph JS SDK and msal-browser in the head of your application. Is it because you are also leveraging them later in the app? msal-browser and the JS SDK are included in the MGT bundle and might cause some collision?

sebastienlevert avatar Jan 12 '22 21:01 sebastienlevert

Yes that is correct. I just removed both the msal-browser and Graph JS SDK from my code and it's breaking some functions on the site. Here's a simple example to demonstrate one of the examples for how I'm using the graph. This function acquireGraph(); is used multiple times throughout the site.

async function welcomeMessage() {
    //Getting the time of day
    let date = new Date();
    let hours = date.getHours();
    let greeting = '';

    if (hours < 12) {
        greeting = 'Good Morning';
    } else if (hours < 18) {
        greeting = 'Good Afternoon';
    } else {
        greeting = 'Good Evening';
    }

    //Getting the firstname of the user
    let json = await acquireGraph();
    let name = json.displayName;
    let firstname = name.split(' ')[0];

    //Displaying the welcome message
    $('.main-content-title').html(greeting + ', ' + firstname +'! &#x1F64C;');
}

async function acquireGraph() {
	const account = msalInstance.getAllAccounts()[0];

	const accessTokenRequest = {
		scopes: ["user.read"],
		account: account,
	};

	let tokenResponse = await msalInstance.acquireTokenSilent(accessTokenRequest);

	let payload = await fetch("https://graph.microsoft.com/beta/me", {
		headers: {
			Authorization: "Bearer " + tokenResponse.accessToken,
		},
	});

	let json = await payload.json();

	return json;
}

NickTheWilder avatar Jan 12 '22 21:01 NickTheWilder

You might be able to skip this as you already have an authenticated Graph client provided by MGT. I feel the reference competes with the one bundled in MGT and might be why you see null results. You could replace your acquireGraph method with something like this

async function acquireGraph() {
	if (Providers.globalProvider.state === ProviderState.SignedIn) {
		  let client = mgt.Providers.globalProvider.client;
	 	  let json = await client.api('https://graph.microsoft.com/beta/me').get();
		  return json;
  	}
}

The docs on this approach are here. Please let us know if this is useful!

Also, when you see a null error, do you see any network traces from Graph that are returning errors (401, 404, 429)?

sebastienlevert avatar Jan 12 '22 21:01 sebastienlevert

I can check for network traces when I see the problem occur next. I have no reliable way to reproduce this error. It seems like the token expires and needs a refresh to run as intended.

I'm going to go hands off for a few minutes and see if I can see this error again. If not, I'll dig more into the docs that you posted above and re-work the acquireGraph(); function

NickTheWilder avatar Jan 12 '22 22:01 NickTheWilder

Refreshed and null error appeared. This is all that I see in the networking tab.

image

NickTheWilder avatar Jan 12 '22 22:01 NickTheWilder

Did this happen after 60 minutes of the initial login? It might be an issue with the refresh token then...

We have an issue open, referencing just in case #844

sebastienlevert avatar Jan 12 '22 22:01 sebastienlevert

I haven't paid specific attention to the time, but 60 minutes seems about right. I checked the token response and the current one that I have set it set to expire 17:31:42. I can give a more definite answer then.

NickTheWilder avatar Jan 12 '22 22:01 NickTheWilder

Can confirm, this issue seems to occur after every 60 minutes.

NickTheWilder avatar Jan 13 '22 20:01 NickTheWilder

This seems to be linked to this issue #844

We will be looking into it in our next sprint as this becomes high priority. Thanks for reporting!

sebastienlevert avatar Jan 17 '22 21:01 sebastienlevert

@NickTheWilder do you still this issue with the MSAL2 Provider?

sebastienlevert avatar Jul 26 '23 15:07 sebastienlevert

@sebastienlevert Sorry, this was a late night accident with closing this issue. 😅

I actually have moved on from that company where this was found so I'm not sure if this is still an issue. Apologies!

NickTheWilder avatar Jul 28 '23 20:07 NickTheWilder

We will be closing it for now, but open to discuss it further if the community feels we should re-open it!

sebastienlevert avatar Jul 31 '23 16:07 sebastienlevert