0
votes

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://docs.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.

3
I think the code for the endpoint that receives the validation request and receives the change notifications is missing, can you include it please?baywet
the endpoint that receives the validation requestSakti Mohapatra
endpoint that receives the validation request 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('graph.microsoft.com/v1.0/…)Sakti Mohapatra
please edit your original post to include the code. This way we'll get formatting and everythingbaywet
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'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 respSakti Mohapatra

3 Answers

0
votes

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.

0
votes
@app.route("/notify",methods=['POST'])
def onedrive():
    valtoken=flask.request.args.get('validationToken')
    data={"validationToken":valtoken}
    resp=app.response_class(response=json.dumps(data),status=200,mimetype='plain/text')
    return resp
0
votes
valtoken=request.args.get('validationToken')
resp=app.response_class(valtoken,status=200,content_type="text/plain")
return resp