Sakti Mohapatra
Sakti Mohapatra

Reputation: 3

"Subscription validation request failed. Response must exactly match validationToken query parameter."

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

Answers (4)

A Kingscote
A Kingscote

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

@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

Angelica E
Angelica E

Reputation: 1

valtoken=request.args.get('validationToken')
resp=app.response_class(valtoken,status=200,content_type="text/plain")
return resp

Upvotes: 0

baywet
baywet

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

Related Questions