Commit b017a5bc authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #279 from hypothesis/reorganise-docs

Reorganise docs
parents d28669cc bd33075d
build/ build/
node_modules/ node_modules/
coverage/ coverage/
docs/_build/
...@@ -19,6 +19,10 @@ test: node_modules/.uptodate ...@@ -19,6 +19,10 @@ test: node_modules/.uptodate
lint: node_modules/.uptodate lint: node_modules/.uptodate
npm run lint npm run lint
.PHONY: docs
docs:
cd docs && make livehtml
################################################################################ ################################################################################
build/manifest.json: node_modules/.uptodate build/manifest.json: node_modules/.uptodate
......
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = HypothesisClient
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
livehtml:
sphinx-autobuild -b dirhtml -p 8888 "$(SOURCEDIR)" "$(BUILDDIR)/dirhtml" $(SPHINXOPTS) $(O)
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
../../images/screenshot.png
\ No newline at end of file
# -*- coding: utf-8 -*-
#
# Hypothesis Client documentation build configuration file, created by
# sphinx-quickstart on Thu Mar 9 18:01:59 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
# import sys
from recommonmark.parser import CommonMarkParser
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# sys.path.insert(0, os.path.abspath('.'))
# on_rtd is whether the docs are being built on readthedocs.org (or whether
# someone is building them locally), this line of code grabbed from
# docs.readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.todo', 'sphinx.ext.intersphinx']
intersphinx_mapping = {'h': ('https://h.readthedocs.io/en/latest/', None)}
# Add any paths that contain tempates here, relative to this directory.
templates_path = ['_templates']
source_parsers = {
'.md': CommonMarkParser, # Add Markdown support to Sphinx.
}
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ['.rst', '.md']
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Hypothesis Client'
copyright = u'2017, Hypothesis Project Contributors'
author = u'Hypothesis Project Contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'1.0.0'
# The full version, including alpha/beta/rc tags.
release = u'1.0.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
numfig = True
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
'display_version': False,
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'HypothesisClientdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'HypothesisClient.tex', u'Hypothesis Client Documentation',
u'Hypothesis Project Contributors', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'hypothesisclient', u'Hypothesis Client Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'HypothesisClient', u'Hypothesis Client Documentation',
author, 'HypothesisClient', 'One line description of project.',
'Miscellaneous'),
]
Configuring the client
======================
### Configuring the client using JSON
The Hypothesis client can be configured by providing a JSON config object in
the body of the hosting page:
```html
<script type="application/json" class="js-hypothesis-config">
{
"openSidebar": true
}
</script>
<script async src="https://hypothes.is/embed.js"></script>
```
Not all configuration settings can be set in this way, some must be
[set using JavaScript](#configuring-the-client-using-javascript) (see below).
**N.B.** The body of the `.js-hypothesis-config` tag must be [valid
JSON](http://jsonlint.com/) -- invalid JSON will cause the entire config object
to be ignored.
### Configuring the client using JavaScript
Alternatively, the Hypothesis client can be configured from the hosting page by
providing a JavaScript function named `window.hypothesisConfig` that returns
a configuration object. Some configuration settings (for example settings that
register callback or event handler functions) can _only_ be set from
JavaScript:
```html
window.hypothesisConfig = function () {
return {
"openSidebar": true
};
};
```
Config settings
---------------
### Client behavior
These settings configure the behavior and initial state of the client when it
loads.
#### `openLoginForm`
_Boolean_. Controls whether the login panel is automatically opened on startup,
as if the user had clicked "Log in" themselves. (Default: _false_.)
#### `openSidebar`
_Boolean_. Controls whether the sidebar opens automatically on startup.
(Default: _false_.)
#### `showHighlights`
_Boolean_. Controls whether the in-document highlights are shown by default.
(Default: _true_.)
### Annotation services
The `services` setting configures which annotation services the client
connects to (for example to login, retrieve annotations, and save annotations).
By default, if no `services` setting is given, the client connects to the
public Hypothesis service at [hypothes.is](https://hypothes.is).
#### `services`
_Array_. A list of alternative annotation services which the client should
connect to instead of connecting the the public Hypothesis service at
[hypothes.is](https://hypothes.is/).
May optionally include information (in the form of a grant token) about the
identity of the user accounts that the client is logged in to on those
services.
**N.B.** These settings are currently still experimental and may change without
warning.
**N.B.** Currently only one alternative annotation service at a time is
supported - only the first item in this `services` array is used, and any
further items in the array are ignored.
Each item in the `services` array should be an object describing an annotation
service, with the following keys:
* `authority` _String_. The domain name which the annotation service is
associated with.
* `grantToken` _String|null_. An OAuth 2 grant token which the client can
exchange for an access token in order to make authenticated requests to the
service. If _null_, the user will be able to read but not create or modify
annotations. (Default: _null_)
* `icon` _String|null_. The URL to an image for the annotation service. This
image will appear to the left of the name of the currently selected group.
The image should be suitable for display at 16x16px and the recommended
format is SVG.
* `onLoginRequest` _function_. A JavaScript function that the client will
call in order to login (for example, when the user clicks a login button in
the Hypothesis client's sidebar).
This setting can only be [set using window.hypothesisConfig](#configuring-the-client-using-javascript).
If the hosting page provides an `onLoginRequest` function then the Hypothesis
client will call this function instead of doing its usual procedure for
logging in to the public service at [hypothes.is](https://hypothes.is/).
No arguments are passed to the `onLoginRequest` function.
The `onLoginRequest` function should cause a login procedure for the hosting page
to be performed - for example by redirecting to a login page, or by opening
a popup login window. After a successful login the hosting page should
reload the original page with a non-null `grantToken` for the logged-in user
in the `services` configuration setting.
### Asset and sidebar app location
These settings configure where the client's assets are loaded from.
**N.B.** These settings are currently still experimental and may change without
warning.
#### `assetRoot`
_String_. The root URL from which assets are loaded. This should be set to the
URL where the contents of the `hypothesis` package are hosted, including the
trailing slash. (Default: For production builds:
_https://cdn.hypothes.is/hypothesis/X.Y.Z/_, for development builds:
_http://localhost:3001/hypothesis/X.Y.Z/_. _X.Y.Z_ is the package version from
`package.json`)
#### `sidebarAppUrl`
_String_. The URL for the sidebar application which displays annotations
(Default: _https://hypothes.is/app.html_ . If the `H_SERVICE_URL` env var is
set, defaults to `${H_SERVICE_URL}/app.html`)
# Developing the client Developing the Client
=====================
Hypothesis is comprised of several components: This section documents how to setup a development environment for the client,
how to run the client and its tests in a development environment,
client coding standards and how to contribute code to the client.
- A browser-based web app for annotating web pages (this repository) Setting up a Client Development Environment
- A service which stores annotations, user accounts and other data. By default -------------------------------------------
the client uses the public service at [hypothes.is](https://hypothes.is).
- A browser extension which can add the client to web pages.
## Prerequisites Prerequisites
#############
You will need: You will need:
* [git](https://git-scm.com/) * `git <https://git-scm.com/>`_
* [Node.js](https://nodejs.org/en/) v6+ * `Node.js <https://nodejs.org/en/>`_ v6+
## Building Building
########
To build the client for development: To build the client for development:
```sh .. code-block:: sh
git clone 'https://github.com/hypothesis/client.git'
cd client git clone 'https://github.com/hypothesis/client.git'
npm install -g gulp-cli # Tip: if you get a "permission denied" error try cd client
# `sudo npm install -g gulp-cli` instead. npm install -g gulp-cli # Tip: if you get a "permission denied" error try
make # `sudo npm install -g gulp-cli` instead.
``` make
You now have a development client built. To run your development client in You now have a development client built. To run your development client in
a browser you'll need a local copy of either the Hypothesis Chrome extension or a browser you'll need a local copy of either the Hypothesis Chrome extension or
the Hypothesis web service. Follow either the instructions for the Hypothesis web service. Follow either
[Running the client from the browser extension](#running-the-client-from-the-browser-extension) :ref:`running-from-browser-ext` or :ref:`running-from-web-service` below.
or for
[Running the client from the web service](#running-the-client-from-the-web-service)
below.
If you're only interested in making changes to the client (and not to the web If you're only interested in making changes to the client (and not to the web
service) then running the client from the browser extension is easiest. service) then running the client from the browser extension is easiest.
## Running the client from the browser extension
.. _running-from-browser-ext:
Running the Client from the Browser Extension
---------------------------------------------
This is the currently easiest way to get your development client running in a This is the currently easiest way to get your development client running in a
browser. It sets you up to make changes to the client and to the Chrome browser. It sets you up to make changes to the client and to the Chrome
extension itself, but not to the web service. extension itself, but not to the web service.
1. Check out the [browser #. Check out the
extension](https://github.com/hypothesis/browser-extension) and follow the `browser extension <https://github.com/hypothesis/browser-extension>`_
steps in the and follow the steps in the browser extension's documentation to build the
[README](https://github.com/hypothesis/browser-extension/blob/master/README.md) extension and configure it to use your local version of the client and the
to make it use your local version of the client and the [production production Hypothesis service.
Hypothesis
service](https://github.com/hypothesis/browser-extension/blob/master/docs/building.md).
1. Start the client's development server to rebuild the client whenever it #. Start the client's development server to rebuild the client whenever it
changes: changes:
``` .. code-block:: sh
gulp watch
```
1. After making changes to the client, you will need to run `make` in the gulp watch
#. After making changes to the client, you will need to run ``make`` in the
browser extension repo and reload the extension in Chrome to see changes. browser extension repo and reload the extension in Chrome to see changes.
You can use [Extensions You can use
Reloader](https://chrome.google.com/webstore/detail/extensions-reloader/fimgfedafeadlieiabdeeaodndnlbhid?hl=en) `Extensions Reloader <https://chrome.google.com/webstore/detail/extensions-reloader/fimgfedafeadlieiabdeeaodndnlbhid?hl=en>`_
to make this easier. to make this easier.
## Running the client from the web service .. _running-from-web-service:
Running the Client From the Web Service
---------------------------------------
This takes longer to setup than This takes longer to setup than :ref:`running-from-browser-ext`.
[Running the client from the browser extension](#running-the-client-from-the-browser-extension).
You should follow these steps if you want to make changes to the Hypothesis You should follow these steps if you want to make changes to the Hypothesis
web service as well as to the client. web service as well as to the client.
First follow the [instructions for setting up a development install of the web First follow the
service](http://h.readthedocs.io/en/latest/developing/). `instructions for setting up a development install of the web service <http://h.readthedocs.io/en/latest/developing/>`_.
Once you have a development install of the Hypothesis service set up, you can Once you have a development install of the Hypothesis service set up, you can
configure it to use a local build of the client. **In the client repository**, configure it to use a local build of the client. **In the client repository**,
run: run:
```sh .. code-block:: sh
export H_SERVICE_URL=http://localhost:5000
gulp watch
```
The `H_SERVICE_URL` env var sets the URL of the service which hosts the HTML export H_SERVICE_URL=http://localhost:5000
entry point for the client's sidebar application. gulp watch
**In the `hypothesis/h` repository**, set the `CLIENT_URL` env var to tell the **In the `hypothesis/h` repository**, set the :envvar:`CLIENT_URL` env var to
service where to load the client from, before running `make dev`: tell the service where to load the client from, before running ``make dev``:
```sh .. code-block:: sh
export CLIENT_URL=http://localhost:3001/hypothesis
make dev export CLIENT_URL=http://localhost:3001/hypothesis
``` make dev
Once the client and service are running, you can test it out by visiting: Once the client and service are running, you can test it out by visiting:
[http://localhost:3000](http://localhost:3000) or [the Help http://localhost:3000 or http://localhost:5000/docs/help in your browser.
page](http://localhost:5000/docs/help) in your browser.
You can also load the client into your own web pages by adding: You can also load the client into your own web pages by adding:
```html .. code-block:: html
<script async src="http://localhost:5000/embed.js"></script>
``` <script async src="http://localhost:5000/embed.js"></script>
to the page's HTML. Note that this will only work in pages served via plain to the page's HTML. Note that this will only work in pages served via plain
HTTP. If you want to test out the client on pages served via HTTPS then building HTTP. If you want to test out the client on pages served via HTTPS then building
the client into a browser extension is the easiest option. the client into a browser extension is the easiest option.
## Running tests Running the Tests
-----------------
Hypothesis uses Karma and mocha for testing. To run all the tests once, run: Hypothesis uses Karma and mocha for testing. To run all the tests once, run:
```sh .. code-block:: sh
gulp test
``` gulp test
To run tests and automatically re-run them whenever any source files change, run: To run tests and automatically re-run them whenever any source files change, run:
```sh .. code-block:: sh
gulp test-watch
```
You can filter the tests which are run by passing `--grep <pattern>` as an gulp test-watch
argument to `gulp test`. See the documentation for Mocha's
[grep](https://mochajs.org/#g---grep-pattern) option.
You can filter the tests which are run by passing ``--grep <pattern>`` as an
argument to ``gulp test``. See the documentation for Mocha's
`grep <https://mochajs.org/#g---grep-pattern>`_ option.
## Code style Code Style
----------
### JavaScript JavaScript
##########
Hypothesis uses ESLint to help maintain style consistency. You can check your Hypothesis uses ESLint to help maintain style consistency. You can check your
changes for conformance using: changes for conformance using:
``` .. code-block:: sh
make lint
``` make lint
Many lint errors can be fixed automatically using: Many lint errors can be fixed automatically using:
``` .. code-block:: sh
./node_modules/.bin/eslint --fix
``` ./node_modules/.bin/eslint --fix
### CSS CSS
###
Styling is authored in SASS. For guidance on writing CSS for Hypothesis Styling is authored in SASS. For guidance on writing CSS for Hypothesis
projects, please see our [CSS projects, please see our
Guide](https://github.com/hypothesis/frontend-toolkit/blob/master/docs/css-style-guide.md). `CSS Guide <https://github.com/hypothesis/frontend-toolkit/blob/master/docs/css-style-guide.md>`_.
## Submitting pull requests Submitting Pull Requests
------------------------
For general guidance on submitting pull requests to Hypothesis projects, please For general guidance on submitting pull requests to Hypothesis projects, please
see the [Contributor's Guide](https://h.readthedocs.io/en/latest/developing/). see the `Contributor's Guide <https://h.readthedocs.io/en/latest/developing/>`_.
Environment Variables
=====================
This section documents all the environment variables supported by the client's
build tasks.
.. envvar:: H_SERVICE_URL
The URL of the service which hosts the HTML entry point for the client's
sidebar application.
For Developers
==============
This section contains documentation for **developers** contributing code to
the Hypothesis client.
.. toctree::
:maxdepth: 3
developing
security
envvars
# Client security Client Security
===============
This document is intended to give an overview of the security considerations This document is intended to give an overview of the security considerations
which must be kept in mind when working on the Hypothesis client. It outlines which must be kept in mind when working on the Hypothesis client. It outlines
...@@ -6,51 +7,42 @@ the overall security goals for the client, names some risks and attack vectors, ...@@ -6,51 +7,42 @@ the overall security goals for the client, names some risks and attack vectors,
and identifies ways in which code in the client attempts to mitigate those and identifies ways in which code in the client attempts to mitigate those
risks. risks.
### Table of Contents .. environment-overview:
- [Environment overview](#environment-overview) Environment Overview
- [Threat model](#threat-model) --------------------
- [Potential attack vectors](#potential-attack-vectors)
- [Design considerations and defenses](#design-considerations-and-defenses)
- [Same-origin policy protections](#same-origin-policy-protections)
- [Input sanitisation](#input-sanitisation)
- [Transport Layer Security](#transport-layer-security)
- [Clickjacking protections](#clickjacking-protections)
- [Phishing/imitation](#phishingimitation)
The Hypothesis client is a
## Environment overview `single-page web application <https://en.wikipedia.org/wiki/Single-page_application>`_
which runs in a browser. Typically, it interacts with some annotated content
The Hypothesis client is a [single-page web (the page on which annotations are made) and an annotation service running on a
application](https://en.wikipedia.org/wiki/Single-page_application) which runs remote server.
in a browser. Typically, it interacts with some annotated content (the page on
which annotations are made) and an annotation service running on a remote
server.
At different times, users interact directly with the client, with the annotated At different times, users interact directly with the client, with the annotated
content, and with the annotation service. Data can flow in both directions: from content, and with the annotation service. Data can flow in both directions: from
the annotated content to the client and vice versa. Communication with the the annotated content to the client and vice versa. Communication with the
annotation service is also bidirectional, making use of an HTTP API and a annotation service is also bidirectional, making use of an HTTP API and a
WebSocket connection. WebSocket connection:
.─. .. code::
( )
.─`─'─. .─.
; User : ( )
┌─────: ;──────┬────────────────────┐ .─`─'─.
│ \ / │ │ ; User :
│ `───' │ │ ┌─────: ;──────┬────────────────────┐
│ │ │ │ \ / │ │
v v v │ `───' │ │
┌────────────┐ * ╔════════════╗ ┌────────────┐ │ │ │
│ │ * ║ ║ │ │ v v v
│ │ * ║ ║ HTTP │ │ ┌────────────┐ * ╔════════════╗ ┌────────────┐
│ Annotated │──────>║ Client ║──────>│ Annotation │ │ │ * ║ ║ │ │
│ content │<──────║ ║<──────│ service │ │ │ * ║ ║ HTTP │ │
│ │ * ║ ║ WS │ │ │ Annotated │──────>║ Client ║──────>│ Annotation │
│ │ * ║ ║ │ │ │ content │<──────║ ║<──────│ service │
└────────────┘ * ╚════════════╝ └────────────┘ │ │ * ║ ║ WS │ │
*Figure 1: Hypothesis client environment* │ │ * ║ ║ │ │
└────────────┘ * ╚════════════╝ └────────────┘
There are two important trust boundaries in this system: There are two important trust boundaries in this system:
...@@ -58,10 +50,11 @@ There are two important trust boundaries in this system: ...@@ -58,10 +50,11 @@ There are two important trust boundaries in this system:
on a remote server. on a remote server.
2. Between the annotated content (which may be an HTML page or a PDF rendered as 2. Between the annotated content (which may be an HTML page or a PDF rendered as
an HTML page) and the client application. This boundary is marked with an HTML page) and the client application. This boundary is marked with
asterisks (\*) in Figure 1. asterisks (``*``) in the ASCII art above.
## Threat model Threat Model
------------
We are principally interested in ensuring that untrusted parties cannot gain We are principally interested in ensuring that untrusted parties cannot gain
access to data that is intended to be confidential, or tamper with such data access to data that is intended to be confidential, or tamper with such data
...@@ -92,108 +85,127 @@ and all of the following: ...@@ -92,108 +85,127 @@ and all of the following:
- members of the public who don't use the annotation service - members of the public who don't use the annotation service
- active attackers - active attackers
We aim to defend confidential user data against any possibility of unauthorised access. We aim to defend confidential user data against any possibility of unauthorised
access.
## Potential attack vectors Potential Attack Vectors
------------------------
The mechanisms of directed attack we are aiming to defend against are common to The mechanisms of directed attack we are aiming to defend against are common to
many web applications, namely: many web applications, namely:
- execution of untrusted code in a trusted context (principally by - execution of untrusted code in a trusted context (principally by
[XSS](https://en.wikipedia.org/wiki/Cross-site_scripting)) `XSS <https://en.wikipedia.org/wiki/Cross-site_scripting>`_)
- [clickjacking](https://en.wikipedia.org/wiki/Clickjacking) - `clickjacking <https://en.wikipedia.org/wiki/Clickjacking>`_
- phishing/imitation attacks - phishing/imitation attacks
- eavesdropping of unencrypted network traffic by an untrusted party - eavesdropping of unencrypted network traffic by an untrusted party
- to a limited extent, [cross-site request - to a limited extent,
forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery), although `cross-site request forgery <https://en.wikipedia.org/wiki/Cross-site_request_forgery>`_,
this is mostly a concern for the annotation service although this is mostly a concern for the annotation service
Design Considerations and Defenses
----------------------------------
## Design considerations and defenses Same-Origin Policy Protections
##############################
### Same-origin policy protections
The starting point for understanding many of the client-side security mechanisms The starting point for understanding many of the client-side security mechanisms
is the web platform's [same-origin is the web platform's
policy](https://en.wikipedia.org/wiki/Same-origin_policy) (SOP), which ensures `same-origin policy <https://en.wikipedia.org/wiki/Same-origin_policy>`_ (SOP),
that any document on origin[^1] "A" has very limited access to the execution which ensures that any document on origin [#f1]_ "A" has very limited access to
context or DOM tree of any document on a different origin "B". the execution context or DOM tree of any document on a different origin "B".
.. _security-sop:
[^1]: An origin is the tuple of (scheme, host, port) for a given web document. .. figure:: security-sop.png
![](security-sop.png) Distinct origins for annotated content and client application
*Figure 2: Distinct origins for annotated content and client application*
As shown in Figure 2, the bulk of the Hypothesis client application executes As shown in :numref:`security-sop`, the bulk of the Hypothesis client application
within an `<iframe>` injected into the annotated content. This `<iframe>` has an executes within an ``<iframe>`` injected into the annotated content. This
origin distinct from that of the hosting page, which means that most of the ``<iframe>`` has an origin distinct from that of the hosting page, which means
protections of the SOP apply. Most importantly, code executing in the context of that most of the protections of the SOP apply. Most importantly, code executing
the annotated page cannot inspect the DOM of the client frame. The red border in in the context of the annotated page cannot inspect the DOM of the client
the image is a visual representation of the trust boundary between the frame. The red border in the image is a visual representation of the trust
inherently untrusted execution context of the annotated page, and the trusted boundary between the inherently untrusted execution context of the annotated
execution context of the client frame. page, and the trusted execution context of the client frame.
Instead, the components of the client which execute in the annotated page must Instead, the components of the client which execute in the annotated page must
communicate with the client frame using [cross-document communicate with the client frame using
messaging](https://en.wikipedia.org/wiki/Web_Messaging). It is important that `cross-document messaging <https://en.wikipedia.org/wiki/Web_Messaging>`_.
such **cross-document messaging should expose only the minimum information It is important that such **cross-document messaging should expose only the
necessary about user data** to code executing in the annotated page. For minimum information necessary about user data** to code executing in the
example: in order to draw highlights, the annotated page needs to know the annotated page. For example: in order to draw highlights, the annotated page
location of annotations, but it does not ever need to know the body text of an needs to know the location of annotations, but it does not ever need to know
an annotation, and so it should not be possible to expose this over the the body text of an an annotation, and so it should not be possible to expose
messaging interface. this over the messaging interface.
_TODO 2017-03-08: currently the client shares an origin with the annotation .. todo:: 2017-03-08
service when delivered by any mechanism other than the Chrome extension. This
makes any XSS vulnerability in the client a problem for the service and vice Currently the client shares an origin with the annotation service when
versa. We need to move the client to its own origin to better isolate the client delivered by any mechanism other than the Chrome extension. This makes any
from the service and minimise the risk posed by XSS._ XSS vulnerability in the client a problem for the service and vice versa. We
need to move the client to its own origin to better isolate the client from
### Input sanitisation the service and minimise the risk posed by XSS.
Input Sanitization
##################
As alluded to above, the client frame is a trusted execution context. Any code As alluded to above, the client frame is a trusted execution context. Any code
running there has full access to everything the user has access to, which may running there has full access to everything the user has access to, which may
constitute a major security flaw if that code was provided by another user (say, constitute a major security flaw if that code was provided by another user (say,
as a `<script>` tag in the body of an annotation). as a ``<script>`` tag in the body of an annotation).
This is an example of a cross-site scripting attack (XSS) and must be mediated This is an example of a cross-site scripting attack (XSS) and must be mediated
by ensuring that **any and all user content displayed in the client frame is by ensuring that **any and all user content displayed in the client frame is
appropriately escaped and/or sanitised**. appropriately escaped and/or sanitised**.
### Transport Layer Security Transport Layer Security
########################
We ensure that it is hard to eavesdrop on traffic between the client and the We ensure that it is hard to eavesdrop on traffic between the client and the
annotation service by communicating with the annotation service over encrypted annotation service by communicating with the annotation service over encrypted
channels (`https://` and `wss://`). channels (``https://`` and ``wss://``).
_TODO 2017-03-08: This is not currently enforced by the client. Perhaps .. todo:: 2017-03-08
production builds of the client should refuse to communicate with annotation
services over insecure channels?_
### Clickjacking protections This is not currently enforced by the client. Perhaps production builds of
the client should refuse to communicate with annotation services over
insecure channels?
Clickjacking Protections
########################
The most straightforward way to protect an application from most kinds of The most straightforward way to protect an application from most kinds of
clickjacking is the [`frame-ancestors` Content-Security-Policy clickjacking is the
directive](https://w3c.github.io/webappsec-csp/#directive-frame-ancestors) or `frame-ancestors Content-Security-Policy directive <https://w3c.github.io/webappsec-csp/#directive-frame-ancestors>`_
the older [`X-Frame-Options` HTTP or the older
Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options). `X-Frame-Options HTTP Header <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options>`_.
Unfortunately, the client runs in a framed context (and on arbitrary origins) by Unfortunately, the client runs in a framed context (and on arbitrary origins) by
default, so simply applying `X-Frame-Options: DENY` would break the client default, so simply applying ``X-Frame-Options: DENY`` would break the client
entirely. entirely.
_TODO 2017-03-08: The Hypothesis client would appear to have very little .. todo:: 2017-03-08
protection against clickjacking attacks that allow arbitrary websites to trick
Hypothesis users into performing actions they did not intend to perform. It's The Hypothesis client would appear to have very little protection against
not immediately clear what tools we have at our disposal to solve this problem._ clickjacking attacks that allow arbitrary websites to trick Hypothesis users
into performing actions they did not intend to perform. It's not immediately
clear what tools we have at our disposal to solve this problem.
### Phishing/imitation Phishing/Imitation
##################
At the moment there is little that would stop a website embedding a replica of At the moment there is little that would stop a website embedding a replica of
the Hypothesis client in a frame and using it to harvest Hypothesis users' the Hypothesis client in a frame and using it to harvest Hypothesis users'
usernames and passwords. usernames and passwords.
_TODO 2017-03-08: Direct credential input must move to a first-party interaction .. todo:: 2017-03-08
(i.e. a popup window) where the user has the benefit of the browser toolbar to
help them identify phishing attacks._ Direct credential input must move to a first-party interaction (i.e. a popup
window) where the user has the benefit of the browser toolbar to help them
identify phishing attacks.
.. rubric:: Footnotes
.. [#f1] An origin is the tuple of (scheme, host, port) for a given web document.
Building the Docs Locally
=========================
You will need:
#. Git
#. Python and Virtualenv
#. Make
To build the docs:
#. ``git clone https://github.com/hypothesis/client.git``
#. ``cd client``
#. Create and activate a Python virtual environment.
#. ``pip install -r requirements-dev.in``
#. ``make docs``
Now open http://localhost:8888 to view your local build of the docs.
The built docs will automatically update when you save changes to the source
files.
For Documenters
===============
This section contains documentation for **documenters** who want to contribute
documentation to the Hypothesis client.
.. toctree::
:maxdepth: 3
buildthedocs
# Interacting with the sidebar
## Show the sidebar:
If you need to have a custom trigger on your third party page to bring up the embedded Hypothesis
sidebar, add the `data-hypothesis-trigger` attribute to the element that you want to enable.
Clicking that element will cause the sidebar to open.
Note, however, subsequent clicks do not hide the sidebar.
Example:
To add a `button` on a page to open the sidebar, simply
add the `data-hypothesis-trigger` attribute.
```html
<button data-hypothesis-trigger>
Open sidebar
</button>
```
## Show the public annotation count:
If you need to show the total number of public annotations, page notes and orphaned annotations
on your third party page where the Hypothesis sidebar is embedded, add the `data-hypothesis-annotation-count`
attribute to the element that you want to enable.
The contents of the enabled element will be replaced with the count of public annotations and if there are no
public annotations, with 0.
Example:
To display the annotation count in a `div` element, simply
add the `data-hypothesis-annotation-count` attribute to the `div`:
```html
<div data-hypothesis-annotation-count>
Annotation count will appear here
</div>
```
Welcome to Hypothesis Client's documentation!
=============================================
The `Hypothesis client <https://github.com/hypothesis/client>`_ is a browser-based tool for making annotations on web
pages. It's a client for the `Hypothesis web annotation service <http://h.readthedocs.io/>`_.
It's used by the
`Hypothesis browser extension <https://chrome.google.com/webstore/detail/hypothesis-web-pdf-annota/bjfhmglciegochdpefhhlphglcehbmek>`_, and can also be
:doc:`embedded directly into web pages <publishers/embedding>`.
.. image:: /_static/screenshot.png
.. toctree::
:maxdepth: 2
:caption: Contents
publishers/index
developers/index
documenters/index
Configuring the Client
======================
This page documents the configuration settings that you can use to configure
the Hypothesis client once it's embedded in your website.
Configuring the Client Using JSON
---------------------------------
The Hypothesis client can be configured by providing a JSON config object in
the body of the hosting page:
.. code-block:: html
<script type="application/json" class="js-hypothesis-config">
{
"openSidebar": true
}
</script>
<script async src="https://hypothes.is/embed.js"></script>
Not all configuration settings can be set in this way, some must be
:ref:`set using JavaScript <configuring-with-js>` (see below).
.. note::
The body of the ``.js-hypothesis-config`` tag must be
`valid JSON <http://jsonlint.com/>`_, invalid JSON will cause the entire
config object to be ignored.
.. _configuring-with-js:
Configuring the Client Using JavaScript
---------------------------------------
.. js:function:: window.hypothesisConfig()
Alternatively, the Hypothesis client can be configured from the hosting page
by providing a JavaScript function named :js:func:`window.hypothesisConfig`
that returns a configuration object. Some configuration settings (for
example settings that register callback or event handler functions) can
*only* be set from JavaScript:
.. code-block:: javascript
window.hypothesisConfig = function () {
return {
"openSidebar": true
};
};
Config Settings
---------------
Client Behavior
###############
These settings configure the behavior and initial state of the client when it
loads.
.. option:: openLoginForm
``Boolean``. Controls whether the login panel is automatically opened on
startup, as if the user had clicked "Log in" themselves.
(Default: ``false``.)
.. option:: openSidebar
``Boolean``. Controls whether the sidebar opens automatically on startup.
(Default: ``false``.)
.. option:: showHighlights
``Boolean``. Controls whether the in-document highlights are shown by default.
(Default: ``true``.)
.. option:: services
``Array``. A list of alternative annotation services which the client should
connect to instead of connecting to the public Hypothesis service at
`hypothes.is <https://hypothes.is/>`_. May optionally include information
(in the form of grant tokens) about user accounts that the client is logged
in to on those services.
For example:
.. code-block:: javascript
window.hypothesisConfig = function () {
return {
services: [{
authority: 'partner.org',
grantToken: '***',
icon: 'https://openclipart.org/download/272629/sihouette-animaux-10.svg'
}],
};
};
By default, if no :option:`services` setting is given, the client connects
to the public Hypothesis service at `hypothes.is <https://hypothes.is/>`_.
.. warning::
The :option:`services` setting is currently still experimental and may
change in the future.
.. note::
Currently only one additional annotation service is supported - only the
first item in this :option:`services` array is used, and any further
items in the array are ignored.
Each item in the :option:`services` array should be an object describing an
annotation service, with the following keys:
.. option:: authority
``String``. The domain name which the annotation service is associated with.
.. option:: grantToken
``String|null``. An OAuth 2 grant token which the client can send to the
service in order to get an access token for making authenticated requests
to the service. If ``null``, the user will not be logged in and will only
be able to read rather than create or modify annotations. (Default:
``null``)
.. seealso::
:ref:`Generating authorization grant tokens` for how to generate grant
tokens for the `hypothes.is <https://hypothes.is/>`_ service.
.. option:: icon
``String|null``. The URL to an image for the annotation service. This
image will appear to the left of the name of the currently selected
group. The image should be suitable for display at 16x16px and the
recommended format is SVG.
.. option:: onLoginRequest
``function``. A JavaScript function that the Hypothesis client will
call in order to login (for example, when the user clicks a login button in
the Hypothesis client's sidebar).
This setting can only be set using :js:func:`window.hypothesisConfig`.
If the hosting page provides an :option:`onLoginRequest` function then the
Hypothesis client will call this function instead of doing its usual
procedure for logging in to the public service at `hypothes.is
<https://hypothes.is/>`_.
No arguments are passed to the :option:`onLoginRequest` function.
The :option:`onLoginRequest` function should cause a login procedure for
the hosting page to be performed - for example by redirecting to a login
page, or by opening a popup login window. After a successful login the
hosting page should reload the original page with a non-null
:option:`grantToken` for the logged-in user in the :option:`services`
configuration setting.
Asset and Sidebar App Location
##############################
These settings configure where the client's assets are loaded from.
.. warning::
These settings are currently still experimental and may change in the future.
.. option:: assetRoot
``String``. The root URL from which assets are loaded. This should be set to
the URL where the contents of the hypothesis package are hosted, including
the trailing slash. (Default: for production builds:
``"https://cdn.hypothes.is/hypothesis/X.Y.Z/"``, for development builds:
``"http://localhost:3001/hypothesis/X.Y.Z/""`.
``X.Y.Z`` is the package version from ``package.json``).
.. option:: sidebarAppUrl
``String``. The URL for the sidebar application which displays annotations
(Default: ``"https://hypothes.is/app.html"``).
How to Add Hypothesis to Your Website
=====================================
.. If you update this page, please ensure you update the "For Publishers" page
on the Hypothesis website, or coordinate with someone who can
(https://hypothes.is/for-publishers/).
To add Hypothesis to your website, just add this one line to the HTML source of
each page that you want to have the Hypothesis client on:
.. code-block:: html
<script src="https://hypothes.is/embed.js" async></script>
Interacting with the Client
===========================
This page documents the ways in which your website can interact with the
Hypothesis client, once the client is embedded in your site.
.. option:: data-hypothesis-trigger
You can add a button to your page that opens the Hypothesis sidebar.
If you need to have a custom trigger on your third party page to bring up
the embedded Hypothesis sidebar, add the :option:`data-hypothesis-trigger`
attribute to the element that you want to enable. Clicking that element
will cause the sidebar to open. Note, however, subsequent clicks do not
hide the sidebar.
For example to add a ``<button>`` on a page to open the sidebar, simply
add the :option:`data-hypothesis-trigger` attribute:
.. code-block:: html
<button data-hypothesis-trigger>
Open sidebar
</button>
.. option:: data-hypothesis-annotation-count
You can add a count of the number of annotations to your page.
If you need to show the total number of public annotations, page notes and
orphaned annotations on your third party page where the Hypothesis client
is embedded, add the :option:`data-hypothesis-annotation-count` attribute to
the element that you want to enable. The contents of the enabled element
will be replaced with the count of public annotations and if there are no
public annotations, with 0.
For example to display the annotation count in a ``<div>`` element, simply
add the :option:`data-hypothesis-annotation-count` attribute to the
``<div>``:
.. code-block:: html
<div data-hypothesis-annotation-count>
Annotation count will appear here
</div>
For Content Publishers
======================
This section is for **content publishers** who publish content to the web and
want to integrate the Hypothesis client into their web pages. If you want to
add the Hypothesis client to your web pages so that visitors can annotate the
pages without having to install their own Hypothesis browser extension, these
pages will help you get started.
.. toctree::
:maxdepth: 3
embedding
config
host-page-integration
# Python requirements needed to run the `make docs` command.
recommonmark
sphinx
sphinx-autobuild
sphinx_rtd_theme
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment