Sorry, you need to enable JavaScript to visit this website.

Web NFC and the Physical Web

BY Zoltan Kis ON Nov 12, 2015

Abstract

This article is a short walkthrough of Web NFC: what it is, why it is important, why it is in the proposed form, how it has evolved, and how it can be integrated with the Physical Web.

Introduction

The essence of the World Wide Web is fetching and presenting content on demand. Content navigation in past decades has been based on display and input devices such as keyboard, mouse, touchscreen, voice commands, etc. Users have been discovering web content using internet searches or using known web pages and URL links.

Now this is being extended through the Physical Web, an open project using small objects called URI beacons to broadcast URLs within a small radius defined by the carrier technology: Bluetooth* Low Energy (BLE) or WiFi networks using mDNS or uPnP/SSDP.

The URI beacons (image source) send URLs for shops, services, safety information, etc., in a compact form. The Physical Web application scans for these beacons and organizes the URLs and short textual presentations it receives into a live list, from which users can choose to open the interesting items.


Figure 1: Google Physical Web (Source)

NFC (image source) stands for Near Field Communications, a short-range wireless technology operating at 13.56 MHz, which enables communication between devices at distances of a few centimeters, usually less than 4 cm, and up to 20 cm. When you tap an NFC-capable device to an NFC tag or an NFC peer (an NFC-capable device), a data transfer will occur. The payload type is standardized by the NFC Forum in the form of an NDEF message consisting of NDEF records, which can contain URLs, text, binary data, or media consisting of image, sound, video, or other IANA media types, formerly MIME type. When the data transfer is complete, the receiving end dispatches the NDEF message to an application registered to handle NFC data.


Figure 2: NFC tags (Source 1, 2)

Web NFC (image source) is a simplified API for using NFC safely from regular web pages. Instead of providing a powerful low level API that requires special privileges--an approach that has previously failed in the W3C System Applications Work Group--Web NFC enables the use cases that are considered to be the most useful for web pages and that can be implemented by using the existing browser security model. Refer to the Security and privacy section. Supported record types include URL, text, JSON, media, and binary data. Media type records contain data described by a supplied IANA media type, meaning they can also be used to represent the other record types, which are included for convenience and backward compatibility with NFC record formats when pushing data.

Web NFC use cases

The basic use cases of Web NFC are the following: reading, writing, or updating a regular NFC tag or a Web NFC tag, and pushing data to NFC peers. More advanced use cases are card emulation, web payments, and connection handovers.

We can discuss one of the more complex use cases of NFC as an example of how to use the Web NFC API from web pages and how to integrate Web NFC with the Physical Web.

Imagine a shopping mall with a physical web of URI beacons installed. You can open your Physical Web application or touch an NFC tag at the information point to open a web page that shows a list of received URLs and short descriptions of the shops nearby. When you enter the shop and walk around, you can tap the tags installed on the shelves or products to open web pages on your device that show more information about the products, and you can add products to a virtual shopping basket. You can also share the shopping session and the basket with significant others by tapping their devices. When exiting the shop, you can pay by keeping the basket page in the foreground and tapping your device to the point of sales terminal, and then you will get the products delivered to your car, or home, or you might just take them along from a reception point.


Figure 3: Shop by tapping your device to NFC tags (Source 1, 2, 3, 4)

Security and privacy

Details about the trust model, threats, and security and privacy policies of Web NFC can be found in the Security and Privacy document and the corresponding section of the Web NFC specification, but a few key points are summarized here.

In principle, web pages using the Web NFC API are not trusted, and operations involving sharing user data need user consent. The permissions given to the web page define what private user data the web page has access to, such as location, contacts, media files, etc.

One of the requirements for Web NFC has been that web pages should be able to identify NFC tags meant for web pages, and that it would not be possible to mistake arbitrary NFC data for Web NFC data, both for tags and peers. Also, the policies need to be defined in a way in which web pages cannot do harm to NFC tags, NFC peers, or user data.

Identification of Web NFC data been achieved by adding a special record to Web NFC messages, in addition to normal NDEF records, which includes a URN with the value ”urn:nfc:ext:w3.org:webnfc”, defining a namespace for W3C Web NFC. The special record also contains a URL origin and an optional path which define the Web NFC identifier of the NDEF message. The origin can be used to apply same-origin or cross-origin policies, and the origin and path together can be used as a URL to match URL patterns defined in NFC watches.

