Secure Entry URL for Assisted Pickup

The Secure Entry URL is a url that partners embed in their order confirmation page which, when clicked, directs the user to Google Maps where they can register the order with the Google Assisted Pickup flow.

Requirements

Create a URL design that:

  • References a specific partner and pickup
  • Can be generated by the partner
  • Unguessable / Unscrapable
  • Is durable on the order of days/weeks
  • Allows Google to be able to confirm the validity of the URL before calling the partner to fetch the Pickup details.

To support these requirements, we use JWTs to sign the pickup info in the payload so that we can be confident the pickup ID came from the partner and is not a bad actor trying to scrape pickup details.

JWT

JSON Web Token (JWT) is an Internet standard for creating data with optional signature and/or optional encryption whose payload holds JSON that asserts some number of claims. The tokens are signed either using a private secret or a public/private key.

Using JWT, partners provide us the pickup ID in a JSON payload while signing the token so that Google can verify that the URL was created by the partner.

JWT Signing for Assisted Pickup

To pass data to Google in a Secure Entry URL, the partner will encode some of the pickup data in a signed JWT with the following parameters:

  1. Sign the token using an RS256 asymmetric key.
  2. The partner will share their public JSON Web Keyset (JWKS) with Google using the Reserve with Google Partner Portal. The key ID used for the current token can (optionally) be specified in the JWT header. If no key ID is specified, all keys will be tried.
  3. To add new keys or retire old keys, the partner will update the keyset in the Partner Portal.

Detailed Design

keyset

We use a standard JSON Web Key Set. We require an RS256 signing key.

Example:

{
  "keys": [
    {
      "kty": "RSA",
      "n": "t9wI5SWyglmdemnJ6IYONsprlRLxsAVqIl2QxyfcHnfCEr6p8Yp6tyi-okFlJF_hjQlXRrrznrL31VVCT4wWg7_gObjcxYmFsEJiXGx3UnzuEJm1y-5pUHuu00kNk-MBm8xu3ahH-V7IHsq_hvranqDw-1f5s7N-rp5oeAnAK8BDn43qN8Rq8ij0BcmgdEYYPcnFtcGZWTsKKZa_yShZWq8d2-WUXCyvR4mJnneeZ6GPybH5GZnrBrYjwekqUrbyiPMj0mQXjSrdOA7y3dkw9nvPW67hlECLeT2vsibNbFlWArLSnBu83WIbpGU20oZYoMjJIAkbOA6Wvx7rT-4PZw",
      "e": "AQAB",
      "alg": "RS256",
      "kid": "example_key_1",
      "use": "sig"
    }
  ]
}

A file with this data will need to be uploaded to the Reserve with Google Partner Portal. Additionally the "kid" parameter must be set such that it corresponds with the "kid" parameter in the JWT.

Token

We will use a standard JSON Web Token requiring the following fields (with example values below).

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "example_key_1"
}

Payload

{
  "partner_id": PARTNER_ID,
  "pickup_id": "abcde",
  "brand_id": "alternate_brand",  // optional
  "salt": "base64 encoded salt",  // optional
  "owh": one_way_hash_algorithm_id,  // optional
  "email": "base64 encoded hmac",  // optional
  "blob": "opaque blob of 200 bytes or less",  // optional
}
  • partner_id is a Google defined integer ID constant. Google will share with the partner once this value is defined. Required
  • pickup_id is the partner defined string ID for the associated pickup. See the Partner API Server Pickup Definition for more information. Required
  • brand_id is a string ID referencing a brand as defined in the Partner Portal. If not set, or if the provided brand_id doesn't exist, default brand (the brand with no ID set in Partner Portal) will be used. Optional
  • salt is a base64 encoded byte-string containing a per-JWT random salt. This field is required if email is present. If set, it should be generated using a secure random source.
  • owh contains the one-way-hash algorithm used to compute email. This field is required if email is present. It must match the allocated ID for a live one-way hash algorithm below, and should be set as an number (e.g.: 1; not "1").
  • email is a base64 encoded byte-string containing the HMAC of the email address associated with this pickup. The algorithm and credentials to generate the HMAC must be configured separately within the Partner Portal.

    This field is optional. If it is set, Google will verify that the logged-in Google account uses the same email. If it is unset, any user with the URL may add this pickup to their account.

  • blob is an opaque string field of 200 characters or less. It may be used to embed additional data within the JWT.

