Giter Club home page Giter Club logo

Comments (7)

21Bruce avatar 21Bruce commented on August 20, 2024

Quick update:

So I've figured out that sending the following HTTP Request message will email the user for confirmation, i've marked where to put the email with the ###EMAIL### token:

Verb: POST
Address: https://www.opentable.com/dapi/fe/gql?optype=mutation&opname=SendVerificationCodeEmail

Headers:
Origin: https://www.opentable.com
Referer: https://www.opentable.com/authenticate/start?isPopup=true&rp=https%3A%2F%2Fwww.opentable.com%2F&srs=1&isFromBookingFlow=false
x-csrf-token: 2e96d1b2-400c-4b31-9a35-1b978d67501a
x-query-timeout: 2000

Body:
{
    "operationName":"SendVerificationCodeEmail",
    "variables":{
        "verifyEmail":false,
        "email":"###EMAIL###",
        "loginType":"popup-redirect",
        "requestedAction":"https://www.opentable.com/",
        "path":"https://www.opentable.com/"
        },
        "extensions":{
            "persistedQuery":{
                "sha256Hash":"b2d378ab902bfbc650cc50fe6e20415c9ce3803c9a82fe830f7834ef31c403fe"
                }
        }
}

It appears the header x-csrf-token: 2e96d1b2-400c-4b31-9a35-1b978d67501a and the value "sha256Hash":"b2d378ab902bfbc650cc50fe6e20415c9ce3803c9a82fe830f7834ef31c403fe" must be used to authenticate the request, and I've tested that these particular values can be re-used for different emails. x-query-timeout can be set to arbitrary values and can still work, but must be set to some value for the request to work.

The server will respond with a message with the following body:

{
    "data": {
        "sendVerificationCodeEmail": {
            "correlationId": "e4cbea19-cdcd-4502-b965-78b1d14a33cd",
            "tooManyRequests": false,
            "__typename": "SendVerificationCodeResult"
        }
    },
    "loading": false,
    "networkStatus": 7
}

The "correlationId": "e4cbea19-cdcd-4502-b965-78b1d14a33cd" field is a unique identifier that must be used in later requests to link the verification code with this login session, and it changes value on each send of the above request. The "tooManyRequests": false field indicates when the server will block the client due to excessive requesting. This block is short-term.

from resolved-bot.

21Bruce avatar 21Bruce commented on August 20, 2024

After the request in the above is sent, two further requests must be made. First, a request must be made of content type x-protobuffer that I'm still looking into, although I believe this request sends a long byte string to a google service in order to compute some sort of CAPTCHA token. I haven't found a way to send this in postman, but in firefox this packet can be sent with a few authentication values that I've recorded in order to obtain a new CAPTCHA token. For the next request, we need the CAPTCHA Token. After that is retrieved, we may send the following request, with the token ###CAPTCHA### where the previously obtained CAPTCHA token should go, the token ###COID### where the correlationId field value should go from the previous server response, the token ###EMAIL### where the user email should go, and the token ###CODE### where the confirmation code from the email should go.

Verb: POST
Address: https://www.opentable.com/dapi/fe/proxy/authentication-consumer-backend/authentication/start-passwordless-login
Headers:
Origin: https://www.opentable.com
Referer: https://www.opentable.com/authenticate/verify-medium?isPopup=true&rp=https%3A%2F%2Fwww.opentable.com%2F&srs=1&isFromBookingFlow=false
x-csrf-token: c6f3e69c-23af-4e96-8cf5-372b7d66a0e1

Body:
{
    "email":"###EMAIL###",
    "correlationId":"###COID###",
    "verificationCode":"###CODE###",
    "loginContextToken":"{\"loginType\":\"popup-redirect\",\"requestedAction\":\"https://www.opentable.com/\"}",
    "recaptchaToken":"###CAPTCHA###",
    "tld":"com",
    "databaseRegion":"na",
    "checkExistingEmailEnabled":true
}

from resolved-bot.

21Bruce avatar 21Bruce commented on August 20, 2024

Just looked into the above, and it appears one does not even need to login to make a reservation on open table, so while the above info is useful, we do not need it.

from resolved-bot.

21Bruce avatar 21Bruce commented on August 20, 2024

It appears the sha256Hash field values are analagous to API Keys, but they work depending on the requested function. So logging in has its own sha256Hash key, searching has its own key, and reserving has its own key

from resolved-bot.

21Bruce avatar 21Bruce commented on August 20, 2024

Working on the search function right now, and managed to get through to the opentable servers on go. Please note, there's some funky behavior with how the opentable servers handle the user-agent header. You must include it, but it doesn't actually have to have anything in it, so feel free to set it to the empty string

from resolved-bot.

21Bruce avatar 21Bruce commented on August 20, 2024

Quick Note:
The following HTTP message can be used to find metadata in order to prepare a reservation. I use the token ###RID### to denote where the venueID should go, ###RESD### where the reservation day should go, ###REST### where the reservation time should go , ###PS### where the party size should go, and ###XTOK### where the x-csrf-token should go:

