Reputation: 3
I have the requirement to enable a subscription for change notifications for OneDrive (me/drive/SharedWithMe) but it is giving error when I post the payload.
When I change the resource to OneDrive( me/drive/root) which Microsoft API recommends for subscriptions but that also giving error.
I set up the API permission for the app. Few of the application permission which needs admin consent but could not be done for the current user. User grants are given below.
I have created ngrok URL to redirect webserver http://localhost:5000 /notify to ngrok URL. This is mentioned in the payload for posting for a new subscription. Python code also is given below.
I want to know what is the prerequisite for the enabling subscription. Please provide light on license requirement, API permission and scopes, resource group, and azure key vault. This requirement is for OneDrive storage subscription.
Document referenced: https://learn.microsoft.com/en-us/samples/microsoftgraph/aspnetcore-webhook-with-resource-data/sample-application---microsoft-graph-change-notifications/
When we are posting the payload for new subscriptions, it is giving error.
payload: { "changeType": "updated", "notificationUrl": "https://d76209350b89.ngrok.io/notify", "resource": "me/drive/root", "expirationDateTime": "2020-07-24T18:23:45.9356913Z", "clientState": "secretClientValue", "latestSupportedTlsVersion": "v1_2" }
subscriptions: https://graph.microsoft.com/v1.0/subscriptions
{
"error": {
"code": "InvalidRequest",
"message": "Subscription validation request failed. Response must exactly match validationToken query parameter.",
"innerError": {
"date": "2020-07-22T16:45:41",
"request-id": "d5d7f05b-9f3d-44a9-a74a-9f21e3c8a9ba"
}
}
}
Endpoint that receives the validation request
enter code here:
http_header={'Authorization':f'Bearer
{token_response["accessToken"]}','Content-type':'application/json'}
print(http_header)
post_data={
"changeType": "updated",
"notificationUrl": REDIRECT_URI_2,
"resource": "me/drive/root",
"expirationDateTime": "2020-07-22T18:23:45.9356913Z",
"clientState": "secretClientValue",
"latestSupportedTlsVersion": "v1_2"
}
res=requests.post('https://graph.microsoft.com/v1.0/subscriptions',headers=http_header,data=post_data)
Receives the change notifications
@app.route("/notify",methods=['GET','POST'])
def onedrive():
valtoken=flask.request.args.get('validationToken')
valtok=valtoken.replace(':','%3a')
valt=valtok.replace(' ','+')
subscribe_url = f'https://062dece903f6.ngrok.io/notify?validationToken={valt} HTTP/1.1'
resp = flask.Response(status=200)
resp.headers['content-type']="plain/text"
resp.headers['token']=valt
resp.headers['location'] = subscribe_url
return resp
I am developing in Python. Anyone has done this before please share.
Thanks.
Upvotes: 0
Views: 1840
Reputation: 433
from urllib.parse import unquote
from flask import Flask, request, make_response
app = Flask("__init__")
@app.route("/", methods=["GET", "POST"])
def main():
validation = unquote(request.args.get("validationToken"))
resp = make_response(validation, 200)
resp.headers["Content-Type"] = "text/plain; charset=utf-8"
return resp
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=5000)
Then im just using ngrok
ngrok http 5000
And using the public URL in my subscription request
Upvotes: 0
Reputation: 1
@app.route("/notify",methods=['POST'])
def onedrive():
valtoken=flask.request.args.get('validationToken')
resp=app.response_class(response=urllib.parse.unquote(valtoken),status=200,mimetype='plain/text')
return resp
Upvotes: 0
Reputation: 1
valtoken=request.args.get('validationToken')
resp=app.response_class(valtoken,status=200,content_type="text/plain")
return resp
Upvotes: 0
Reputation: 5372
The content type should be text/plain
. The validation token value should be returned as the response body and not a header. There's no need for a location header.
Also: I'm not sure why you are replacing characters but you should simply url decode and return as is.
Upvotes: 0