Skip to content

Commit

Permalink
Fix CAIP-122 verification (#193)
Browse files Browse the repository at this point in the history
# Problem

Various issues found when testing the CAIP-122 signature verification

# Solution

1. Fixed a few SIWA references
2. Fixed the signature verification to allow for the hashed version in
addition to the pure string version.
3. `publicKey` should be `Sr` not `SR` (verification doesn't care
however)
4. Added additional test generated from FA code
5. Match address encoding before comparing for the CAIP-122 payload
6. Fix address extraction
7. Fix expired parsing
  • Loading branch information
wilwade authored Oct 10, 2024
1 parent 87b24c6 commit 281782d
Show file tree
Hide file tree
Showing 18 changed files with 132 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Looking for SIWF v1 resources? [Go to the `v1` branch](https://github.com/Projec

## 💻 Prerequisites<a name="-prerequisites"></a>

Using Sign In With Access requires:
Using Sign In With Frequency requires:

- Frequency Provider setup
- Frequency Node RPC access
Expand Down
2 changes: 1 addition & 1 deletion docs/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ authors = ["Project Liberty Labs"]
language = "en"
multilingual = false
src = "src"
title = "Sign In With Access"
title = "Sign In With Frequency"

[preprocessor.local]
command = "node preprocessor.mjs"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/DataStructures/Request.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
```json
{
"signedRequest": "eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNSMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweGU2NjBiZjA4MTQxNzI3OGE4YzYxOTkwZGM3N2JjZTZjOTQxZWU3ZjM0ZDMwZGRiYjVjYzdjMzk2NmE0MDhjMDA3YmU1MGYyNjBkMzc2Y2I3ZjAyYzRiOGI2ZmFjZTkzOTJkZjZhNzE4MTYzZmJmZDI2YTNkNWQwYzA4NzYwNDgwIn0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0",
"signedRequest": "eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNyMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweDNlMTdhYzM3Yzk3ZWE3M2E3YzM1ZjBjYTJkZTcxYmY3MmE5NjlkYjhiNjQyYzU3ZTI2N2Q4N2Q1OTA3ZGM4MzVmYTJjODI4MTdlODA2YTQ5NGIyY2E5Y2U5MjJmNDM1NDY4M2U4YzAxMzY5NTNlMGZlNWExODJkMzU0NjQ2Yzg4In0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0",
"mode": "dark"
}
```
2 changes: 1 addition & 1 deletion docs/src/DataStructures/RequestUrl.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
```json
"https://testnet.frequencyaccess.com/siwa/start?signedRequest=eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNSMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweGU2NjBiZjA4MTQxNzI3OGE4YzYxOTkwZGM3N2JjZTZjOTQxZWU3ZjM0ZDMwZGRiYjVjYzdjMzk2NmE0MDhjMDA3YmU1MGYyNjBkMzc2Y2I3ZjAyYzRiOGI2ZmFjZTkzOTJkZjZhNzE4MTYzZmJmZDI2YTNkNWQwYzA4NzYwNDgwIn0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0&mode=dark"
"https://testnet.frequencyaccess.com/siwa/start?signedRequest=eyJyZXF1ZXN0ZWRTaWduYXR1cmVzIjp7InB1YmxpY0tleSI6eyJlbmNvZGVkVmFsdWUiOiJmNmNMNHdxMUhVTngxMVRjdmRBQk5mOVVOWFhveUg0N21WVXdUNTl0elNGUlc4eURIIiwiZW5jb2RpbmciOiJiYXNlNTgiLCJmb3JtYXQiOiJzczU4IiwidHlwZSI6IlNyMjU1MTkifSwic2lnbmF0dXJlIjp7ImFsZ28iOiJTUjI1NTE5IiwiZW5jb2RpbmciOiJiYXNlMTYiLCJlbmNvZGVkVmFsdWUiOiIweDNlMTdhYzM3Yzk3ZWE3M2E3YzM1ZjBjYTJkZTcxYmY3MmE5NjlkYjhiNjQyYzU3ZTI2N2Q4N2Q1OTA3ZGM4MzVmYTJjODI4MTdlODA2YTQ5NGIyY2E5Y2U5MjJmNDM1NDY4M2U4YzAxMzY5NTNlMGZlNWExODJkMzU0NjQ2Yzg4In0sInBheWxvYWQiOnsiY2FsbGJhY2siOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJwZXJtaXNzaW9ucyI6WzUsNyw4LDksMTBdfX0sInJlcXVlc3RlZENyZWRlbnRpYWxzIjpbeyJ0eXBlIjoiVmVyaWZpZWRHcmFwaEtleUNyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFtZHZteGQ1NHp2ZTVraWZ5Y2dzZHRvYWhzNWVjZjRoYWwydHMzZWV4a2dvY3ljNW9jYTJ5Il19LHsiYW55T2YiOlt7InR5cGUiOiJWZXJpZmllZEVtYWlsQWRkcmVzc0NyZWRlbnRpYWwiLCJoYXNoIjpbImJjaXFlNHFvY3poZnRpY2k0ZHpmdmZiZWw3Zm80aDRzcjVncmNvM29vdnd5azZ5NHluZjQ0dHNpIl19LHsidHlwZSI6IlZlcmlmaWVkUGhvbmVOdW1iZXJDcmVkZW50aWFsIiwiaGFzaCI6WyJiY2lxanNwbmJ3cGMzd2p4NGZld2NlazVkYXlzZGpwYmY1eGppbXo1d251NXVqN2UzdnUydXducSJdfV19XX0&mode=dark"
```
2 changes: 1 addition & 1 deletion docs/src/DataStructures/Response-LoginOnly.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
"encoding": "base58",
"format": "ss58",
"type": "SR25519"
"type": "Sr25519"
},
"payloads": [
{
Expand Down
2 changes: 1 addition & 1 deletion docs/src/DataStructures/Response-NewProvider.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
"encoding": "base58",
"format": "ss58",
"type": "SR25519"
"type": "Sr25519"
},
"payloads": [
{
Expand Down
2 changes: 1 addition & 1 deletion docs/src/DataStructures/Response-NewUser.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"encodedValue": "f6akufkq9Lex6rT8RCEDRuoZQRgo5pWiRzeo81nmKNGWGNJdJ",
"encoding": "base58",
"format": "ss58",
"type": "SR25519"
"type": "Sr25519"
},
"payloads": [
{
Expand Down
2 changes: 1 addition & 1 deletion docs/src/DataStructures/SignedRequest.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"encodedValue": "f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH",
"encoding": "base58",
"format": "ss58",
"type": "SR25519"
"type": "Sr25519"
},
"signature": {
"algo": "SR25519",
Expand Down
8 changes: 4 additions & 4 deletions libraries/js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions libraries/js/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@projectlibertylabs/siwf",
"version": "0.0.0",
"description": "Sign In With Access Utility Library",
"description": "Sign In With Frequency Utility Library",
"main": "src/index.ts",
"type": "module",
"scripts": {
Expand Down Expand Up @@ -38,7 +38,7 @@
"eslint": "^9.12.0",
"prettier": "3.3.3",
"tsup": "^8.3.0",
"typescript": "^5.6.2",
"typescript": "^5.6.3",
"typescript-eslint": "^8.8.1",
"vitest": "^2.1.2"
},
Expand Down
2 changes: 1 addition & 1 deletion libraries/js/src/mocks/generate-data-structures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function exampleSignedRequest(): SiwfSignedRequest {
encodedValue: 'f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH',
encoding: 'base58',
format: 'ss58',
type: 'SR25519',
type: 'Sr25519',
},
signature: {
algo: 'SR25519',
Expand Down
2 changes: 1 addition & 1 deletion libraries/js/src/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const ExampleUserPublicKey: SiwfPublicKey = {
encodedValue: ExampleUserKey.public,
encoding: 'base58',
format: 'ss58',
type: 'SR25519',
type: 'Sr25519',
};

// NOTICE: These mocks ALSO generate the `docs/DataStructure/[].md` files. Take care changing them
Expand Down
37 changes: 37 additions & 0 deletions libraries/js/src/payloads.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,43 @@ beforeAll(async () => {

describe('validatePayloads', () => {
describe('Login Related Payloads', () => {
it('Can verify Login Payload generated from FA using hash', async () => {
await expect(
validatePayloads(
{
userPublicKey: {
encodedValue: '5HYHZ8e8kyLEBuEbsFa2bwKYbVSMgaUhymfRVgH7CuM4VCHv',
encoding: 'base58',
format: 'ss58',
type: 'Sr25519',
},
payloads: [
{
signature: {
algo: 'SR25519',
encoding: 'base16',
encodedValue:
'0xa6da6fa47076fbf7b0aac57a246041a777c867d15571dad1fdd014f4f0477a7ca5a92f5c952a740791b4e360b2320e94a3f20e733e821ac4242b1de72fbc6a80',
},
type: 'login',
payload: {
message: `localhost wants you to sign in with your Frequency account:
frequency:dev:5HYHZ8e8kyLEBuEbsFa2bwKYbVSMgaUhymfRVgH7CuM4VCHv
URI: http://localhost:3030/login/callback
Version: 1
Nonce: d83eba8e-05a3-4c9a-9901-a976e67278b6
Chain ID: frequency:dev
Issued At: 2024-10-10T18:40:37.344099626Z`,
},
},
],
},
'localhost'
)
).resolves.toBeUndefined();
});

it('Can verify a Generated Login Payload', async () => {
await expect(
validatePayloads(
Expand Down
92 changes: 68 additions & 24 deletions libraries/js/src/payloads.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { signatureVerify, cryptoWaitReady } from '@polkadot/util-crypto';
import { signatureVerify, cryptoWaitReady, decodeAddress, blake2AsU8a } from '@polkadot/util-crypto';
import { hexToU8a, stringToU8a, u8aToHex, u8aWrapBytes } from '@polkadot/util';
import {
isPayloadAddProvider,
isPayloadClaimHandle,
Expand All @@ -20,14 +21,17 @@ interface SiwxMessage {
nonce: string;
expired: boolean;
issuedAt: Date;
expirationTime: Date;
expirationTime?: Date;
uri: string;
}

function parseMessage(message: string): SiwxMessage {
const msgSplit = message.split('\n');
const domain = (msgSplit[0] || '').split(' ')[0] || '';
const address = msgSplit[1] || '';

const addressLines = (msgSplit[1] || '').split(':');
const address = addressLines[addressLines.length - 1] || '';

const nonceLine = msgSplit.find((x) => x.startsWith('Nonce: '));
const nonce = nonceLine ? nonceLine.replace('Nonce: ', '') : '';

Expand All @@ -36,8 +40,8 @@ function parseMessage(message: string): SiwxMessage {

const expiredLine = msgSplit.find((x) => x.startsWith('Expiration Time: '));
const expiredString = expiredLine ? expiredLine.replace('Expiration Time: ', '') : '';
const expirationTime = new Date(expiredString);
const expired = +expirationTime < Date.now();
const expirationTime = expiredString ? new Date(expiredString) : undefined;
const expired = expirationTime ? +expirationTime < Date.now() : false;

const issuedLine = msgSplit.find((x) => x.startsWith('Issued At: '));
const issuedString = issuedLine ? issuedLine.replace('Issued At: ', '') : '';
Expand All @@ -54,6 +58,36 @@ function parseMessage(message: string): SiwxMessage {
};
}

// SIWA is switching away from this, but we should still support it for now
function verifySignatureHashMaybeWrapped(publicKey: string, signature: string, message: Uint8Array): boolean {
const unwrappedSigned = message.length > 256 ? blake2AsU8a(message) : message;

const unwrappedVerifyResult = signatureVerify(unwrappedSigned, signature, publicKey);
if (unwrappedVerifyResult.isValid) {
return true;
}

// Support both wrapped and unwrapped signatures
const wrappedSignedBytes = u8aWrapBytes(message);
const wrappedSigned = wrappedSignedBytes.length > 256 ? blake2AsU8a(wrappedSignedBytes) : wrappedSignedBytes;
const wrappedVerifyResult = signatureVerify(wrappedSigned, signature, publicKey);

return wrappedVerifyResult.isValid;
}

function verifySignatureMaybeWrapped(publicKey: string, signature: string, message: Uint8Array): boolean {
const unwrappedVerifyResult = signatureVerify(message, signature, publicKey);
if (unwrappedVerifyResult.isValid) {
return true;
}

// Support both wrapped and unwrapped signatures
const wrappedSignedBytes = u8aWrapBytes(message);
const wrappedVerifyResult = signatureVerify(wrappedSignedBytes, signature, publicKey);

return wrappedVerifyResult.isValid || verifySignatureHashMaybeWrapped(publicKey, signature, message);
}

function expect(test: boolean, errorMessage: string) {
if (!test) throw new Error(errorMessage);
}
Expand All @@ -64,31 +98,41 @@ function validateLoginPayload(
loginMsgDomain: string
): void {
// Check that the userPublicKey signed the message
const signedMessage = payload.payload.message;
const verifyResult = signatureVerify(signedMessage, payload.signature.encodedValue, userPublicKey.encodedValue);

expect(verifyResult.isValid, 'Login message signature failed');
expect(
verifySignatureMaybeWrapped(
userPublicKey.encodedValue,
payload.signature.encodedValue,
stringToU8a(payload.payload.message)
),
'Login message signature failed'
);

// Validate the message contents
const msg = parseMessage(signedMessage);
const msg = parseMessage(payload.payload.message);
expect(
msg.domain === loginMsgDomain,
`Message does not match expected domain. Message: ${msg.domain} Expected: ${loginMsgDomain}`
);
expect(
msg.address === userPublicKey.encodedValue,
`Message does not match expected user public key value. Message: ${msg.address}`
);
// Match address encoding before comparing
// decodeAddress will throw if it cannot decode meaning bad address
try {
const msgAddr = decodeAddress(msg.address);
const userAddr = decodeAddress(userPublicKey.encodedValue);
// Hex for easy comparison
expect(u8aToHex(msgAddr) === u8aToHex(userAddr), 'Address mismatch');
} catch (_e) {
throw new Error(
`Invalid address or message does not match bytes of expected user public key value. Message: ${msg.address} User: ${userPublicKey.encodedValue}`
);
}

expect(
!msg.expired,
`Message does not match expected user public key value. Message: ${msg.expirationTime.toISOString()}`
);
if (msg.expirationTime) {
expect(!msg.expired, `Message has expired. Message: ${msg.expirationTime.toISOString()}`);
}
}

function validateSignature(key: string, signature: string, message: string) {
const verifyResult = signatureVerify(message, signature, key);
expect(verifyResult.isValid, 'Payload signature failed');
function validateExtrinsicPayloadSignature(key: string, signature: string, message: string) {
expect(verifySignatureMaybeWrapped(key, signature, hexToU8a(message)), 'Payload signature failed');
}

export async function validatePayloads(response: SiwfResponse, loginMsgDomain: string): Promise<void> {
Expand All @@ -99,19 +143,19 @@ export async function validatePayloads(response: SiwfResponse, loginMsgDomain: s
case isPayloadLogin(payload):
return validateLoginPayload(payload, response.userPublicKey, loginMsgDomain);
case isPayloadAddProvider(payload):
return validateSignature(
return validateExtrinsicPayloadSignature(
response.userPublicKey.encodedValue,
payload.signature.encodedValue,
serializeAddProviderPayloadHex(payload.payload)
);
case isPayloadClaimHandle(payload):
return validateSignature(
return validateExtrinsicPayloadSignature(
response.userPublicKey.encodedValue,
payload.signature.encodedValue,
serializeClaimHandlePayloadHex(payload.payload)
);
case isPayloadItemActions(payload):
return validateSignature(
return validateExtrinsicPayloadSignature(
response.userPublicKey.encodedValue,
payload.signature.encodedValue,
serializeItemActionsPayloadHex(payload.payload)
Expand Down
4 changes: 2 additions & 2 deletions libraries/js/src/request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('request', () => {
encodedValue: 'f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH',
encoding: 'base58',
format: 'ss58',
type: 'SR25519',
type: 'Sr25519',
},
signature: {
algo: 'SR25519',
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('request', () => {
encodedValue: 'f6cL4wq1HUNx11TcvdABNf9UNXXoyH47mVUwT59tzSFRW8yDH',
encoding: 'base58',
format: 'ss58',
type: 'SR25519',
type: 'Sr25519',
},
},
});
Expand Down
2 changes: 1 addition & 1 deletion libraries/js/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export function buildSignedRequest(
encodedValue: encodeAddress(signerPublicKey, 90),
encoding: 'base58',
format: 'ss58',
type: 'SR25519',
type: 'Sr25519',
},
signature: {
algo: 'SR25519',
Expand Down
7 changes: 7 additions & 0 deletions libraries/js/src/response.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,11 @@ describe('validateSiwfResponse', () => {
'Response failed to correctly parse or invalid content: {"foo":"bad"}'
);
});

it('throws on a bad domain', async () => {
const example = await ExampleLogin();
await expect(validateSiwfResponse(base64url(JSON.stringify(example)), 'bad.example.xyz')).to.rejects.toThrowError(
'Message does not match expected domain. Message: localhost Expected: bad.example.xyz'
);
});
});
2 changes: 1 addition & 1 deletion libraries/js/src/types/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface SiwfPublicKey {
encodedValue: string;
encoding: 'base58';
format: 'ss58';
type: 'SR25519';
type: 'Sr25519';
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down

0 comments on commit 281782d

Please sign in to comment.