Background
I have followed all Microsoft’s documentation, and have viewed several of their samples. It appears that I’m doing everything correctly. The steps I have taken so far are as follows.
Configuration
This is a business sharepoint, so the base url is https://{tenant}-my.sharepoint.com/_layouts/15/FilePicker.aspx
. I have validated that I can access the file picker by manually navigating to that control with no issues.
We get a SharePoint token by refreshing our AAD Graph token with the https://{tenant}-my.sharepoint.com/.default
scope. The Graph token has the following in addition to other scopes necessary for my app:
- User.Read
- Files.Read
- Files.Read.All
- Sites.Read.All
My app is a Graph app, but just in case, I also added the Sharepoint Delegated permissions
- MyFiles.Read
- AllSites.Read
The token refreshes as expected, and I receive a jwt with, among other properties:
"aud": "https://{tenant}-my.sharepoint.com",
"scp": "User.Read Files.Read Files.Read.All Sites.Read.All ..."
I then configure the picker with the following, however, it never reaches the initializeMessageListener
event.
const click = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
const win = window.open("", "Picker", "width=800,height=600");
if (!win) {
throw new Error("Could not open picker window");
}
setupPicker(win);
};
const setupPicker = async (win: Window) => {
const options: IFilePickerOptions = {
sdk: "8.0",
entry: {
sharePoint: {},
},
authentication: {},
messaging: {
origin: window.location.origin, // http://localhost:5173
channelId: "27", // hard-coded for now, as in the samples
},
typesAndSources: {
mode: "files",
},
};
const queryString = new URLSearchParams({
filePicker: JSON.stringify(options),
});
const accessToken = `Bearer ${await getAccessToken()}`; // access token with properties above
const url = `${baseUrl}?${queryString}`;
const form = win.document.createElement("form");
form.setAttribute("action", url);
form.setAttribute("method", "POST");
win.document.body.appendChild(form);
const input = win.document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "access_token");
input.setAttribute("value", accessToken);
form.appendChild(input);
win.addEventListener("message", initializeMessageListener);
form.submit();
};
const initializeMessageListener = async (event: MessageEvent) => {
console.log(event);
// ideally I would setup the port here, but I never receive any messages from the window
};
I never receive any messages from the window. For the first 40 seconds, it displays an empty sharepoint picker. After that, it times out, and I receive a setup timeout error.
My gut tells me that maybe there’s some kind of configuration issue with messaging. I’m using window.location.origin
which in this case resolves to http://localhost:5173
… That’s my local app. I don’t see why I would receive no messages.
Debugging Steps
I took my sharepoint token, and attempted to call the sharepoint api at
https://{tenant}-my.sharepoint.com/_api/web/folders
- Initially, I received a
403 Access Denied
response. - I removed the Authorization header, and received
403 Attempted to perform an unauthorized operation
suggesting that I was originally properly assigning the token to the request. - I tried refreshing the token with the scope
https://{tenant}.sharepoint.com/.default
just to see what would happen. It gave me401 unauthorized
with the exceptionMicrosoft.IdentityModel.Tokens.AudienceUriValidationFailedException
, suggesting that my original token did have the correct audience.
I am able to call
https://{tenant}-my.sharepoint.com/_api/web/GetFolderByServerRelativeUrl('/my')/Files
However, it returns an empty object (which is not accurate)
{
"d": {
"results": []
}
}
If I try to access the folder directly, I get 403 Access Denied