Validating Open Badges

During the Foundation All-hands last week I had the opportunity to work with Brian Brennan, who is the technical lead on Mozilla’s Open Badges project. One of the problems that interested me during the work week was validating open badges.

First off, lets see a real badge:

Why, it looks just like a normal PNG! And it is! The thing that makes a PNG a badge is metadata stored within the PNG.

A PNG is not just image data; it’s composed of multiple ‘chunks’ which specify different kinds of data: image, transparency, colour space, text, time, and other miscellaneous data. The chunk structure is actually pretty understandable:

Currently, the Open Badges spec specifies that the metadata be stored in a ‘tEXt’ chunk, which looks like this:

Each tEXt chunk contains a keyword and a text string, in the format:

Keyword 1-79 bytes (character string)
Null separator 1 byte (null character)
Text string 0 or more bytes (character string)

The keyword and text string are separated by a zero byte (null character). Neither the keyword nor the text string may contain a null character. The text string is not null-terminated (the length of the chunk defines the ending). The text string may be of any length from zero bytes up to the maximum permissible chunk size less the length of the keyword and null character separator.

The keyword indicates the type of information represented by the text string as described in 11.3.4.2: Keywords and text strings.

Text is interpreted according to the Latin-1 character set [ISO-8859-1]. The text string may contain any Latin-1 character. Newlines in the text string should be represented by a single linefeed character (decimal 10). Characters other than those defined in Latin-1 plus the linefeed character have no defined meaning in tEXt chunks. Text containing characters outside the repertoire of ISO/IEC 8859-1 should be encoded using the iTXt chunk.

This doesn’t look too difficult to work with. Now we just need to get access to the metadata somehow. But how are we going to do that? The browser doesn’t allow access to PNG metadata through the <img> element, and I certainly don’t want to write a PNG parser from scratch in JavaScript. Fortunately for me, Devon Govett did! PNG.js is a PNG decoder written in JS for the <canvas> element without using a DOM Image. I was easily able to add support for the ‘tEXt’ chunk, and found that the sample badge used ‘openbadges’ as the keyword for storing the validation URL.

The last step in the puzzle was retrieving the JSON data located at the validation URL. Unfortunately, that’s a cross-domain request:

Fortunately, the Open Badges server is being built in the open, and I was easily able to enable CORS on the server by submitting a pull request.

With all that done, I built a demo that showed off in-browser verification of badges. I’d love to see the badge spec continue to evolve, and become even more robust. The next step is signing badges is going to ensure that they can’t be tampered with. It should be interesting to verify that inside the browser. It’d also be good to switch to the ‘iTXt’ PNG chunk, which is designed to hold international text, such as URLs.

This entry was posted in Open Source. Bookmark the permalink.

One Response to Validating Open Badges

  1. Pingback: Digital Media and Learning Competition

Comments are closed.