Editions

Richie Editions HTML5: Single Sign-On

Developer guide for website implementators

Integrating the web version of Richie Editions with your website typically entails the following steps:

  1. Download and cache a list of issues from Richie servers, and use the contents to display a list of available issues. See the issue index documentation for details.

  2. Implement an authentication gateway. When the end user clicks the link to an issue, code on your web server must validate whether the user has access to the selected issue. If access is granted, your code must generate a cryptographically signed RichieSSO sign-on URL which points to the Richie authentication gateway server and redirect the user to that URL. Generating these links is described in this document.

For simple use cases where you wish to display only the latest issue on your site and prefer not to implement the cryptographic operations for generating RichieSSO URLs yourself, a simplified interface is also available. See section Remote RichieSSO link generation for details.

Richie servers can be accessed both using plain (unencrypted) HTTP as well as TLS-based (encrypted) HTTPS. The choice of protocol should match the protocol of your main web site. For simplicity, the examples below show https URLs; change the scheme to http if appropriate.

RichieSSO authenticated sign-on

The RichieSSO sign-on system provides a secure way to provide subscriber access to Richie Editions issues. Your sign-on system generates a signed URL and redirects the user to the Richie Editions authentication server, which validates the signature and grants access to the specified issues and issue archives.

The sign-on URL is valid for a short time (by default 10 minutes) to prevent distribution to third parties. It may optionally include an authenticated user identification token to identify users engaging in prohibited behavior from server logs.

We recommend implementing the following flow on your site to provide secure and reliable access to your content:

  1. User signs in to your site.

  2. Your site presents one or more available issues, with links to your own sign-on URL generator.

  3. When the user selects an issue to view, your sign-on URL generator checks the user's session and that the user is authorized to acess the issue in question, generates a RichieSSO sign-on URL for the current time, and immediately redirects the user to the newly-generated URL. This way the sign-on URL will always be fresh and will not be available for casual copying.

  4. The Richie Editions server validates the sign-on and grants the user access to the specified issue.

Warning: Your service must not directly place RichieSSO sign-on links onto a HTML page, such as your issue index. You should direct the user to a separate handler which generates the link as described in step 3 above. If sign-on links are placed directly onto a HTML page, users can copy and share links that grant access to paid content. Furthermore, if the user leaves the page open for several minutes and attempts to open an issue, the link(s) will be expired and the user will not be able to access the content.

URL format

Issue sign-ons

The basic format of the sign-on URL for an issue is https://<hostname>/_signin/<uuid>/<timestamp>/<sig>. hostname is the Richie Editions server name for your organization. uuid is the UUID of the issue to be opened, which is available in the issue index. The UUID should be specified using lowercase characters. timestamp is the current Unix timestamp (seconds since Jan 1 1970), without a decimal part. sig is the lowercase hexadecimal representation of a HMAC signature of the URL and its parameters. The computation of the signature is described in the section Signature calculation.

Additionally, the URL may contain both authenticated (included in the hash) and unauthenticated (not included in the signature) query parameters. All query parameters are optional. All parameters must be encoded as UTF-8. Conversion to Unicode Normalization Form C (the default for most systems) is recommended where applicable (Normalization Forms are only applicable to certain non-ASCII characters).

If your Editions HTML5 configuration includes subtenants, the sign-on URL must include the subtenant tag the user should be directed to: https://<hostname>/<subtenant>/_signin/…

Authenticated query parameters

  • user: contains a user identifier. The contents not processed by the Editions HTML5, but it is included in logs for monitoring purposes.

  • allow: additional products to allow access to, if issue archives are enabled in your Richie Editions deployment. The value is a product key from index.json, such as sample.magg.io/sample. Multiple allow parameters may be specified. The user is implicitly granted access to the archive of the product that is being requested.

  • return_link: if specified, the user is returned to this URL on authentication errors and when using the back button in the Richie Editions client. The content of the parameter must be an HTTP or HTTPS URL.

Unauthenticated query parameters

The following parameters are handled specially by the Richie Editions server:

  • page: number of the page to be shown when the issue opens (must be omitted or an integer).

All other query parameters are passed as-is to the Richie Editions JavaScript client to control its behavior. No control parameters are currently documented.

Archive sign-ons

To to directly enter the issue archive, use the format https://<hostname>/_signin/archive/<timestamp>/<sig>. The fields are the same as for issue sign-ons, but using one or more allow query parameters is necessary if archive authentication if enabled for your products.

Authenticated query parameters

  • user: as for issue sign-ons.

  • allow: additional products to allow access to. The value for each is a product key from the issue index, such as sample.magg.io/sample. Multiple allow parameters may be specified. Previous access rights are revoked, so each archive sign-on should contain an allow parameter for each product the user is entitled to.

  • return_link: as for issue sign-ons.

Unauthenticated query parameters

The following parameters are handled specially by the Richie Editions server:

  • initial_tag: the name of the product to show initially in the archive view. The value is a product key from the issue index, such as sample.magg.io/sample.

All other query parameters are passed as-is to the Editions HTML5 Javascript client to control its behavior. No control parameters are currently documented.

Signature calculation

The signature is an RFC 2104 HMAC using the SHA-256 hash function. Most standard cryptographic libraries provide functions for computing these functions.

The key for the HMAC signature has been provided to you during Editions HTML5 setup. It is typically given in the form of an UUID, such as 4361583c-be39-4dee-aa1c-a4ebe7f5ceda. This string encoded as ASCII is the key (i.e. you do not need to decode the hex-encoded UUID into binary).

The string over which the HMAC is calculated is constructed as follows:

issue_uuid|"archive" + "\n" +
timestamp + "\n" +
parameters

issue_uuid is the UUID of the issue the user is entering as an ASCII string, such as df12727c-bd54-42be-916c-0f5dd9e8747a, or the string archive when signing an archive sign-on URL. These strings must be in lowercase characters.

timestamp is the current Unix timestamp without a decimal part converted to an ASCII string, such as 1432301730, as it appears in the sign-on URL.

parameters are the authenticated query parameters of the URL, in UTF-8 encoded query string format. URL encoding must not be applied. The parameters must be sorted first by key and then by value. The sorting must be done after UTF-8 encoding, in other words by sorting based on the UTF-8-encoded byte-strings, not on the original Unicode characters. Unicode Normalization Form C must be used (this is the default for most implementations).

For example, if the URL parameters are user=foo&allow=m2/p2&allow=m1/p1, the sorted parameter string would be allow=m1/p1&allow=m2/p2&user=foo.

The resulting binary signature must be converted to hex-encoded form using lowercase characters.

Signature calculation example

Given the above issue_uuid, timestamp and parameters, the HMAC-SHA256 would be calculated over the following string (no trailing newline):

df12727c-bd54-42be-916c-0f5dd9e8747a
1432301730
allow=m1/p1&allow=m2/p2&user=foo

Given the above secret 4361583c-be39-4dee-aa1c-a4ebe7f5ceda, the hex-encoded result of the calculation is c982c54f694898808ae339dbd059b71c8b385654e3ef250bc9325b5f86dd162d.

The final sign-on URL would be:

https://richie.example.com/_signin/df12727c-bd54-42be-916c-0f5dd9e8747a/1432301730/c982c54f694898808ae339dbd059b71c8b385654e3ef250bc9325b5f86dd162d?user=foo&allow=m1/p1&allow=m2/p2

Signature calculation example code

The following Python 3 code demonstrates computation of the signature HMAC value. auth_params is an optional list of authenticated URL parameter key/value tuples, for example [('user', 'foo'), ('allow', 'm1/p1'), ('allow', 'm2/p2')].

def gen_hash(secret: str, issue_id: str, timestamp: float, auth_params: Optional[list] = None):
    # Encode all arguments to bytes for the hashing process
    b_timestamp = bytes(str(int(timestamp)), 'ascii')
    b_issue_id = bytes(issue_id, 'ascii')
    b_secret = bytes(secret, 'ascii')
 
    # If optional authenticated parameters are present,
    # convert to encoded form. The parameters must be
    # a list of (key, value) tuples.
    b_params = b''
    if auth_params:
        ap_list = []
        for key, value in auth_params:
            b_key = bytes(key, 'utf-8')
            b_value = bytes(value, 'utf-8')
 
            ap_list.append((b_key, b_value))
        # Parameters must be sorted by their encoded values
        ap_list.sort()
 
        # Format as a query string _without_ URL encoding
        ap_strs = [key + b'=' + value for key, value in ap_list]
        b_params = b'&'.join(ap_strs)
 
    # Combine all the pieces separated by newlines and generate the HMAC-SHA256
    sig_data = b_issue_id + b'\n' + b_timestamp + b'\n' + b_params
 
    import hashlib, hmac
    sig_hash = hmac.new(b_secret, sig_data, hashlib.sha256).hexdigest()
 
    return sig_hash

Examples

