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:
-
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.
-
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. (This document describes how to do this.)
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.
A JWT-based flow where you do not need to implement the sign-on link generation yourself is also available. This is recommended for cases where JWT-based user tokens are already used in your authentication flows.
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.
Recommended usage flow
We recommend implementing the following flow on your site to provide secure and reliable access to your content:
-
User signs in to your site.
-
Your site presents one or more available issues, with links to your own sign-on URL generator.
-
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.
-
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 listing. You should direct the user to a separate handler which generates the link as described in step 3 above when they click on an issue.
If sign-on links are placed directly into the page HTML, users can copy and share links that grant access to paid content. Furthermore, if the user attempts to open an issue several minutes after opening the page, the link will be expired.
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.
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 signature) and unauthenticated (not included in the signature) query parameters. All query parameters are optional. All parameters must be encoded as UTF-8.
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
-
allow: additional products to allow access to, if issue archives are enabled in your Richie Editions deployment. The value is a product key fromindex.json, such assample.magg.io/sample. Multipleallowparameters 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). -
GTM data layer parameters with prefix
gtm_: see next section.
All other query parameters are passed as-is to the Richie Editions JavaScript client to control its behavior. No control parameters are currently documented.
GTM data layer parameters
Query parameters may be used to pass information to the Google Tag Manager data
layer for use in your analytics. These parameters must be prefixed by the string
gtm_, followed by the key that should appear in window.dataLayer.
For example, adding the query parameter gtm_userIsSubscriber=true causes
the entry {"userIsSubscriber": "true"} to be added to window.dataLayer.
These parameters are always unauthenticated. The gtm_ prefix may be customized
if needed.
Reserved query parameters
The following query parameters are reserved and must not be present in
the query string: user.
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. The list of reserved (prohibited) query parameters documented in the
prior section also applies to archive sign-ons.
Authenticated query parameters
-
allow: additional products to allow access to. The value for each is a product key from the issue index, such assample.magg.io/sample. Multipleallowparameters may be specified. Previous access rights are revoked, so each archive sign-on should contain anallowparameter 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 assample.magg.io/sample. -
GTM data layer parameters: as for issue sign-ons.
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 exact ASCII string is the key. You
do not need to decode the hex-encoded version into binary
The string over which the HMAC is calculated is constructed as follows:
issue_uuid|"archive" + "\n" +
timestamp + "\n" +
parameters
When signing an issue sign-on URL, issue_uuid is the UUID of the issue the
user is requesting as an ASCII string (example:
df12727c-bd54-42be-916c-0f5dd9e8747a). If signing an archive sign-on URL, the
literal string archive is used instead. In both cases lowercase characters
must be used.
timestamp is the current Unix timestamp without a decimal part converted to an
ASCII string, such as 1432301730. It must exactly match the timestamp that
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 by sorting based on the UTF-8-encoded byte-strings (not on the
original Unicode codepoints). Unicode Normalization Form C must be used (this is
the default for most implementations).
For example, if the URL parameters are allow=m2/p2&allow=m1/p1, the sorted parameter
string would be allow=m1/p1&allow=m2/p2.
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
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/79712d6fdaaa21571ddeb6afa2bc38390e01e7a898df47a00fb1b0fe072625cc?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 [('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_hashExamples
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 1e6f3357-80cc-4f54-81dc-152cc300164e, with parameters:
https://richie.example.com/_signin/1e6f3357-80cc-4f54-81dc-152cc300164e/1432301730/2e1ba0982e79d244e79bd5ff0b22a2e65b8d2d3313584e8040b61f349c30ab1e?allow=m1/p1&allow=m2/p2
Signed string is 1e6f3357-80cc-4f54-81dc-152cc300164e\n1432301730\nallow=m1/p1&allow=m2/p2.
Archive sign-on, multiple parameters, including an unauthenticated parameter:
https://richie.example.com/_signin/archive/1432301730/663ea159a9d08432c7596dcdf68f292a1dafe13828c5716bb35a715b62d4360f?allow=m1/p1&allow=m2/p2&initial_tag=sample/sample
Signed string is archive\n1432301730\nallow=m1/p1&allow=m2/p2.
Remote link generation
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:
Latest issue link
Configure your HTTP client to use HTTP Basic Authentication with 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 is
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.
Archive link
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 service.
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>/<subtenant>/_logout