fix(auth): every call with a code after the password takes the address
Whoever guessed codes decided whether the owner was mailed (the re-review's fourth finding): the address a sign-in sent was optional, so a guesser left it out and no mail went, and a wait begun without a mail used up the one mail there was. Every call carrying a code after the password or the phrase proved (signing in, the phrase's reset, a change of password, a new phrase, deletion) now takes the account's address and the language of its mails, and is refused (wrongCredentials, as anything wrong after the password) before any code is checked when the address isn't the account's; every wait mails the owner, not only the first. The app sends the address the person typed, or for changes while signed in the one this device signed in with, and says so where it doesn't know it (addressUnknown). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
e8c4a3d472
commit
2a21672b43
2 changed files with 795 additions and 347 deletions
|
|
@ -278,8 +278,8 @@ class EndpointAccountRecovery extends _isc.EndpointRef {
|
|||
String? totpCode,
|
||||
String? recoveryCode,
|
||||
required String host,
|
||||
String? address,
|
||||
String? language,
|
||||
required String address,
|
||||
required String language,
|
||||
}) => caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||
'halkyon_base.accountRecovery',
|
||||
'resetPassword',
|
||||
|
|
@ -455,8 +455,10 @@ class EndpointPassword extends _isc.EndpointRef {
|
|||
/// Changes the caller's password to [password] (the same keys, wrapped
|
||||
/// under the new password's key on the device), with the old password's
|
||||
/// proof for [challenge] ([beginChange]) and a [totpCode] or
|
||||
/// [recoveryCode]. Every other session of theirs ends, in every service of
|
||||
/// the instance; this one stays. Refusals as `changePassword`'s.
|
||||
/// [recoveryCode], and the account's [address] as the device typed it
|
||||
/// (checked before the code; the owner is mailed in [language] should
|
||||
/// codes come to wait). Every other session of theirs ends, in every
|
||||
/// service of the instance; this one stays. Refusals as `changePassword`'s.
|
||||
_ida.Future<void> change({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData clientValue,
|
||||
|
|
@ -465,6 +467,8 @@ class EndpointPassword extends _isc.EndpointRef {
|
|||
String? recoveryCode,
|
||||
required _i95l60wq.NewPassword password,
|
||||
required String host,
|
||||
required String address,
|
||||
required String language,
|
||||
}) => caller.callServerEndpoint<void>(
|
||||
'halkyon_base.password',
|
||||
'change',
|
||||
|
|
@ -476,14 +480,17 @@ class EndpointPassword extends _isc.EndpointRef {
|
|||
'recoveryCode': recoveryCode,
|
||||
'password': password,
|
||||
'host': host,
|
||||
'address': address,
|
||||
'language': language,
|
||||
},
|
||||
);
|
||||
|
||||
/// A new recovery phrase: [recoveryKeys], the caller's keys wrapped under
|
||||
/// it on the device, replace the old wrapping, and [recoveryProofKey], the
|
||||
/// public half of its proof key, the old one, with the password's proof
|
||||
/// for [challenge] ([beginChange]) and a [totpCode] or [recoveryCode], as
|
||||
/// [change] takes. Refusals as `setRecoveryKeys`'.
|
||||
/// for [challenge] ([beginChange]) and a [totpCode] or [recoveryCode], with
|
||||
/// the account's [address] and [language], as [change] takes. Refusals as
|
||||
/// `setRecoveryKeys`'.
|
||||
_ida.Future<void> setRecoveryKeys({
|
||||
required _isc.UuidValue challenge,
|
||||
required _idt.ByteData clientValue,
|
||||
|
|
@ -493,6 +500,8 @@ class EndpointPassword extends _isc.EndpointRef {
|
|||
required _i3so7e0p.WrappedKeys recoveryKeys,
|
||||
required _idt.ByteData recoveryProofKey,
|
||||
required String host,
|
||||
required String address,
|
||||
required String language,
|
||||
}) => caller.callServerEndpoint<void>(
|
||||
'halkyon_base.password',
|
||||
'setRecoveryKeys',
|
||||
|
|
@ -505,6 +514,8 @@ class EndpointPassword extends _isc.EndpointRef {
|
|||
'recoveryKeys': recoveryKeys,
|
||||
'recoveryProofKey': recoveryProofKey,
|
||||
'host': host,
|
||||
'address': address,
|
||||
'language': language,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -550,8 +561,8 @@ class EndpointPasswordSignIn extends _isc.EndpointRef {
|
|||
_isc.UuidValue? request,
|
||||
String? code,
|
||||
required String host,
|
||||
String? address,
|
||||
String? language,
|
||||
required String address,
|
||||
required String language,
|
||||
}) => caller.callServerEndpoint<_ix90myvx.PasswordSignedIn>(
|
||||
'halkyon_base.passwordSignIn',
|
||||
'complete',
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ abstract class DeletionProof
|
|||
this.totpCode,
|
||||
this.recoveryCode,
|
||||
required this.host,
|
||||
required this.address,
|
||||
required this.language,
|
||||
});
|
||||
|
||||
factory DeletionProof({
|
||||
|
|
@ -36,6 +38,8 @@ abstract class DeletionProof
|
|||
String? totpCode,
|
||||
String? recoveryCode,
|
||||
required String host,
|
||||
required String address,
|
||||
required String language,
|
||||
}) = _DeletionProofImpl;
|
||||
|
||||
factory DeletionProof.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
|
|
@ -52,6 +56,8 @@ abstract class DeletionProof
|
|||
totpCode: jsonSerialization['totpCode'] as String?,
|
||||
recoveryCode: jsonSerialization['recoveryCode'] as String?,
|
||||
host: jsonSerialization['host'] as String,
|
||||
address: jsonSerialization['address'] as String,
|
||||
language: jsonSerialization['language'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +75,13 @@ abstract class DeletionProof
|
|||
/// checks it is its own before the register binds the proof to it.
|
||||
String host;
|
||||
|
||||
/// The account's address as the device typed it, and the language its
|
||||
/// mails are worded in: checked before the code, so the owner is mailed
|
||||
/// should codes come to wait (the re-review's fourth finding).
|
||||
String address;
|
||||
|
||||
String language;
|
||||
|
||||
/// Returns a shallow copy of this [DeletionProof]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
|
|
@ -79,6 +92,8 @@ abstract class DeletionProof
|
|||
String? totpCode,
|
||||
String? recoveryCode,
|
||||
String? host,
|
||||
String? address,
|
||||
String? language,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
@ -90,6 +105,8 @@ abstract class DeletionProof
|
|||
if (totpCode != null) 'totpCode': totpCode,
|
||||
if (recoveryCode != null) 'recoveryCode': recoveryCode,
|
||||
'host': host,
|
||||
'address': address,
|
||||
'language': language,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +120,8 @@ abstract class DeletionProof
|
|||
if (totpCode != null) 'totpCode': totpCode,
|
||||
if (recoveryCode != null) 'recoveryCode': recoveryCode,
|
||||
'host': host,
|
||||
'address': address,
|
||||
'language': language,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -122,6 +141,8 @@ class _DeletionProofImpl extends DeletionProof {
|
|||
String? totpCode,
|
||||
String? recoveryCode,
|
||||
required String host,
|
||||
required String address,
|
||||
required String language,
|
||||
}) : super._(
|
||||
challenge: challenge,
|
||||
clientValue: clientValue,
|
||||
|
|
@ -129,6 +150,8 @@ class _DeletionProofImpl extends DeletionProof {
|
|||
totpCode: totpCode,
|
||||
recoveryCode: recoveryCode,
|
||||
host: host,
|
||||
address: address,
|
||||
language: language,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [DeletionProof]
|
||||
|
|
@ -142,6 +165,8 @@ class _DeletionProofImpl extends DeletionProof {
|
|||
Object? totpCode = _Undefined,
|
||||
Object? recoveryCode = _Undefined,
|
||||
String? host,
|
||||
String? address,
|
||||
String? language,
|
||||
}) {
|
||||
return DeletionProof(
|
||||
challenge: challenge ?? this.challenge,
|
||||
|
|
@ -150,6 +175,8 @@ class _DeletionProofImpl extends DeletionProof {
|
|||
totpCode: totpCode is String? ? totpCode : this.totpCode,
|
||||
recoveryCode: recoveryCode is String? ? recoveryCode : this.recoveryCode,
|
||||
host: host ?? this.host,
|
||||
address: address ?? this.address,
|
||||
language: language ?? this.language,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue