fix(auth)!: proofs are bound to the instance the device addresses
Nothing tied a sign-in's proof to the instance it was made for: an instance a person was lured into adding could pass A, M1 and the code on to the real register and get a session there, and pass a phrase's proof on with a password of its own in place of the person's (the second reading's M6). SRP's identity is now a label, the challenge's ID and the host the device addressed (passwordIdentity, in halkyon_base_client and halkyon_base_server alike), and the phrase's proof signs that host, what it is for (an authenticator's reset or a new password) and the new password's digest (key proof v2). Every proving call carries the host; in production it must be the server's apiServer.publicHost (otherwise otherInstance, which the app shows as an instance it can't trust), in development any; a member forwards its own. The tests prove that a relayed sign-in, a proof for another host or purpose, and a swapped password are refused, nothing changing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
009970faab
commit
dab2c80524
1 changed files with 966 additions and 137 deletions
|
|
@ -236,6 +236,7 @@ Future<Map<String, Object?>?> _answer(
|
|||
recoveryCode: arguments.optionalString('recoveryCode'),
|
||||
request: arguments.optionalId('request'),
|
||||
code: arguments.optionalString('code'),
|
||||
host: arguments.string('host'),
|
||||
);
|
||||
return {'proof': proof.toJson()};
|
||||
case RegisterOperation.signUpWithCode:
|
||||
|
|
@ -300,6 +301,7 @@ Future<Map<String, Object?>?> _answer(
|
|||
code: arguments.optionalString('code'),
|
||||
keyChallenge: arguments.optionalId('keyChallenge'),
|
||||
signature: arguments.optionalBytes('signature'),
|
||||
host: arguments.string('host'),
|
||||
);
|
||||
return {'pending': pending.toJson()};
|
||||
case RegisterOperation.beginKeyProof:
|
||||
|
|
@ -317,6 +319,7 @@ Future<Map<String, Object?>?> _answer(
|
|||
password: arguments.model('password', NewPassword.fromJson),
|
||||
totpCode: arguments.optionalString('totpCode'),
|
||||
recoveryCode: arguments.optionalString('recoveryCode'),
|
||||
host: arguments.string('host'),
|
||||
);
|
||||
return _sessionsEnded(ended);
|
||||
case RegisterOperation.startAccountReset:
|
||||
|
|
@ -354,6 +357,7 @@ Future<Map<String, Object?>?> _answer(
|
|||
recoveryCode: arguments.optionalString('recoveryCode'),
|
||||
password: arguments.model('password', NewPassword.fromJson),
|
||||
keepSession: arguments.optionalId('keepSession'),
|
||||
host: arguments.string('host'),
|
||||
);
|
||||
return const {};
|
||||
case RegisterOperation.setRecoveryKeys:
|
||||
|
|
@ -367,6 +371,7 @@ Future<Map<String, Object?>?> _answer(
|
|||
recoveryCode: arguments.optionalString('recoveryCode'),
|
||||
recoveryKeys: arguments.model('recoveryKeys', WrappedKeys.fromJson),
|
||||
recoveryProofKey: arguments.bytes('recoveryProofKey'),
|
||||
host: arguments.string('host'),
|
||||
);
|
||||
return const {};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue