Pnpjs: [405] Method Not Allowed when RequestDigest required

Created on 18 Jan 2019  路  6Comments  路  Source: pnp/pnpjs

Thank you for reporting an issue, suggesting an enhancement, or asking a question. We appreciate your feedback - to help the team understand your
needs please complete the below template to ensure we have the details to help. Thanks!

Please check out the Docs to see if your question is already addressed there. This will help us ensure our documentation covers the most frequent questions.

Category

  • [ ] Enhancement
  • [x] Bug
  • [x] Question
  • [ ] Documentation gap/issue

Version

Please specify what version of the library you are using: [ v1.2.8 ]

Please specify what version(s) of SharePoint you are targeting: [ SharePoint Online ]

If you are not using the latest release, please update and see if the issue is resolved before submitting an issue.

Expected / Desired Behavior / Question

This is my first time using pnpjs, and I'm initially trying to read and write to a basic list to make sure I know what I'm doing before I go much further.

I have written a basic application to read from a list, and then write an item to the list (see below)

Observed Behavior

I get an error that appears to occur when a requestdigest needs to be retrieved.
From my very basic idea of how this might work i tried to trace back in the pnpjs and i can't see any reason why it would be doing a GET instead of a POST
error

Steps to Reproduce

The only change to code before pasting is redacting my company's org name from the url

  • the client ID and secret are saved in an environment variable
  • I have created a brand new clean app with the following dependencies only
  "dependencies": {
    "@pnp/common": "^1.2.8",
    "@pnp/logging": "^1.2.8",
    "@pnp/nodejs": "^1.2.8",
    "@pnp/odata": "^1.2.8",
    "@pnp/sp": "^1.2.8"
  }
  • I have authorised the App to the /sandpit site with the following
<AppPermissionRequests>
     <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web/" Right="FullControl"/>
</AppPermissionRequests>

And so here's the code...

var sp = require(`@pnp/sp`).sp;
var SPFetchClient = require(`@pnp/nodejs`).SPFetchClient;

sp.setup({
    sp: {
        fetchClientFactory: () => {
            return new SPFetchClient("http://org.sharepoint.com/sandpit/", process.env.SP_Auth_ClientID, process.env.SP_Auth_Secret);
        }
    }
});

// This Works :)
sp.web.lists.getByTitle("PlainList").items.select("Title").get().then((results) => {
    console.log(results);
});

// This doesn't work :(
sp.web.lists.getByTitle("PlainList").items.add({
    Title: "Another Test Item"
}).then((iar) => {
    console.log(iar);
}).catch((err) => {
    console.error(err);
});

// This also doesn't work :(
/* 
sp.web.lists.getByTitle("PlainList").items.getById(1).update({
    Title: "My New Title",
}).then(i => {
    console.log(i);
}).catch((err) => {
    console.error(err);
});
*/

I'm fully aware that I've probably missed something simple, but I've followed the instructions in the document and kept it as simple as possible and I just cannot get my head around it :(

details needed not a bug question

Most helpful comment

Hi @jasonalex13,

For backed processes when the library knows nothing about SP site URL before it's implicitly provided, it's better defining the environment URL and pass it to setup method or even better approach is to create new web object using the corresponding URL.

sp.setup({
  sp: {
    // ...
    baseUrl: 'https://contoso.sharepoint.com/sites/site/web'
  }
});

or using the implicit web declaration:

import { Web } from '@pnp/sp';
const web = new Web('https://contoso.sharepoint.com/sites/site/web');

Also, not sure that AppPermissionRequests are sufficient without any level to the site collection scope. Just not sure here and something tells me it should be checked too.

All 6 comments

Hi @jasonalex13,

For backed processes when the library knows nothing about SP site URL before it's implicitly provided, it's better defining the environment URL and pass it to setup method or even better approach is to create new web object using the corresponding URL.

sp.setup({
  sp: {
    // ...
    baseUrl: 'https://contoso.sharepoint.com/sites/site/web'
  }
});

or using the implicit web declaration:

import { Web } from '@pnp/sp';
const web = new Web('https://contoso.sharepoint.com/sites/site/web');

Also, not sure that AppPermissionRequests are sufficient without any level to the site collection scope. Just not sure here and something tells me it should be checked too.

In nodejs is should be sufficient to set the url in the client and not have to set it via config. I would check the permissions. I think you need to add the AllowAppOnlyPolicy attribute to your xml as a start. Can you also up the permissions as shown below, at least for a quick test? Don't recommend something this broad for production, but will ensure you can make the calls for testing without perms getting in the way.

  <AppPermissionRequests AllowAppOnlyPolicy="true">
    <AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="FullControl" />
    <AppPermissionRequest Scope="http://sharepoint/social/tenant" Right="FullControl" />
    <AppPermissionRequest Scope="http://sharepoint/search" Right="QueryAsUserIgnoreAppPrincipal" />
  </AppPermissionRequests>

Give that a try and let us know. Thanks!

Thanks for the suggestions so far :)

Just to double check @patrick-rodgers - should that XML be applied in the admin centre?

I've also re-added the permissions with "AllowAppOnlyPolicy" on the web level and the site collection level and the output of the script is still exactly the same :(

You can review the docs page on setting up app permissions for pointers to ensure you are setting up the perms correctly. I would create a new app id to go through the registration process, in my experience it works best starting from scratch.

I've tried this morning creating a new app id/secret and set up the exact permissions from the docs in the admin centre.
Just to be sure I've also added explicitly added FullControl permissions to the site collection, the web in question, and the specific list i'm trying to work on, but I'm still getting a 405 error.

Wow, I am such a digital dummy.
All I needed to do was change 'http' to 'https' in SPFetchClient()

Was this page helpful?
0 / 5 - 0 ratings