GSoC 2016: Progress #3

My last week has been quite busy, but it all paid off in the end as I’ve managed to overcome the issue that I had with the login phase. Thankfully, I was able to take a look at how the postMessage() API is used to do the login in Firefox iOS and implement it myself in Epiphany.

To summarize it, this is how it’s done:

  1. Load the FxA iframe with the service=sync parameter in a WebKitWebView.
  2. Inject a few JavaScript lines to listen to FirefoxAccountsCommand events (sent by the FxA Server). This is done with a WebKitUserContentManager and a WebKitUserScript.
  3. In the event listener use postMessage() to send to back to WebKit the data received from the server.
  4. In the C code, register a script message handler with a callback that gets called whenever something is sent through the postMessage() channel. This is done with webkit_user_content_manager_register_script_message_handler().
  5. In the callback you now hold the server’s response to your request. This includes all the tokens you need to retrieve the sync keys.
  6. Profit!

Basically, postMessage() acts like a forwarder between JavaScript and WebKit. Cool!

With this new sign in method, users can also benefit of the possibility to create new Firefox accounts. The iframe contains a “Create an account” link that shows a form by which the users will create a new account. The user will have to verify the account before he signs in.

GSoC 2016: Progress #2

Unexpected things happen all the time and plans get damaged accordingly. That was my case too: since around July 1, the Firefox Accounts server started to block direct requests to the account/login endpoint. As you may assume, this was (and still is) a real impairment to my project’s progress.

I had nothing to do but to ask for answers on the Mozilla’s sync-dev mailing list: turns out the Firefox Accounts service is currently operating with tightened security rules due to an uptick in suspicious login attempts. Unfortunately, this also increases the likelihood of blocking legitimate login attempts, if they appear too similar to the suspicious traffic.

The guys at Mozilla suggested that I should change my approach and use the JavaScript postMessage() API in order to login, rather than the protocol I’m using now, since their intention is to deprecate this protocol for general public use in the near future. Therefore, my next step is to try to implement this new login method in Epiphany. This requires a good amount of documentation to determine whether it is feasible for Epiphany in the first place, therefore my project is getting delayed accordingly.

The login phase is a crucial part to the sync flow, since this is how you obtain the sessionToken and the keyFetchToken, used to further retrieve the sync keys that enable the client to encrypt/decrypt synchronized data records.

Since I’ve pretty much spent my time on mailing lists and digging through Firefox code, I wasn’t able to make a noticeable progress in the last week. However, I managed to achieve two things:

  • implement a shortcuts window for Epiphany (during the downtime of my actual project). Shortcuts windows were introduced in GNOME 3.20 and provide a way for the user to see all the keyboard shortcuts for an application with their corresponding actions. Many applications had their shortcuts window ready before the 3.20 release, but Epiphany was not one of them.
  • implement the Fetching Sync Keys act. This means to process the keyFetchToken – which is received once the user logs in – (I had to use a restmail email to test this, apparently requests from test emails don’t get blocked by the server), and derive the tokenID and reqHMACkey that will be further used in the request to the account/keys endpoint. The server then responds with a hex bundle that undergoes multiple cryptographic operations to obtain the sync keys. This phase also gave me the opportunity to rethink some portions of my code and provide a better transparency between the crypto module and the service module.

Until I find a way to make login work again, there is nothing much I can do to advance my project. Hopefully, I’ll figure out how to implement the alternate login method, so I can proceed to establish the communication with the storage server.