In general, browsers try to minimize the number of user prompts. This can be achieved by applying appropriate design, security, and user prompting policies. The policies used in the Web NFC API implementations are the following:

  • Web pages using Web NFC must have a secure context.
  • Web pages using Web NFC must be in the foreground, meaning they are visible and in focus. Later versions of the specification may support service workers, and then this policy would change.
  • Web NFC allows reading data from any Web NFC tags or regular NFC tags without needing a user prompt.
  • Updating an NFC tag with the same origin as the writing web page does not trigger a user prompt.
  • However, writing a blank NFC tag from a web page or updating a tag with an origin different than that of the web page triggers a user prompt.
  • Pushing content to peers may involve an “ask for forgiveness” notification, but since the push requires a user gesture with the requesting web page in the foreground and with known permissions, a prompt is not strictly necessary. The current version of the specification does not require a user prompt to push content to NFC peers.

There may be implementations with a policy to decline Web NFC requests if they would trigger user prompts. Web pages will still be able to read NFC and Web NFC tags and update existing Web NFC tags that have the same origin.

Also, using hosted apps eliminates the need to trigger user prompts for Web NFC.

Implementation and discussion

The design choices of the Web NFC API are presented through specific aspects of the implementation of the use case above. This use case can be implemented using both the native NFC stack and the Web NFC API, but with different user experiences for each.

The use case assumes the physical store has a web store functionality, where each physical product found in the store also has a web page that displays information about the product, such as specifications, images, or reviews, with the possibility to add the product to a virtual shopping basket. In addition, users need to have an account on the web store that is used to manage the shopping session, including payment. The accounts can be previously configured permanent accounts, to which users need to sign in after manually opening the store’s web page, or they can be temporary accounts which are generated when the user first taps on a special tag installed at the entrance of the shop or when the user taps on any product-specific NFC tag installed in the store.

Regular NFC tags could also be used to implement this use case. They will likely contain URLs that are opened in a browser in a new tab on every tap. The shopping session will be the same for all tags in the shop since all the URLs will have the same origin, therefore a shopping session could be implemented with regular NFC tags as well.

However, using Web NFC tags has the following benefits:

  • The shopping session could be managed by a single web page (behavior controlled by the client), instead of a new tab opened for each product (behavior controlled by the device). For a similar user experience with regular NFC tags, a shop-specific application would need to be downloaded.
  • The Web NFC tags could be safely updated by the web store from the session web page using the customers’ or employees’ devices.
  • Shopping sessions are shared more easily with other devices.
  • During payment, the shopping basket could be identified by tapping the POS terminal (with future versions of the specification), whereas with regular NFC different provisioning is needed. For example, the web page would need to show a barcode or QR code to scan or present a human-readable identification string.

In summary, integrating NFC with web-based solutions is easier with the Web NFC API, and this also provides a better user experience. Besides, when integrated with the Physical Web, it enables a more efficient shop infrastructure, which is beneficial both for shop owners (less cost) and customers (reduced prices).

To continue, let us focus on how to implement the client side functionality using Web NFC.

Tag content

In this example, a Web NFC tag associated with a given product contains the product identifier, or product URL, and the origin and path of the web store to which the product belongs are the main information. When the user taps a product’s NFC tag, the user agent receives the data stored on the tag and can launch the product’s web page.

Watching NFC content

The web page that implements the shopping session from the use case above uses the navigator.nfc object to access NFC functionality. The first step is to install a watch to read tags belonging to the shop. An NFC watch basically consists of a filter and a callback that gets invoked every time a received NFC message matches the given filter. The filter can specify the type of tags (Web NFC tags or any tags), the type of records (URL, text, JSON, or binary), and the type of payloads (IANA media types) the application is interested in from specified URLs. In the example below the watch installs the callback for any text record coming from a URL that matches the URL pattern specified in the example. Web NFC tags are the only tags watched by default.

navigator.nfc.watch(
    // callback for handling read content
    (message) => {
          console.log(“NFC data read from: “ + message.url);
          message.data.forEach(processRecord);
    },
    // filters
    { 
         url: ‘https://myshop.com/products/*’,
         recordType: ‘text’
    })
.then(() => { console.log(“Watch added successfully.”); })
.catch((error) => { console.log(“Error adding watch: “ + error.message); });

The watch() method returns a Promise, used to handle the asynchronous operation of setting up the watch, consisting of the filters and the data processing callback method provided as argument. The Promise is rejected with an error if NFC functionality is not available or if an adapter is not found. Upon success it invokes the provided callback and passes the NFC content as the parameter every time a new read operation is made.

If there are multiple available NFC adapters (for instance, a built-in adapter and one connected via USB), any of them can be used to read or push, and as such, the watch is installed on all of them. The user can then choose which physical adapter to tap. Because of the small range of NFC communication, only one adapter will be able to complete the operation (or an error will result).