The following examples demonstrate various sign-on URLs using the secret key 4361583c-be39-4dee-aa1c-a4ebe7f5ceda signed at the time 1432301730.

sign-on to issue de27f9d8-b020-43d7-99a6-15184d5d986f, no parameters:

https://richie.example.com/_signin/de27f9d8-b020-43d7-99a6-15184d5d986f/1432301730/584345aa710a7b5ef512aa1224872f127d81950a4fff896568019cde64d5fd18

(signed string is 'de27f9d8-b020-43d7-99a6-15184d5d986f\n1432301730\n)

sign-on to issue b46a037f-5e08-4edc-828f-35201caddd49, one parameter:

https://richie.example.com/_signin/b46a037f-5e08-4edc-828f-35201caddd49/1432301730/927c8ba1b336ed4788a1a15637c8e481439d104c78a00230ce1d1c7ad13e0aac?user=foobar

(signed string is b46a037f-5e08-4edc-828f-35201caddd49\n1432301730\nuser=foobar)

sign-on to issue 1e6f3357-80cc-4f54-81dc-152cc300164e, multiple parameters:

https://richie.example.com/_signin/1e6f3357-80cc-4f54-81dc-152cc300164e/1432301730/fb9ed2e7e61c8abd5a680955d54f89753d9e7f1a3319694db9629e50e005306b?user=foobar&allow=m1&allow=m2

(signed string is 1e6f3357-80cc-4f54-81dc-152cc300164e\n1432301730\nallow=m1&allow=m2&user=foobar)

Archive sign-on, multiple parameters, including an unauthenticated parameter:

https://richie.example.com/_signin/archive/1432301730/a7123bc42c5cf8be3dbaf73280e02ebb033af4d2591ebdac89d397321ee72fd4?user=foobar&allow=m1&allow=m2&initial_tag=sample.magg.io/sample

(signed string is archive\n1432301730\nallow=m1&allow=m2&user=foobar)

When only the latest issue of your product(s) needs to be accessible on your website and you wish to keep your backend code as simple as possible, you can have the Editions HTML5 server perform the above computations to generate the RichieSSO link.

Using this mechanism, you also do not need to fetch and parse index.json or latest.json on your own backend server(s). This allows you to implement a completely stateless backend for your website.

Link generation requires you to implement only a single HTTPS request (HTTP is not available for security reasons) with HTTP Basic Authentication in your authentication gateway code. The result of this request is a RichieSSO URL which allows the user to access the latest issue of the selected product.

It is also possible to get a RichieSSO URL which allows the user to access the Editions HTML5 built-in issue archive, if this functionality is enabled for your products.

A high level overview of the sign-on process from your system’s perspective looks like this:

Link generation flowchart

Configure your HTTP client to use HTTP Basic Authentication for the realm maggio-authproxy-links using the username lgen and the link generator password issued to you.

Perform a HTTP request to the URL https://<hostname>/_get_link/<organization>/<product>. hostname is your Richie Editions server name, and organization and product represent the product configured for the target publication in Editions Author.

For example if your company is called NewsCo and you publish a newspaper called DailyNews, the request URL might be https://newsco.ap.richiefi.net/_get_link/newsco/dailynews.

On success, the call returns a text/plain response which is the RichieSSO URL for the latest issue of the given product (for example, today's issue of the DailyNews paper). Your authentication gateway can then simply redirect the end-user to this URL.

A HTTP error response is returned if the link could not be generated. The cause is indicated by one of the following HTTP error codes:

  • 403: authentication failed or attempted to use unencrypted HTTP.
  • 404: product invalid or no issues available.
  • 500/502/503: temporary failure; your code should retry the request.

To request a link to the issue archive, use the URL https://<hostname>/_get_link/. As above, a RichieSSO URL which allows the user to enter the issue archive is returned.

Error codes are as above, except that status 404 signifies that issue archives are not configured on your Richie Editions server.

Issue archive logout

If you want to revoke the user's access to the issue archive when they log out from your site, have the user's browser perform an XHR request to https://<hostname>/_logout during your logout flow. This will clear the relevant access control cookies from the user's browser.

Note: You must have the user's browser make the _logout call as it requires access to cookies—calling it from a server-side logout hook or similar will have no effect.

The logout call returns status 200 with the JSON result {"status": "ok"} on success.

Implementing the logout call is optional. The cookies used by Editions HTML5 will expire within a limited time and are not renewable by the user without going through your site's access control.

If your Editions HTML5 configuration uses subtenants, the call must include the subtenant tag: https://<hostname>/<tag>/_logout

Previous
Issue Indexes