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. 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.
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 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 fromindex.json
, such assample.magg.io/sample
. Multipleallow
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 assample.magg.io/sample
. Multipleallow
parameters may be specified. Previous access rights are revoked, so each archive sign-on should contain anallow
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 assample.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
)
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 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.
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 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