Processing received NFC content

In the web store example, the watch specifically listens to text content that represents a product identifier by design, and processing simply means opening a URL assembled from the store origin, path, and the product identifier:

    function processRecord(record) {
        window.open(record.url + “?id=” + record.data, “_self”);
    };

In a generic case, a web page that watches all supported content types may want to handle the different record types and payload data types:

function processRecord(record, index, array) {
  if (record.recordType == ‘url’) {
      console.log(“Data is URL: “ + record.data);
  } else if (record.recordType == ‘text’) {
      console.log(“Data is text: “ + record.data);
      console.log(“The media type: “ + record.mediaType);
  } else if (record.recordType == ‘json’) {
      var myobject = JSON.parse(record.data);
      // use the properties of ‘myobject’
  } else if (record.recordType == ‘opaque’) {
      // record.data is an ArrayBuffer, holding app specific format
      // use the data, based on IANA media type
      if (record.mediaType == ‘image/png’) {
          var img = document.createElement(“img”);
          img.src = URL.createObjectURL(new Blob(record.data, record.mediaType));
          img.onload = function() {
               window.URL.revokeObjectURL(this.src);
          };
          // ...
      }
  }
};

Updating tags

A script on a store’s web page might use Web NFC to update product tags when they are read by a customer. Since the origin of the store’s web page is the same as that on the product Web NFC tags, this does not trigger a user prompt, and can therefore be done transparently.

For this example let us assume the shop uses product tags that contain JSON data. First, install a watch to look for price tags.

       navigator.nfc.watch(
           updatePrice,  
           { url: ‘https://myshop.com/products/prices*’,  recordType: ‘json’ } 
       );

The push() method is used to send content to NFC tags or peers. When push() is invoked, an NDEF message is prepared and written the next time the user taps an NFC tag. A timeout value can be specified in milliseconds for how much time the user is allowed to make the tap gesture on an NFC tag. Any error condition results in rejection of the Promise. The push() method can take a simple parameter type, such as a string or an ArrayBuffer. However, if the developer wants to control or preserve the data layout on the NFC tag, like in the shop example above, then an NFCMessage structure is passed as an argument.

function updatePrice(message) {
    if (message.data[0].data.hasOwnProperty(“price”) {
        message.data[0].price = newPrice;
        navigator.nfc.push(message, { target: “tag”, timeout: 10000 })
           .then(() => { console.log(“Data prepared for pushing.”); })
           .catch((error) => { console.log(“Error pushing data.”); });
        }
    }
}

If the product tags were not restricted to contain JSON data, the push was not restricted to NFC tags, and if there was no timeout set, then a simpler invocation of push() could be used:

navigator.nfc.push(JSON.stringify(json));

Sharing by NFC push

NFC can also be used to share data between devices. When push() is used for NFC peers as a target, an NDEF message is prepared and written the next time the user taps an NFC peer. Any error condition results in rejection of the Promise. If the user taps a tag, nothing happens unless an earlier invocation of push() has set up a buffer to push data to tags.

The NFC message contains a URL path pushed together with the data, two records, a textual description, and the basket content as a JSON serialized object:

function shareBasket(basket, description) {
    var message = { 
        url: “/mypath/sharing/basket/”,
        data: [ 
            {
                recordType: “json”, 
                mediaType: “application/json”, 
                data: basket
            },
            {
                recordType: “text”,
                data: description
            }
        ]};

    navigator.nfc.push(message, { target: “peer” })
              .then(() => { console.log(“Basket has been shared”); })
              .catch((error) => { console.log(“Error pushing NFC data”); });
        }
    }
}

The example above uses the default value Infinity for the push timeout, meaning that no timer is started with the operation, and the operation is pending until the web page closes or until cancelPush() is invoked. However, the buffer is cleared after the push is resolved, and a new push requires another invocation of push().

Payments

When the user checks out in the use case above, a card compatible with the shop’s payment system needs to be emulated. For payment systems that use well known application identifiers, such as Visa and MasterCard, implementations could encapsulate the payment process, but specific browser extensions might be needed to support other application identifiers. Payments are not supported in the current version of the Web NFC specification.

Handovers: sharing

When large amounts of data is to be transferred, NFC can be used to configure the data transfer to happen over a technology with higher bandwidth, such as Bluetooth or Wi-Fi. Handover is not supported in the current version of the Web NFC specification.

Summary

Web NFC extends the Physical Web concept well and may even become part of it. Additionally, Web NFC can be used to enhance user experience based on NFC by reducing complexity and enabling fast integration with other web technologies.