1

I've modified sample_flask.py by adding a new action to the graphcall function. The new MSGRAPH.post call should create an openTypeExtension to the user. The code is as follows:

endpoint = 'me/extensions'
data = {
    "@odata.type": "microsoft.graph.openTypeExtension",
    "extensionName": "com.myorgname.appname",
    "permissions": "guest"
}
graphanswer = MSGRAPH.post(endpoint, headers=headers, data=data).data
print(graphanswer)

with the complete endpoint path being https://graph.microsoft.com/v1.0/me/extensions, and I've tried using the absolute uid path as well. Headers are recycled from the get example in the source. Either case results in the following error:

{'error': 
    {'code': 'RequestBroker--ParseUri', 
    'message': "Resource not found for the segment 'extensions'.", 
    'innerError': 
        {'request-id': '<omitted>', 'date': '2019-11-20T23:37:40'}
    }
}

I've checked the token in jwt.ms for the necessary scopes, which I've elevated to User.ReadWrite.All and granted permissions. When I test the post method in Graph Explorer, everything pans out very nicely and the extension is created.

Is there an obvious error here? I've been reading through everything related to "resource not found" errors and openTypeExtension, but haven't found anything pertinent thus far.

L. Batavan
  • 23
  • 4

1 Answers1

0

Everything looks right (Uri, http method, scenario, token, etc.) but I think the content-type header in your request was application/x-www-form-urlencoded instead of application/json.

David
  • 2,412
  • 1
  • 14
  • 22
  • That's a good remark. However, I already tried declaring the content-type in the header for the post call (as it is not declared in the get call), but it had no effect and the error was returned once again. Tried again after your reply, but, alas, to no avail. – L. Batavan Nov 22 '19 at 19:01
  • Can you post the request id and timestamp of the call with the content-type header as application/json? – David Nov 22 '19 at 19:02
  • Here you go: `{'request-id': 'd7df80e7-5449-412c-a86c-d1113b32cb8d', 'date': '2019-11-22T18:58:58'}` – L. Batavan Nov 22 '19 at 19:03
  • Hmmm I'm still seeing the wrong content-type for that request when the request landed in Graph servers. Can you double check it's set to application/json? Maybe use a tool like fiddler or something? I also have a local repro of getting that exact error back when the content-type is set to form-urlencoded instead of application/json – David Nov 22 '19 at 19:11
  • Everything works fine when I lift the token from the server output and use it in Advanced REST Client to send only the `authorization` and `content-type` headers; I can post, delete and whatnot. When I make the script send only the two headers, it returns the same error. Looks like I've got to delve deeper into the flask-oauthlib and see whether something's messing up the header in a post call. – L. Batavan Nov 22 '19 at 19:26
  • 1
    That's it! flask-oauthlib expects `urlencoded` by default in outgoing post data, and rewrites the content-type header if one is fed to the post function. Sending a JSON payload must be instructed by `format='json'`in the post call. Hence, the correct way to invoke is `MSGRAPH.post(endpoint, headers=headers, data=data, format='json')`. Two side notes: 1) the call should be fed a dict payload, as it encodes the payload itself; using `json.dumps()` just spews out errors, and 2) no need to use the flask-oauthlib `content_type` when you use `format`. Thank you very much for the debugging help, @Dan – L. Batavan Nov 22 '19 at 20:02