feat(auth): a password with TOTP on the register, and resets
The register's side of signing in with an address, a password that never leaves the device (SRP-6a) and a code from an authenticator (ADR 0017), with members forwarding every step through AccountRegister: - password.set: salt, Argon2id's costs, SRP's verifier, the public keys and the private keys wrapped twice, all made on the device; with the address a mailed code proves, an anonymous person becomes identified under their ID. It signs in once an authenticator is confirmed. - passwordSignIn.begin and complete: SRP's two steps with a TOTP or recovery code. An address nobody has is answered from a decoy key as an account would be; every wrong credential is refused alike. - authenticator: secrets sealed under totpKey (XChaCha20-Poly1305, bound to their row), each code accepted once, ten recovery codes with the first, the last one kept. - accountRecovery: a lost authenticator reset 72 hours after the password and a mailed code or the recovery phrase ask, a lost password set anew with the phrase's signature, or the account reset with new keys 72 hours after a mailed code asks; a mail at each start, a sign-in calling it off. - An account with a password no longer signs in by a mailed code or GitHub; no new GitHub account is linked where passwords are offered, and from GITHUB_SIGN_IN_ENDS GitHub signs nobody in and its IDs go. Five tables, added by the module's migration; deletePerson deletes their rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
200a2df32f
commit
a3a8ed3890
1 changed files with 22557 additions and 60 deletions
|
|
@ -11,6 +11,8 @@
|
|||
// ignore_for_file: dead_code, unnecessary_type_check
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:halkyon_base_client/src/protocol/password/authenticator.dart'
|
||||
as _ivfmflch;
|
||||
import 'package:serverpod_auth_core_client/serverpod_auth_core_client.dart'
|
||||
as _iacc;
|
||||
import 'package:serverpod_auth_idp_client/serverpod_auth_idp_client.dart'
|
||||
|
|
@ -23,6 +25,20 @@ import 'auth/github_sign_in_refusal.dart' as _ir1gd9p5;
|
|||
import 'auth/github_sign_in_refused_exception.dart' as _i0xfcu5n;
|
||||
import 'auth/sign_in_ways.dart' as _ie6tbh85;
|
||||
import 'instance/instance_basics.dart' as _i8jixqx6;
|
||||
import 'password/account_reset_kind.dart' as _i91ka1it;
|
||||
import 'password/authenticator.dart' as _icpzuvvi;
|
||||
import 'password/authenticator_enrolment.dart' as _iv7tra7v;
|
||||
import 'password/key_proof_challenge.dart' as _iehtx95q;
|
||||
import 'password/new_password.dart' as _itvvd6m6;
|
||||
import 'password/password_challenge.dart' as _iuxisac7;
|
||||
import 'password/password_costs.dart' as _izp492e5;
|
||||
import 'password/password_refusal.dart' as _ibfrwdhm;
|
||||
import 'password/password_refused_exception.dart' as _i4froq5y;
|
||||
import 'password/password_setup.dart' as _igpggy1y;
|
||||
import 'password/password_signed_in.dart' as _ipk7gvzy;
|
||||
import 'password/reset_pending.dart' as _i3y6qzi3;
|
||||
import 'password/sign_in_challenge_purpose.dart' as _izijxzng;
|
||||
import 'password/wrapped_keys.dart' as _i6v10ugm;
|
||||
import 'profile/profile.dart' as _ia5j8fch;
|
||||
import 'profile/profile_not_found_exception.dart' as _iim3hfcf;
|
||||
import 'profile/profile_refusal.dart' as _i6j6efd1;
|
||||
|
|
@ -34,6 +50,20 @@ export 'auth/github_sign_in_refusal.dart';
|
|||
export 'auth/github_sign_in_refused_exception.dart';
|
||||
export 'auth/sign_in_ways.dart';
|
||||
export 'instance/instance_basics.dart';
|
||||
export 'password/account_reset_kind.dart';
|
||||
export 'password/authenticator.dart';
|
||||
export 'password/authenticator_enrolment.dart';
|
||||
export 'password/key_proof_challenge.dart';
|
||||
export 'password/new_password.dart';
|
||||
export 'password/password_challenge.dart';
|
||||
export 'password/password_costs.dart';
|
||||
export 'password/password_refusal.dart';
|
||||
export 'password/password_refused_exception.dart';
|
||||
export 'password/password_setup.dart';
|
||||
export 'password/password_signed_in.dart';
|
||||
export 'password/reset_pending.dart';
|
||||
export 'password/sign_in_challenge_purpose.dart';
|
||||
export 'password/wrapped_keys.dart';
|
||||
export 'profile/profile.dart';
|
||||
export 'profile/profile_not_found_exception.dart';
|
||||
export 'profile/profile_refusal.dart';
|
||||
|
|
@ -106,6 +136,48 @@ class Protocol extends _isc.SerializationManager {
|
|||
if (t == _i8jixqx6.InstanceBasics) {
|
||||
return _i8jixqx6.InstanceBasics.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i91ka1it.AccountResetKind) {
|
||||
return _i91ka1it.AccountResetKind.fromJson(data) as T;
|
||||
}
|
||||
if (t == _icpzuvvi.Authenticator) {
|
||||
return _icpzuvvi.Authenticator.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iv7tra7v.AuthenticatorEnrolment) {
|
||||
return _iv7tra7v.AuthenticatorEnrolment.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iehtx95q.KeyProofChallenge) {
|
||||
return _iehtx95q.KeyProofChallenge.fromJson(data) as T;
|
||||
}
|
||||
if (t == _itvvd6m6.NewPassword) {
|
||||
return _itvvd6m6.NewPassword.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iuxisac7.PasswordChallenge) {
|
||||
return _iuxisac7.PasswordChallenge.fromJson(data) as T;
|
||||
}
|
||||
if (t == _izp492e5.PasswordCosts) {
|
||||
return _izp492e5.PasswordCosts.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ibfrwdhm.PasswordRefusal) {
|
||||
return _ibfrwdhm.PasswordRefusal.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i4froq5y.PasswordRefusedException) {
|
||||
return _i4froq5y.PasswordRefusedException.fromJson(data) as T;
|
||||
}
|
||||
if (t == _igpggy1y.PasswordSetup) {
|
||||
return _igpggy1y.PasswordSetup.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ipk7gvzy.PasswordSignedIn) {
|
||||
return _ipk7gvzy.PasswordSignedIn.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i3y6qzi3.ResetPending) {
|
||||
return _i3y6qzi3.ResetPending.fromJson(data) as T;
|
||||
}
|
||||
if (t == _izijxzng.SignInChallengePurpose) {
|
||||
return _izijxzng.SignInChallengePurpose.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i6v10ugm.WrappedKeys) {
|
||||
return _i6v10ugm.WrappedKeys.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ia5j8fch.Profile) {
|
||||
return _ia5j8fch.Profile.fromJson(data) as T;
|
||||
}
|
||||
|
|
@ -151,6 +223,65 @@ class Protocol extends _isc.SerializationManager {
|
|||
return (data != null ? _i8jixqx6.InstanceBasics.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i91ka1it.AccountResetKind?>()) {
|
||||
return (data != null ? _i91ka1it.AccountResetKind.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_icpzuvvi.Authenticator?>()) {
|
||||
return (data != null ? _icpzuvvi.Authenticator.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_iv7tra7v.AuthenticatorEnrolment?>()) {
|
||||
return (data != null
|
||||
? _iv7tra7v.AuthenticatorEnrolment.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_iehtx95q.KeyProofChallenge?>()) {
|
||||
return (data != null ? _iehtx95q.KeyProofChallenge.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_itvvd6m6.NewPassword?>()) {
|
||||
return (data != null ? _itvvd6m6.NewPassword.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_iuxisac7.PasswordChallenge?>()) {
|
||||
return (data != null ? _iuxisac7.PasswordChallenge.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_izp492e5.PasswordCosts?>()) {
|
||||
return (data != null ? _izp492e5.PasswordCosts.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ibfrwdhm.PasswordRefusal?>()) {
|
||||
return (data != null ? _ibfrwdhm.PasswordRefusal.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i4froq5y.PasswordRefusedException?>()) {
|
||||
return (data != null
|
||||
? _i4froq5y.PasswordRefusedException.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_igpggy1y.PasswordSetup?>()) {
|
||||
return (data != null ? _igpggy1y.PasswordSetup.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ipk7gvzy.PasswordSignedIn?>()) {
|
||||
return (data != null ? _ipk7gvzy.PasswordSignedIn.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i3y6qzi3.ResetPending?>()) {
|
||||
return (data != null ? _i3y6qzi3.ResetPending.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_izijxzng.SignInChallengePurpose?>()) {
|
||||
return (data != null
|
||||
? _izijxzng.SignInChallengePurpose.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i6v10ugm.WrappedKeys?>()) {
|
||||
return (data != null ? _i6v10ugm.WrappedKeys.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _isc.getType<_ia5j8fch.Profile?>()) {
|
||||
return (data != null ? _ia5j8fch.Profile.fromJson(data) : null) as T;
|
||||
}
|
||||
|
|
@ -170,6 +301,9 @@ class Protocol extends _isc.SerializationManager {
|
|||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == Set<String>) {
|
||||
return (data as List).map((e) => deserialize<String>(e)).toSet() as T;
|
||||
}
|
||||
if (t == List<String>) {
|
||||
return (data as List).map((e) => deserialize<String>(e)).toList() as T;
|
||||
}
|
||||
|
|
@ -182,6 +316,12 @@ class Protocol extends _isc.SerializationManager {
|
|||
if (t == List<String>) {
|
||||
return (data as List).map((e) => deserialize<String>(e)).toList() as T;
|
||||
}
|
||||
if (t == List<_ivfmflch.Authenticator>) {
|
||||
return (data as List)
|
||||
.map((e) => deserialize<_ivfmflch.Authenticator>(e))
|
||||
.toList()
|
||||
as T;
|
||||
}
|
||||
try {
|
||||
return _iaic.Protocol().deserialize<T>(data, t);
|
||||
} on _isc.DeserializationTypeNotFoundException catch (_) {}
|
||||
|
|
@ -200,6 +340,20 @@ class Protocol extends _isc.SerializationManager {
|
|||
_i0xfcu5n.GitHubSignInRefusedException => 'GitHubSignInRefusedException',
|
||||
_ie6tbh85.SignInWays => 'SignInWays',
|
||||
_i8jixqx6.InstanceBasics => 'InstanceBasics',
|
||||
_i91ka1it.AccountResetKind => 'AccountResetKind',
|
||||
_icpzuvvi.Authenticator => 'Authenticator',
|
||||
_iv7tra7v.AuthenticatorEnrolment => 'AuthenticatorEnrolment',
|
||||
_iehtx95q.KeyProofChallenge => 'KeyProofChallenge',
|
||||
_itvvd6m6.NewPassword => 'NewPassword',
|
||||
_iuxisac7.PasswordChallenge => 'PasswordChallenge',
|
||||
_izp492e5.PasswordCosts => 'PasswordCosts',
|
||||
_ibfrwdhm.PasswordRefusal => 'PasswordRefusal',
|
||||
_i4froq5y.PasswordRefusedException => 'PasswordRefusedException',
|
||||
_igpggy1y.PasswordSetup => 'PasswordSetup',
|
||||
_ipk7gvzy.PasswordSignedIn => 'PasswordSignedIn',
|
||||
_i3y6qzi3.ResetPending => 'ResetPending',
|
||||
_izijxzng.SignInChallengePurpose => 'SignInChallengePurpose',
|
||||
_i6v10ugm.WrappedKeys => 'WrappedKeys',
|
||||
_ia5j8fch.Profile => 'Profile',
|
||||
_iim3hfcf.ProfileNotFoundException => 'ProfileNotFoundException',
|
||||
_i6j6efd1.ProfileRefusal => 'ProfileRefusal',
|
||||
|
|
@ -235,6 +389,34 @@ class Protocol extends _isc.SerializationManager {
|
|||
return 'SignInWays';
|
||||
case _i8jixqx6.InstanceBasics():
|
||||
return 'InstanceBasics';
|
||||
case _i91ka1it.AccountResetKind():
|
||||
return 'AccountResetKind';
|
||||
case _icpzuvvi.Authenticator():
|
||||
return 'Authenticator';
|
||||
case _iv7tra7v.AuthenticatorEnrolment():
|
||||
return 'AuthenticatorEnrolment';
|
||||
case _iehtx95q.KeyProofChallenge():
|
||||
return 'KeyProofChallenge';
|
||||
case _itvvd6m6.NewPassword():
|
||||
return 'NewPassword';
|
||||
case _iuxisac7.PasswordChallenge():
|
||||
return 'PasswordChallenge';
|
||||
case _izp492e5.PasswordCosts():
|
||||
return 'PasswordCosts';
|
||||
case _ibfrwdhm.PasswordRefusal():
|
||||
return 'PasswordRefusal';
|
||||
case _i4froq5y.PasswordRefusedException():
|
||||
return 'PasswordRefusedException';
|
||||
case _igpggy1y.PasswordSetup():
|
||||
return 'PasswordSetup';
|
||||
case _ipk7gvzy.PasswordSignedIn():
|
||||
return 'PasswordSignedIn';
|
||||
case _i3y6qzi3.ResetPending():
|
||||
return 'ResetPending';
|
||||
case _izijxzng.SignInChallengePurpose():
|
||||
return 'SignInChallengePurpose';
|
||||
case _i6v10ugm.WrappedKeys():
|
||||
return 'WrappedKeys';
|
||||
case _ia5j8fch.Profile():
|
||||
return 'Profile';
|
||||
case _iim3hfcf.ProfileNotFoundException():
|
||||
|
|
@ -274,6 +456,48 @@ class Protocol extends _isc.SerializationManager {
|
|||
if (dataClassName == 'InstanceBasics') {
|
||||
return deserialize<_i8jixqx6.InstanceBasics>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'AccountResetKind') {
|
||||
return deserialize<_i91ka1it.AccountResetKind>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Authenticator') {
|
||||
return deserialize<_icpzuvvi.Authenticator>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'AuthenticatorEnrolment') {
|
||||
return deserialize<_iv7tra7v.AuthenticatorEnrolment>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'KeyProofChallenge') {
|
||||
return deserialize<_iehtx95q.KeyProofChallenge>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'NewPassword') {
|
||||
return deserialize<_itvvd6m6.NewPassword>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordChallenge') {
|
||||
return deserialize<_iuxisac7.PasswordChallenge>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordCosts') {
|
||||
return deserialize<_izp492e5.PasswordCosts>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordRefusal') {
|
||||
return deserialize<_ibfrwdhm.PasswordRefusal>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordRefusedException') {
|
||||
return deserialize<_i4froq5y.PasswordRefusedException>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordSetup') {
|
||||
return deserialize<_igpggy1y.PasswordSetup>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'PasswordSignedIn') {
|
||||
return deserialize<_ipk7gvzy.PasswordSignedIn>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'ResetPending') {
|
||||
return deserialize<_i3y6qzi3.ResetPending>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'SignInChallengePurpose') {
|
||||
return deserialize<_izijxzng.SignInChallengePurpose>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'WrappedKeys') {
|
||||
return deserialize<_i6v10ugm.WrappedKeys>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Profile') {
|
||||
return deserialize<_ia5j8fch.Profile>(data['data']);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue