|
|
# Payment vouchers
|
|
|
|
|
|
This document specifies how payment vouchers are handled by the Self-Service
|
|
|
Storage Gateway (SSGW).
|
|
|
|
|
|
A payment voucher is a small section of text which represents a payment of a
|
|
|
specified value. A voucher has the following properties:
|
|
|
|
|
|
* A unique id preventing "double-spending" of a voucher.
|
|
|
* A "value" giving the payment amount the voucher represents.
|
|
|
* An "issuer" known to the SSGW. (See below.)
|
|
|
* Optionally, a fixed user who can "spend" the voucher.
|
|
|
* Optionally, an expiry and start-of-validity date.
|
|
|
|
|
|
The SSGW supports multiple issuers. An issuer is responsible for choosing the
|
|
|
unique token id, the value to the token, the validity period (if any) and the
|
|
|
spending user (if any).
|
|
|
|
|
|
Administrators of the SSGW may add a trusted voucher issuer in the admin
|
|
|
interface. A voucher issuer consists of:
|
|
|
|
|
|
* A short slug identifying the issuer which matches the "iss" claim in the
|
|
|
voucher. Generally this is randomly generated using a tool such as
|
|
|
``pwgen``. It is not a secret so do not be tempted to use any existing
|
|
|
credential.
|
|
|
* An ECDSA public key for the issuer used to verify vouchers.
|
|
|
* Optionally, a human-readable description of the issuer.
|
|
|
|
|
|
For the moment all issuers are treated equally; any trusted issuer may issue a
|
|
|
token for any storage which supports voucher payments. This may change in
|
|
|
future.
|
|
|
|
|
|
## Issuing vouchers
|
|
|
|
|
|
This section describes how an issuer may create a voucher.
|
|
|
|
|
|
Firstly, you will need to create an ECDSA public/private key pair. You can do
|
|
|
this using the ``openssl`` command on Linux or OS X machines:
|
|
|
|
|
|
```
|
|
|
$ openssl ecparam -genkey -name prime256v1 -noout -out private.pem
|
|
|
$ openssl ec -in private.pem -pubout -out public.pem
|
|
|
```
|
|
|
|
|
|
Send the public key to the SSGW admins who will respond with your issuer id.
|
|
|
This should be used for the "iss" claim described below.
|
|
|
|
|
|
A "voucher" is actually a [JSON Web Token](https://jwt.io/) (JWT). A JWT allows
|
|
|
a JSON document (the "claims") to be encoded in a manner which is verifiable.
|
|
|
JWT supports multiple verification algorithms but the SSGW only supports the
|
|
|
"ES256" algorithm. All vouchers should be signed with the private key
|
|
|
corresponding to the public key sent to the SSGW admins.
|
|
|
|
|
|
JWT is [a standard](https://tools.ietf.org/html/rfc7519) and has an
|
|
|
[implementation](https://pyjwt.readthedocs.io/) available for Python.
|
|
|
|
|
|
### Voucher payload
|
|
|
|
|
|
The payload of the token has the following form. Some of the claims use
|
|
|
[registered claim names](https://tools.ietf.org/html/rfc7519#section-4.1) so
|
|
|
refer to the JWT standard for more information
|
|
|
|
|
|
```js
|
|
|
{
|
|
|
// REQUIRED. Unique id of JWT. Must be globally unique. The Base64
|
|
|
// representation of a v4 UUID is a good choice.
|
|
|
// The SSGW DOES NOT attempt to parse this value beyond using it to
|
|
|
// prevent double-spending.
|
|
|
"jti": string, // example: "njnsEdjkquFWiqfFEWjq8"
|
|
|
|
|
|
// REQUIRED. "Issuer" of token. Used to identify the private key which
|
|
|
// issued the token. Matched to a database of public keys in the SSGW. This
|
|
|
// should be your issuer id as given to you by the SSGW admins.
|
|
|
"iss": string, // example: "ifs-freemium"
|
|
|
|
|
|
// REQUIRED. Value of the voucher in Pounds Sterling. Must be a textual
|
|
|
// representation since JSON uses double precision floating point for
|
|
|
// numerical values which cannot represent certain common decimal values.
|
|
|
// (See the output of "python -c 'print(repr(0.1+0.2))'" for example.)
|
|
|
"val": string, // example "75.60"
|
|
|
|
|
|
// REQUIRED. Audience of the token. Vouchers for the SSGW should have
|
|
|
// this set to "ssgw".
|
|
|
"aud": "ssgw",
|
|
|
|
|
|
// OPTIONAL. Authorised user of token. If specified the crsid of the user
|
|
|
// making the purchase must match this field.
|
|
|
"crsid": string, // example: "spqr1"
|
|
|
|
|
|
// OPTIONAL. Number of seconds from 1970-01-01T00:00:00Z UTC at which
|
|
|
// the voucher expires. The voucher cannot be spent after this time.
|
|
|
"exp": number, // example: 12345
|
|
|
|
|
|
// OPTIONAL. Number of seconds from 1970-01-01T00:00:00Z UTC at which
|
|
|
// the voucher becomes valid. The voucher cannot be spent before this time.
|
|
|
"nbf": number, // example: 12345
|
|
|
|
|
|
// OPTIONAL. Number of seconds from 1970-01-01T00:00:00Z UTC at which
|
|
|
// this voucher was issued.
|
|
|
"iat": number, // example: 12345
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### Header
|
|
|
|
|
|
The JWT standard allows [some
|
|
|
claims](https://tools.ietf.org/html/rfc7519#section-10.4.1) to be repeated in
|
|
|
the header. The "iss" and "aud" claims MUST be present in the header and MUST be
|
|
|
identical to the corresponding claims in the payload. |