Skip to content

Commit 6e0c53b

Browse files
committed
added webAuthDomain parameter and validation to SEP-10 util functions
1 parent 84d10c6 commit 6e0c53b

File tree

2 files changed

+318
-16
lines changed

2 files changed

+318
-16
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(
@@ -181,7 +192,10 @@ export namespace Utils {
181192
}
182193

183194
// verify base64
184-
if (Buffer.from(operation.value.toString(), "base64").length !== 48) {
195+
if (
196+
!operation.value ||
197+
Buffer.from(operation.value.toString(), "base64").length !== 48
198+
) {
185199
throw new InvalidSep10ChallengeError(
186200
"The transaction's operation value should be a 64 bytes base64 random string",
187201
);
@@ -228,6 +242,16 @@ export namespace Utils {
228242
"The transaction has operations that are unrecognized",
229243
);
230244
}
245+
if (
246+
op.name === "web_auth_domain" &&
247+
(!op.value || op.value.toString() !== webAuthDomain)
248+
) {
249+
throw new InvalidSep10ChallengeError(
250+
`Invalid 'web_auth_domain' value. Expected: ${webAuthDomain}; Contained: ${
251+
op.value ? op.value.toString() : op.value
252+
}`,
253+
);
254+
}
231255
}
232256

233257
return { tx: transaction, clientAccountID, matchedHomeDomain };
@@ -260,6 +284,7 @@ export namespace Utils {
260284
* @param {number} threshold The required signatures threshold for verifying this transaction.
261285
* @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.
262286
* @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().
287+
* @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().
263288
* @returns {string[]} The list of signers public keys that have signed the transaction, excluding the server account ID, given that the threshold was met.
264289
* @example
265290
*
@@ -311,6 +336,7 @@ export namespace Utils {
311336
threshold: number,
312337
signerSummary: ServerApi.AccountRecordSigners[],
313338
homeDomains: string | string[],
339+
webAuthDomain: string,
314340
): string[] {
315341
const signers = signerSummary.map((signer) => signer.key);
316342

@@ -320,6 +346,7 @@ export namespace Utils {
320346
networkPassphrase,
321347
signers,
322348
homeDomains,
349+
webAuthDomain,
323350
);
324351

325352
let weight = 0;
@@ -363,6 +390,7 @@ export namespace Utils {
363390
* @param {string} networkPassphrase The network passphrase, e.g.: 'Test SDF Network ; September 2015'.
364391
* @param {string[]} signers The signers public keys. This list should contain the public keys for all signers that have signed the transaction.
365392
* @param {string|string[]} [homeDomains] The home domain(s) that should be included in the first Manage Data operation's string key. Required in readChallengeTx().
393+
* @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().
366394
* @returns {string[]} The list of signers public keys that have signed the transaction, excluding the server account ID.
367395
* @example
368396
*
@@ -400,13 +428,15 @@ export namespace Utils {
400428
networkPassphrase: string,
401429
signers: string[],
402430
homeDomains: string | string[],
431+
webAuthDomain: string,
403432
): string[] {
404433
// Read the transaction which validates its structure.
405434
const { tx } = readChallengeTx(
406435
challengeTx,
407436
serverAccountID,
408437
networkPassphrase,
409438
homeDomains,
439+
webAuthDomain,
410440
);
411441

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

0 commit comments

Comments
 (0)