Skip to content

Commit 89f2d88

Browse files
authored
Added webAuthDomain parameter and validation to SEP-10 util functions (#607)
1 parent 052266a commit 89f2d88

File tree

2 files changed

+319
-17
lines changed

2 files changed

+319
-17
lines changed

src/utils.ts

+32-2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ export namespace Utils {
2929
* @param {string} homeDomain The fully qualified domain name of the service requiring authentication
3030
* @param {number} [timeout=300] Challenge duration (default to 5 minutes).
3131
* @param {string} networkPassphrase The network passphrase. If you pass this argument then timeout is required.
32+
* @param {string} webAuthDomain The fully qualified domain name of the service issuing the challenge.
3233
* @example
3334
* import { Utils, Keypair, Networks } from 'stellar-sdk'
3435
*
3536
* let serverKeyPair = Keypair.fromSecret("server-secret")
36-
* let challenge = Utils.buildChallengeTx(serverKeyPair, "client-stellar-account-id", "SDF", 300, Networks.TESTNET)
37+
* let challenge = Utils.buildChallengeTx(serverKeyPair, "client-stellar-account-id", "stellar.org", 300, Networks.TESTNET)
3738
* @returns {string} A base64 encoded string of the raw TransactionEnvelope xdr struct for the transaction.
3839
*/
3940
export function buildChallengeTx(
@@ -42,6 +43,7 @@ export namespace Utils {
4243
homeDomain: string,
4344
timeout: number = 300,
4445
networkPassphrase: string,
46+
webAuthDomain: string,
4547
): string {
4648
if (clientAccountID.startsWith("M")) {
4749
throw Error(
@@ -74,6 +76,13 @@ export namespace Utils {
7476
source: clientAccountID,
7577
}),
7678
)
79+
.addOperation(
80+
Operation.manageData({
81+
name: "web_auth_domain",
82+
value: webAuthDomain,
83+
source: account.accountId(),
84+
}),
85+
)
7786
.build();
7887

7988
transaction.sign(serverKeypair);
@@ -103,13 +112,15 @@ export namespace Utils {
103112
* @param {string} serverAccountID The server's stellar account (public key).
104113
* @param {string} networkPassphrase The network passphrase, e.g.: 'Test SDF Network ; September 2015'.
105114
* @param {string|string[]} [homeDomains] The home domain that is expected to be included in the first Manage Data operation's string key. If an array is provided, one of the domain names in the array must match.
115+
* @param {string} webAuthDomain The home domain that is expected to be included as the value of the Manage Data operation with the 'web_auth_domain' key. If no such operation is included, this parameter is not used.
106116
* @returns {Transaction|string|string} The actual transaction and the stellar public key (master key) used to sign the Manage Data operation, and matched home domain.
107117
*/
108118
export function readChallengeTx(
109119
challengeTx: string,
110120
serverAccountID: string,
111121
networkPassphrase: string,
112122
homeDomains: string | string[],
123+
webAuthDomain: string,
113124
): { tx: Transaction; clientAccountID: string; matchedHomeDomain: string } {
114125
if (serverAccountID.startsWith("M")) {
115126
throw Error(
@@ -182,7 +193,7 @@ export namespace Utils {
182193

183194
if (operation.value === undefined) {
184195
throw new InvalidSep10ChallengeError(
185-
"The transaction's operation value should not be null",
196+
"The transaction's operation values should not be null",
186197
);
187198
}
188199

@@ -234,6 +245,19 @@ export namespace Utils {
234245
"The transaction has operations that are unrecognized",
235246
);
236247
}
248+
if (op.value === undefined) {
249+
throw new InvalidSep10ChallengeError(
250+
"The transaction's operation values should not be null",
251+
);
252+
}
253+
if (
254+
op.name === "web_auth_domain" &&
255+
op.value.compare(Buffer.from(webAuthDomain))
256+
) {
257+
throw new InvalidSep10ChallengeError(
258+
`'web_auth_domain' operation value does not match ${webAuthDomain}`,
259+
);
260+
}
237261
}
238262

239263
return { tx: transaction, clientAccountID, matchedHomeDomain };
@@ -266,6 +290,7 @@ export namespace Utils {
266290
* @param {number} threshold The required signatures threshold for verifying this transaction.
267291
* @param {ServerApi.AccountRecordSigners[]} signerSummary a map of all authorized signers to their weights. It's used to validate if the transaction signatures have met the given threshold.
268292
* @param {string|string[]} [homeDomains] The home domain(s) that should be included in the first Manage Data operation's string key. Required in verifyChallengeTxSigners() => readChallengeTx().
293+
* @param {string} webAuthDomain The home domain that is expected to be included as the value of the Manage Data operation with the 'web_auth_domain' key, if present. Used in verifyChallengeTxSigners() => readChallengeTx().
269294
* @returns {string[]} The list of signers public keys that have signed the transaction, excluding the server account ID, given that the threshold was met.
270295
* @example
271296
*
@@ -317,6 +342,7 @@ export namespace Utils {
317342
threshold: number,
318343
signerSummary: ServerApi.AccountRecordSigners[],
319344
homeDomains: string | string[],
345+
webAuthDomain: string,
320346
): string[] {
321347
const signers = signerSummary.map((signer) => signer.key);
322348

@@ -326,6 +352,7 @@ export namespace Utils {
326352
networkPassphrase,
327353
signers,
328354
homeDomains,
355+
webAuthDomain,
329356
);
330357

331358
let weight = 0;
@@ -369,6 +396,7 @@ export namespace Utils {
369396
* @param {string} networkPassphrase The network passphrase, e.g.: 'Test SDF Network ; September 2015'.
370397
* @param {string[]} signers The signers public keys. This list should contain the public keys for all signers that have signed the transaction.
371398
* @param {string|string[]} [homeDomains] The home domain(s) that should be included in the first Manage Data operation's string key. Required in readChallengeTx().
399+
* @param {string} webAuthDomain The home domain that is expected to be included as the value of the Manage Data operation with the 'web_auth_domain' key, if present. Used in readChallengeTx().
372400
* @returns {string[]} The list of signers public keys that have signed the transaction, excluding the server account ID.
373401
* @example
374402
*
@@ -406,13 +434,15 @@ export namespace Utils {
406434
networkPassphrase: string,
407435
signers: string[],
408436
homeDomains: string | string[],
437+
webAuthDomain: string,
409438
): string[] {
410439
// Read the transaction which validates its structure.
411440
const { tx } = readChallengeTx(
412441
challengeTx,
413442
serverAccountID,
414443
networkPassphrase,
415444
homeDomains,
445+
webAuthDomain,
416446
);
417447

418448
// Ensure the server account ID is an address and not a seed.

0 commit comments

Comments
 (0)