Skip to content

Commit

Permalink
SEP-10: Add multi-sig capabilities (#489)
Browse files Browse the repository at this point in the history
Add requirements to SEP-10 that a server validate that the client key that has signed the challenge transaction is actually a signer of the account. Add details about how multiple signatures on a challenge transaction are a possibility.

SEP-10 has the goal to provide the mechanics to help a server get proof that a client holds a Stellar account, but if a server was to implement only the functionality described in this document it would only be proving that the client is in possession of the secret key of the account's address, the master key, and not necessarily the Stellar account. The checks required to go beyond that have until now been left up to the implementer to define.

Proving possession of a secret key doesn't prove any threshold of control of an account because an account can alter its signers. The master key for an account may have its weight reduced to zero which removes the master key as a signer, and so possession of a master key is not proof of control of an account.

It's important that implementers of SEP-10 take an extra step that is not currently discussed in the document. That extra step is to verify that the key is a signer on the account and that the weight of that signature is sufficient from the perspective of the service/anchor for whatever interactions taking place.

It's also possible for accounts to have multiple signers where no single signer will have sufficient weight to meet any threshold. In this case it's important for SEP-10 to allow a combination of signatures to prove control of the account.

This change is important for supporting applications that do not use the master key as a signer, that rotate the signing key for a single signature account, and for accounts that have multiple signers.
  • Loading branch information
leighmcculloch committed Jan 29, 2020
1 parent 3c7afa0 commit ea0d7ed
Showing 1 changed file with 62 additions and 10 deletions.
72 changes: 62 additions & 10 deletions ecosystem/sep-0010.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
```
SEP: 0010
Title: Stellar Web Authentication
Author: Sergey Nebolsin <sergey@mobius.network>, Tom Quisel <tom.quisel@gmail.com>
Author: Sergey Nebolsin <sergey@mobius.network>, Tom Quisel <tom.quisel@gmail.com>, Leigh McCulloch <@leighmcculloch>
Status: Active
Created: 2018-07-31
Updated: 2019-12-02
Version 1.2.0
Updated: 2020-01-29
Version 1.3.0
```

## Simple Summary
Expand All @@ -22,18 +22,23 @@ The authentication flow is as follows:

1. The client obtains a unique [`challenge`](#challenge), which is represented as specially formed Stellar transaction
1. The client verifies that the transaction has an invalid sequence number 0. This is extremely important to ensure the transaction isn't malicious.
1. The client signs the transaction using the secret key for the user's Stellar account
1. The client signs the transaction using the secret key(s) of signers for the user's Stellar account
1. The client submits the signed challenge back to the server using [`token`](#token) endpoint
1. The server gets the signers of the user's account
1. The server verifies the signatures
1. The server verifies the weight provided by the signers meets the required threshold(s), if any
1. If the signature checks out, the server responds with a [JWT](https://jwt.io) that represents the user's session
1. Any future calls to the server can be authenticated by including the JWT as a parameter

The flow achieves several things:

* Both client and server part can be implemented using well-established Stellar libraries
* The client can verify that the server holds the secret key to a particular account
* The server can verify that the client holds the secret key to their account
* The client is able to prove their identity using a Ledger or other hardware wallet as well as by having direct access to the secret key
* The server can verify that the client holds the secret key(s) to signers of their account
* The client is able to prove their identity using a Ledger or other hardware wallet as well as by having direct access to the secret key(s)
* The server can choose its own timeout for the user's session
* The server can choose required threshold(s) that the user needs on the account, if any
* The server can choose to include other application specific claims

## Authentication Endpoint

Expand Down Expand Up @@ -81,7 +86,7 @@ On success the endpoint must return `200 OK` HTTP status code and a JSON object
* `transaction`: an XDR-encoded Stellar transaction with the following:
* source account set to server's signing account
* invalid sequence number (set to 0) so the transaction cannot be run on the Stellar network
* time bounds: `{min: now(), max: now() + 300 }` (we recommend expiration of 5 minutes to give user time to sign transaction)
* time bounds: `{min: now(), max: now() + 900 }` (we recommend expiration of 15 minutes to give user time to sign transaction)
* operations: `manage_data(source: client_account, key: '<anchor name> auth', value: random_nonce())`
* The value of key is not important, but can be the name of the anchor followed by `auth`. It can be at most 64 bytes.
* The value must be 64 bytes long. It contains a 48 byte cryptographic-quality random string encoded using base64 (for a total of 64 bytes after encoding).
Expand Down Expand Up @@ -122,16 +127,25 @@ To validate the challenge transaction the following steps are performed by the s
* verify that transaction has time bounds set, and that current time is between the minimum and maximum bounds;
* verify that transaction contains a single [Manage Data](https://www.stellar.org/developers/guides/concepts/list-of-operations.html#manage-data) operation and its source account is not null;
* verify that transaction envelope has a correct signature by server's signing key;
* verify that transaction envelope has a correct signature by the operation's source account;
* if the operation's source account exists:
* verify that client signatures count is one or more;
* verify that client signatures on the transaction are signers of the operation's source account;
* verify that client signatures are correct;
* verify that client signatures provide weight that meets the required threshold(s), if any;
* if the operation's source account does not exist:
* verify that client signature count is one;
* verify that client signature is correct for the master key of the account address;
* verify that transaction sequenceNumber is equal to zero;
* use operations's source account to determine the authenticating client and perform any additional service-specific validations.

Upon successful validation service responds with a session JWT, containing the following claims:
The verification process confirms that a user holds an account. Depending on your application this may mean complete signing authority, some threshold of control, or being a signer of the account. See [Verification](#verification) for examples.

Upon successful verification, service responds with a session JWT, containing the following claims:

* `iss` (the principal that issued a token, [RFC7519, Section 4.1.1](https://tools.ietf.org/html/rfc7519#section-4.1.1)) — a [Uniform Resource Identifier (URI)] for the issuer (`https://example.com` or `https://example.com/G...`)
* `sub` (the principal that is the subject of the JWT, [RFC7519, Section 4.1.2](https://tools.ietf.org/html/rfc7519#section-4.1.2)) — the public key of the authenticating Stellar account (`G...`)
* `iat` (the time at which the JWT was issued [RFC7519, Section 4.1.6](https://tools.ietf.org/html/rfc7519#section-4.1.6)) — current timestamp (`1530644093`)
* `exp` (the expiration time on or after which the JWT must not be accepted for processing, [RFC7519, Section 4.1.4](https://tools.ietf.org/html/rfc7519#section-4.1.4)) — a server can pick its own expiration period for the token, however 24 hours is recommended (`1530730493`)
* `exp` (the expiration time on or after which the JWT must not be accepted for processing, [RFC7519, Section 4.1.4](https://tools.ietf.org/html/rfc7519#section-4.1.4)) — a server can pick its own expiration period for the token (`1530730493`)

The JWT may contain other claims specific to your application, see [RFC7519].

Expand Down Expand Up @@ -187,6 +201,44 @@ Every other HTTP status code will be considered an error. For example:
}
```

## Verification

The verification process confirms that a user holds an account. Depending on your application this may mean complete signing authority, some threshold of control, or being a signer of the account.

An account's master key may not meet any threshold of control or could have had its weight reduced to zero. Most applications should not assume possession of the master key is possession of an account.

An account's signers may include third-party services providing services to the user. Authenticating users with less than any threshold may allow a third-party to authenticate as a user.

An account's signers may include the server's signing key if the server is a signer for the account. When determining the weight of the client sigantures the server's signature should be explicitly excluded. A server should not assist a client in authentication.

The server should only issue a JWT if the appropriate thresholds are met, but if a server is supporting a variety of applications it may choose to use additional application specific claims to capture the threshold of control the user has proven.

### Verifying Authority to Move Funds

A server that needs to verify that a user has authority aligned with the capability to move money out of an account can verify that the user meets the medium threshold. It should do this by checking that the sum of the weights of the challenge transaction signers is equal or greater to the medium threshold.

#### Example

An anchor implementing [SEP-24] will let an authenticated user define the destination of withdrawn funds. This level of control is similar to the capability to choose the destination of payments on the network which require a medium threshold.

[SEP-24]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0024.md

### Verifying Complete Authority

A server that needs to verify a user has complete authority of an account should verify that the weight of the client signatures meet the high threshold. It should do this by checking that the sum of the weights is equal or greater to the high threshold.

### Verifying Being a Signer

A server may choose to issue JWTs for less than all thresholds and based on any other application specific logic. It's important to keep in mind that a Stellar account may have third-parties who are signers. Authenticating users with less than any threshold may allow a third-party to authenticate as a user.

### Verifying Accounts that Do Not Exist

A server that needs to support validating accounts that do not exist can require a signature of the master key of the account address for accounts that do not exist.

## JWT Expiration

Servers should select an expiration time for the JWT that is appropriate for the assumptions and risk of the interactions a user can perform with it. A user may be in control of an account at the time the JWT is issued but they may lose control of the account through a change in signers. Expiration times that are too long increase the risk that control on the account has changed. Expiration times that are too short increase the number of times authentication must reoccur, and a user using a hardware signing device or who must complete a complex signing process could have a poor user experience.

## A convention for signatures

Signatures in Stellar involve both the secret key of the signer and the passphrase of the network. SEP-10 clients and servers must use the following convention when deciding what network passphrase to use for signing and verifying signatures in SEP-10:
Expand Down

0 comments on commit ea0d7ed

Please sign in to comment.