Verb: POST
Address: https://www.opentable.com/dapi/fe/gql?optype=query&opname=RestaurantsAvailability
Headers(on top of normal headers): 
x-csrf-token: ###XTOK###
Body:
{
    "operationName": "RestaurantsAvailability",
    "variables": {
        "onlyPop": false,
        "forwardDays": 0,
        "requireTimes": false,
        "requireTypes": [],
        "restaurantIds": [
            ###RID###
        ],
        "date": "###RESD###",
        "time": "###REST###",
        "partySize": ###PS###,
        "databaseRegion": "NA"
    },
    "extensions": {
        "persistedQuery": {
            "version": 1,
            "sha256Hash": "e6b87021ed6e865a7778aa39d35d09864c1be29c683c707602dd3de43c854d86"
        }
    }
}

This will trigger a response from the server with the following example body:

Body:
{
    "data": {
        "availability": [
            {
                "restaurantId": 1287013,
                "restaurantAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJzIjowLCJuIjowfQ",
                "availabilityDays": [
                    {
                        "noTimesReasons": [],
                        "earlyCutoff": null,
                        "sameDayCutoff": null,
                        "dayOffset": 0,
                        "allowNextAvailable": true,
                        "topExperience": null,
                        "slots": [
                            {
                                "isAvailable": true,
                                "timeOffsetMinutes": -60,
                                "slotHash": "3120410745",
                                "pointsType": "Standard",
                                "pointsValue": 100,
                                "experienceIds": [],
                                "slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
                                "attributes": [
                                    "highTop"
                                ],
                                "isMandatory": false,
                                "isMandatoryBySeating": [
                                    {
                                        "tableCategory": "highTop",
                                        "isMandatory": false,
                                        "__typename": "IsMandatoryBySeating"
                                    }
                                ],
                                "experiencesBySeating": [],
                                "redemptionTier": "GreatDeal",
                                "type": "Standard",
                                "__typename": "AvailableSlot"
                            },
                            {
                                "isAvailable": true,
                                "timeOffsetMinutes": -30,
                                "slotHash": "283703391",
                                "pointsType": "Standard",
                                "pointsValue": 100,
                                "experienceIds": [],
                                "slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
                                "attributes": [
                                    "highTop"
                                ],
                                "isMandatory": false,
                                "isMandatoryBySeating": [
                                    {
                                        "tableCategory": "highTop",
                                        "isMandatory": false,
                                        "__typename": "IsMandatoryBySeating"
                                    }
                                ],
                                "experiencesBySeating": [],
                                "redemptionTier": "GreatDeal",
                                "type": "Standard",
                                "__typename": "AvailableSlot"
                            },
                            {
                                "isAvailable": true,
                                "timeOffsetMinutes": 0,
                                "slotHash": "1620779529",
                                "pointsType": "Standard",
                                "pointsValue": 100,
                                "experienceIds": [],
                                "slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
                                "attributes": [
                                    "highTop"
                                ],
                                "isMandatory": false,
                                "isMandatoryBySeating": [
                                    {
                                        "tableCategory": "highTop",
                                        "isMandatory": false,
                                        "__typename": "IsMandatoryBySeating"
                                    }
                                ],
                                "experiencesBySeating": [],
                                "redemptionTier": "GreatDeal",
                                "type": "Standard",
                                "__typename": "AvailableSlot"
                            },
                            {
                                "isAvailable": true,
                                "timeOffsetMinutes": 15,
                                "slotHash": "335170686",
                                "pointsType": "Standard",
                                "pointsValue": 100,
                                "experienceIds": [],
                                "slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
                                "attributes": [
                                    "highTop"
                                ],
                                "isMandatory": false,
                                "isMandatoryBySeating": [
                                    {
                                        "tableCategory": "highTop",
                                        "isMandatory": false,
                                        "__typename": "IsMandatoryBySeating"
                                    }
                                ],
                                "experiencesBySeating": [],
                                "redemptionTier": "GreatDeal",
                                "type": "Standard",
                                "__typename": "AvailableSlot"
                            },
                            {
                                "isAvailable": true,
                                "timeOffsetMinutes": 30,
                                "slotHash": "142556990",
                                "pointsType": "Standard",
                                "pointsValue": 100,
                                "experienceIds": [],
                                "slotAvailabilityToken": "eyJ2IjoyLCJtIjowLCJwIjowLCJjIjo2LCJzIjowLCJuIjowfQ",
                                "attributes": [
                                    "highTop"
                                ],
                                "isMandatory": false,
                                "isMandatoryBySeating": [
                                    {
                                        "tableCategory": "highTop",
                                        "isMandatory": false,
                                        "__typename": "IsMandatoryBySeating"
                                    }
                                ],
                                "experiencesBySeating": [],
                                "redemptionTier": "GreatDeal",
                                "type": "Standard",
                                "__typename": "AvailableSlot"
                            }
                        ],
                        "__typename": "AvailabilityDay"
                    }
                ],
                "__typename": "RestaurantAvailability"
            }
        ]
    },
    "loading": false,
    "networkStatus": 7
}

Each entry in the "availabilityDays" data array represents metadata for a time slot, with the "timeOffsetMinutes" field value representing the difference between the time for that slot and the requested time, the "isAvailable" field value representing whether the slot is free, and the "slotHash" and "slotAvailabilityToken" being used to identify the slot in the next request for finalizing the reservation

from resolved-bot.

21Bruce avatar 21Bruce commented on August 20, 2024

Closed with recent PR

from resolved-bot.

Related Issues (14)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.