URL structure

There are three components of the URL:

  1. The JWT Token
  2. The "Inner URL" which includes the JWT Token as a parameter
  3. The "Outer URL" which wraps the Inner URL in a firebase link
JWT Token

The JWT Token should follow the detailed design above.

Inner URL:
https://www.google.com/maps/reserve/v/pickup?pickup=JWT_TOKEN

(This URL is supported by GMM on Android, iOS, and Google’s server.)

Outer URL

The Inner URL is wrapped in a Firebase Dynamic Link to ensure that mobile devices will open the relevant app store. The inner URL should be included as the link parameter in this outer URL.

https://maps.app.goo.gl/?link=INNER_URL&apn=com.google.android.apps.maps&amv=1062000000&ibi=com.google.Maps&isi=585027354&ius=comgooglemapsurl&imv=5.64
Full Example

An example of the full URL with JWT, Inner URL, and Outer URL will look like:

https://maps.app.goo.gl/?link=https%3A//www.google.com/maps/reserve/v/pickup%3Fpickup%3DeyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImV4YW1wbGVfa2V5XzEifQ.eyJwYXJ0bmVyX2lkIjoiUEFSVE5FUl9JRCIsInBpY2t1cF9pZCI6ImFiY2RlIiwicGxhY2VfaWQiOiJDaElKVDJlSDQ4NmdsVlFSOEdaWnNTcEYwdmMifQ.Uz2Daly2ObXTsThT6QvgajURtsluqjix3zIgHqegjbW4jQA5GVLD5yu5QbWM_bbjmU1kZlWTlKvinht9qpLIvWn33K1m8ulZP-PTKcXhxw688SL6XpMQycYVUr6YEG8AqIM2kmPvq92YZs0P59Ct-jeQrsNK6mKy1VVdwHelNHAy06WGIepLjSxjzx6elQSsUT4Tw9SHCG4SfVYmab-1UTqb5KDX-xGLZMJrKV4yc4VDufWpXcF1BAFN_MA1hOq91gTOEoBCLQiwQFRBnaZ4UOLUnmVHtPNAO2c69kVS4DhPhQLNP3plMdk2lfFJgiV0iUZsqJdyz8krv_ZIVampM24JOtj8LBdUNK6LrZdDyz4N-R0OMitmfxt1bQ84WsGcq0Y6n_LbmCpODuGyDod3fXkHIUn2RNmVIW2zlgtRBcLdP76uIpJCZXVnx9LUVRgJ1Ll7fNLbenAWGTXwuqybbjeI2NkPU1KrUEe46p8MScoTB5pCXqkizjys3gNhuPlRn0z_0n0-ttio9NpRjQmbF-m94KThuIwNGbJ41cUCJwyIbvbWzaJ3KKDpWE3kTkG_qASFW81FigMNiQ6G7sIq0WifrcNRdf0efmS-vAPjCkTD9rzmLs6AoGqtquh5kZhU0NO8q7Wd_t0jzojlvPzm9l1nGKW-vrkr73ke3bTqgxw&apn=com.google.android.apps.maps&amv=1062000000&ibi=com.google.Maps&isi=585027354&ius=comgooglemapsurl&imv=5.64

Security note

JWTs allow Google to validate that a URL was genuinely generated by the partner and not a bad actor trying to scrape pickup data. It does not provide a guarantee that the person accessing this link is the same person who placed the order. Anyone in possession of this link will be able to add the associated pickup to their Google account.

One-way hash algorithms

HMAC_SHA_2_256_TRUNC_160

To generate one-way hashes for this algorithm...

  1. Obtain the data to hash
  2. Generate a new random salt of 120 bits or more. A secure random generator should be used
  3. Generate the full hash using data and the salt as the HMAC key using HMAC-SHA-2-256
  4. Truncate the hash, keeping the left 160 bits to generate hash
  5. Base64 encode the hash

JWTs which use this one-way hash must set payload field owh to 1 (note: not "1").