diff --git a/0035-ilp-over-http/0035-ilp-over-http.md b/0035-ilp-over-http/0035-ilp-over-http.md index 28812476..79b83e62 100644 --- a/0035-ilp-over-http/0035-ilp-over-http.md +++ b/0035-ilp-over-http/0035-ilp-over-http.md @@ -1,6 +1,6 @@ --- title: ILP Over HTTP -draft: 2 +draft: 3 --- # ILP Over HTTP @@ -20,10 +20,6 @@ Each ILP Prepare packet is sent as the body of an HTTP request to the peer's ser This is a minimal protocol built on HTTP. HTTP/2 is HIGHLY RECOMMENDED for performance reasons, although HTTP/1.1 MAY also be used. Implementations SHOULD support HTTP version negotiation via Application Protocol Negotiation (ALPN). -### Authentication - -Peers MAY use any standard HTTP authentication mechanism to authenticate incoming requests. TLS Client Certificates are RECOMMENDED between peers for security and performance, though bearer tokens such as JSON Web Tokens (JWTs) or Macaroons MAY be used instead. Basic authentication (username and password) is NOT RECOMMENDED, because of the additional delay introduced by securely hashing the password. - ### Request ```http @@ -56,3 +52,119 @@ All ILP Packets MUST be returned with the HTTP status code `200: OK`. An endpoint MAY return standard HTTP errors, including but not limited to: a malformed or unauthenticated request, rate limiting, or an unresponsive upstream service. Connectors SHOULD either retry the request, if applicable, or relay an ILP Reject packet back to the original sender with an appropriate [Final or Temporary error code](./0027-interledger-protocol-4/0027-interledger-protocol-4#error-codes). Server errors (status codes 500-599) SHOULD be translated into ILP Reject packets with `T00: Temporary Error` codes. +### Authentication +When authenticating requests between Interledger nodes, it is important to choose an algorithm that maintains an appropriate balance between usability and security, while at the same time maintaining high-performance _and_ interoperability. + +In order to find this balance, this document defines two Authentication profiles, each with various trade-offs that should be considered before use: + +* `SIMPLE`: Allows two ILP nodes to utilize a previously agreed-upon shared-secret as a [Bearer token](https://tools.ietf.org/html/rfc6750) in all ILP-over-HTTP requests. Peers SHOULD consider this token to be opaque and SHOULD NOT derive any special meaning from the token. + +* `JWT_HS_256`: Allows two ILP nodes to utilize a previously agreed-upon shared-secret in order to _derive_ a Bearer token that conforms to the JSON Web Token (JWT) specification. JWTs generated by this scheme can then be used as a Bearer in all ILP-over-HTTP requests. + +Peers MAY use any standard HTTP authentication mechanism to authenticate incoming requests, MUST support `JWT_HS_256`. + +#### `SIMPLE` Authentication Profile +This profile allows two ILP nodes to utilize a previously agreed-upon shared-secret that contains at least 32 bytes (256 bits) of randomly generated data, and is encoded using Base64. + +Because tokens in this profile do not inherently contain information about the identity of the caller, requests MUST contain an additional HTTP request-header named `Auth-Principal`. + +This extra header allows for the identity of the authentication request to be separated from authentication token itself, which reduces computational overhead as well as data-management complexity (e.g., implementations do not need to create data-store indexes using derivations of tokens for lookup purposes). + +##### Example Usage +An example shared-secret in this profile is `HEiMCp0FoAC903QHueY89gAWJHo/izaBnJU8/58rlSI=`. This shared secret is passed as an `Authorization` header in each HTTP request, using the Bearer token scheme, along with an `Auth-Principal` header like this: + +``` +Auth-Principal: alice-usd-123 +Authorization: Bearer HEiMCp0FoAC903QHueY89gAWJHo/izaBnJU8/58rlSI= +``` + +Implementations MAY support this profile, but SHOULD consider it for development purposes only. + +##### Trade-off Summary +* **Pros** + * The simplest, most usable Authentication profile -- just a shared-secret with _at least_ 32 bytes and an identity header. + * Very little processing time to verify a token (just a simple value comparison or, for more security, an HMAC-SHA256 computation). + +* **Cons** + * The shared-secret is transmitted "on the wire" for every request, increasing the chances that it might be intercepted by a compromised TLS session (e.g., a [MITM attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack)); a TLS termination endpoint (e.g., a Load Balancer); or logged by an internal system during transit. + * The shared-secret itself never expires, so if an implementation neglects to rotate the secret with its peer, this token will likely be very long-lived. This increases the chance of compromise by an attacker, and means compromised usage of this type of token could go undetected for very longer periods of time. + * Requires out-of-band communication for both peers to agree upon the shared secret. + +#### `JWT_HS_256` Authentication Profile +This profile allows two ILP nodes to utilize a previously agreed-upon shared-secret, but then derive an [RFC-7519](https://tools.ietf.org/html/rfc7519) compliant JWT token in order to perform actual authentication. + +##### JWT Claims +In order to be considered a valid JWT for this profile, the signed JWT MUST contain a `sub` (subject) claim containing the identifier of the "principal" that the token authenticates. + +A JWT token SHOULD also include an `exp` (expiry) claim that indicates a date/time after which the token should be considered invalid. Implementations SHOULD reject any tokens with a missing or invalid expiry claim. + +Note that tokens without this claim never expire, and only become invalid if the shared-secret used to sign the JWT changes or is otherwise invalidated. + +##### Example Usage +In this profile, the Base64-encoded JWT is passed as an `Authorization` header in each HTTP request, using the [Bearer token](https://tools.ietf.org/html/rfc6750) scheme. + +One example of such a Bearer token: + +`Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhbGljZSJ9._Jn0pkqrK1leE3WZJKn-g5hm5kGJxGdSHggtz5wO1w4`. + +Using the JWT specification, this token can be verified using the shared-secret previously agreed upon. For example, the above token contains a `sub` claim of `alice` and can be verified using a shared-secret value of `HEiMCp0FoAC903QHueY89gAWJHo` (Base64 encoded). + +Another example is a Bearer token that contains an expiration date: + +`Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhbGljZSIsImV4cCI6MTU1ODAzNTg2OH0.__9CiSGdn4Grhl48slun7Lp4q4xt0uq398omcipBU8M`. + +Using the JWT specification, this token can be verified using the shared-secret previously agreed upon. For example, the above token contains a `sub` claim of `alice` and an `exp` claim of `1558035868`, which means this token is no longer valid after `May 16th, 2019 at 9:29:11 GMT`. This token can be verified using a shared-secret value of `HEiMCp0FoAC903QHueY89gAWJHo` (Base64 encoded). + +##### Trade-off Summary +* **Pros** + * Same usability as the `SIMPLE` profile -- just a shared-secret with _at least_ 32 bytes and a `sub` claim. + * Allows both identity and authentication claims to be contained in single Bearer token, which eliminates the need for a second `Auth-Principal` header. This should simplify token validation and ease account-lookup (no need to create an HMAC or encrypted data-store index because the principal can be trivially decoded from the token). + * Requires only enough processing to perform an HMAC-SHA256 signing operation, which is very fast. + * Supports token expiry, which allows tokens to be generally short-lived so that peers can narrow the potential window of unauthorized usage in the event of token compromise. + * The actual shared-secret is _never_ transmitted "on the wire" during any request. Instead, authentication tokens are always _derived_ from the shared-secret, which eliminates the risk of an _actual_ shared-secret being intercepted in transit. + +* **Cons** + * Total transmitted bytes for authentication are more than the `SIMPLE` scheme (about 41 bytes, or ~50% more). However, HTTP/2 header compression should mitigate this differential. + * Requires out-of-band communication for both peers to agree upon the shared secret. + +## Appendix1: Security Best Practices +This section outlines and clarifies some best practices for authentication-token security when using this protocol. Recommendations in this section are _Non-Normative_, but highly RECOMMENDED. + +### Follow Standardized Security Recommendations +It is advisable to follow all applicable best practices when using a Bearer-token scheme for authentication. [Section 5.1 of RFC-6570](https://tools.ietf.org/html/rfc6750#section-5) contains a number of very good practices that should be considered on a per-deployment basis. + +### HTTP BASIC/FORM Auth +HTTP Auth schemes using a username and password is NOT RECOMMENDED for the same reasons that the `SIMPLE` profile is only recommended for development and testing scenarios only. + +### Use SIMPLE Profile for Development/Testing Only +The `SIMPLE` authentication profile provides only marginal benefits when compared to the `JWT_HS_256` profile, but introduces significant drawbacks as outlined in the "Trade-off Summary" sections of this RFC. As such, the `SIMPLE` profile MAY be used for development or testing purposes, but SHOULD NOT be used in production scenarios. Instead, prefer `JWT_HS_256` for production deployments. + +### Use Reasonable Token Expiries +Tokens generators should choose a reasonable token expiry. Considerations in this choice include the ability to cache and re-use authentication tokens for a limited time in order to enable very fast authentication decisions. However, this should be balanced against a desire for shorter token lifetimes, which will limit the attack surface caused by a compromised token. + +As a best practice, implementations SHOULD use tokens that expire. For example, consider generating tokens with a lifetime that doesn't exceed 5 minutes. + +### Secrets At Rest +In most ILP Connector implementations, secrets are stored on a per-account basis in some sort of data-store. Implementations SHOULD protect secret-values that can be used to generate authentication tokens by encrypting them prior to storage. This will help prevent actual shared secrets from being captured by unauthorized parties, increasing the chances that only the Connector runtime will be able to generate tokens using underlying shared-secrets. + +One option is to encrypt any secrets at-rest using an Authenticated Encryption algorithm, such as AES-GCM-256. This [article](https://proandroiddev.com/security-best-practices-symmetric-encryption-with-aes-in-java-7616beaaade9) provides a nice overview using Java, along with various configuration options to consider. + +### Secrets In Memory +Implementations SHOULD minimize the amount of time that an actual secret-value exists in-memory in unencrypted form. This includes narrowing the availability of secrets to only code that actually requires them; minimizing the time any secret might exist in memory; and zeroing out memory after a secret is no longer used, if possible. + +### Mutual TLS +All ILP-over-HTTP connections MUST be performed over a TLS session. However, it is also RECOMMENDED to use TLS Client Certificates between peers for additional security. + +### High Security Deployments +For deployments requiring very high security, it is recommended to utilize a secret-store deployed outside of the Connector runtime, such as [Vault](https://www.vaultproject.io/) or an [HSM](https://safenet.gemalto.com/data-encryption/hardware-security-modules-hsms/) or both. + +This will provide an extra layer of protection in case a Connector runtime is compromised, and will also make it significantly harder for an attacker to compromise actual shared-secret values (especially if employing an HSM). + +However, before employing such a system, Connector operators SHOULD perform extensive performance testing to ensure proper levels of service. + +## Appendix2: Normative References +For more details on the algorithms and standards referenced in this RFC, see the following: + +* RFC-6750: [Bearer Token Usage](https://tools.ietf.org/html/rfc6750) +* RFC-7518: [JSON Web Algorithms (JWA)](https://www.rfc-editor.org/rfc/rfc7518.html) +* RFC-7519: [JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519.html)