feat(base): SimpleLogin accounts' keys without SRP, signing up in one call (ADR 0020, step 3)
An account that signs in with SimpleLogin keeps its keys under a password that signs nobody in (D19): `account_password` keeps the password's own proof key (Ed25519, `passwordProofKey`) in place of SRP's verifier, which becomes nullable. The migration adds the column and drops the NOT NULL, nothing else. - `simpleLogin.signUp(attempt, handle, setup)`: someone new whose identity waits under the attempt gets, in one transaction, an account (identified), the link, a profile with the handle and the keys; then a session (D18). Refused, the identity still waiting, for a setup out of range and a handle refused as saving a profile refuses it. - `simpleLogin.checkHandle(attempt, handle)`: whether someone new could take a handle, at most 30 an hour per attempt and 60 per network. - `simpleLogin.complete` says, for an account, whether it has its keys and its handle, and keeps the sign-in ten minutes under its attempt, the account as its caller: D20's confirmation for the changes to come. - `keys.begin`, `keys.unlock`: the keys for a signed-in device once the password is proven with its proof key, for a nonce, bound to the base URL the device addressed; wrong proofs counted per session as ADR 0017's. - An authenticator is enrolled only for a password that signs in. - Members ask the register for all of it; `RemoteRegister` and the instance API carry the four new operations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
c6831b0b7b
commit
090d901e92
81 changed files with 46254 additions and 78 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigration",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationAction",
|
||||||
|
"type": "alterTable",
|
||||||
|
"alterTable": {
|
||||||
|
"__className__": "serverpod.TableMigration",
|
||||||
|
"name": "account_password",
|
||||||
|
"schema": "public",
|
||||||
|
"addColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnDefinition",
|
||||||
|
"name": "passwordProofKey",
|
||||||
|
"fieldName": "passwordProofKey",
|
||||||
|
"columnType": 5,
|
||||||
|
"isNullable": true,
|
||||||
|
"dartType": "dart:typed_data:ByteData?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deleteColumns": [],
|
||||||
|
"modifyColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnMigration",
|
||||||
|
"columnName": "verifier",
|
||||||
|
"addNullable": true,
|
||||||
|
"removeNullable": false,
|
||||||
|
"changeDefault": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addIndexes": [],
|
||||||
|
"deleteIndexes": [],
|
||||||
|
"addForeignKeys": [],
|
||||||
|
"deleteForeignKeys": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"warnings": [],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,7 @@ part '20261021110159867-second-factor-paths/migration.dart';
|
||||||
part '20261021134803749-reset-hold-outs/migration.dart';
|
part '20261021134803749-reset-hold-outs/migration.dart';
|
||||||
part '20261021184601197-private-studysets/migration.dart';
|
part '20261021184601197-private-studysets/migration.dart';
|
||||||
part '20261023181810112-oidc-module/migration.dart';
|
part '20261023181810112-oidc-module/migration.dart';
|
||||||
|
part '20261023192913178-simplelogin-keys/migration.dart';
|
||||||
|
|
||||||
/// Migration registry for the client-side database.
|
/// Migration registry for the client-side database.
|
||||||
class MigrationRegistry {
|
class MigrationRegistry {
|
||||||
|
|
@ -60,6 +61,7 @@ class MigrationRegistry {
|
||||||
_Migration20261021134803749_reset_hold_outs(),
|
_Migration20261021134803749_reset_hold_outs(),
|
||||||
_Migration20261021184601197_private_studysets(),
|
_Migration20261021184601197_private_studysets(),
|
||||||
_Migration20261023181810112_oidc_module(),
|
_Migration20261023181810112_oidc_module(),
|
||||||
|
_Migration20261023192913178_simplelogin_keys(),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// List of all client-side database migration versions.
|
/// List of all client-side database migration versions.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigration",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationAction",
|
||||||
|
"type": "alterTable",
|
||||||
|
"alterTable": {
|
||||||
|
"__className__": "serverpod.TableMigration",
|
||||||
|
"name": "account_password",
|
||||||
|
"schema": "public",
|
||||||
|
"addColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnDefinition",
|
||||||
|
"name": "passwordProofKey",
|
||||||
|
"fieldName": "passwordProofKey",
|
||||||
|
"columnType": 5,
|
||||||
|
"isNullable": true,
|
||||||
|
"dartType": "dart:typed_data:ByteData?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deleteColumns": [],
|
||||||
|
"modifyColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnMigration",
|
||||||
|
"columnName": "verifier",
|
||||||
|
"addNullable": true,
|
||||||
|
"removeNullable": false,
|
||||||
|
"changeDefault": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addIndexes": [],
|
||||||
|
"deleteIndexes": [],
|
||||||
|
"addForeignKeys": [],
|
||||||
|
"deleteForeignKeys": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"warnings": [],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- ACTION ALTER TABLE
|
||||||
|
--
|
||||||
|
ALTER TABLE "account_password" ADD COLUMN "passwordProofKey" bytea;
|
||||||
|
ALTER TABLE "account_password" ALTER COLUMN "verifier" DROP NOT NULL;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_learn
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_learn', '20261023192913178-simplelogin-keys', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261023192913178-simplelogin-keys', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_base
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_base', '20261023192912859-simplelogin-keys', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261023192912859-simplelogin-keys', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod', '20260824182259319', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260824182259319', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_idp
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_idp', '20260924105404509', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105404509', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_offline_sync
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_offline_sync', '20260914143806119', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260914143806119', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_oidc
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_oidc', '20261023180644988', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261023180644988', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_core
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_core', '20260924105232991', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105232991', "timestamp" = now();
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
@ -47,3 +47,4 @@
|
||||||
20261021184601197-private-studysets
|
20261021184601197-private-studysets
|
||||||
20261023131636437
|
20261023131636437
|
||||||
20261023181810112-oidc-module
|
20261023181810112-oidc-module
|
||||||
|
20261023192913178-simplelogin-keys
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseDefinition",
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"moduleName": "halkyon_todo",
|
||||||
|
"tables": [],
|
||||||
|
"installedModules": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "halkyon_base",
|
||||||
|
"version": "20261023192912859-simplelogin-keys"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "serverpod",
|
||||||
|
"version": "20260824182259319"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "serverpod_auth_idp",
|
||||||
|
"version": "20260924105404509"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "halkyon_oidc",
|
||||||
|
"version": "20261023180644988"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationVersion",
|
||||||
|
"module": "serverpod_auth_core",
|
||||||
|
"version": "20260924105232991"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigration",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.DatabaseMigrationAction",
|
||||||
|
"type": "alterTable",
|
||||||
|
"alterTable": {
|
||||||
|
"__className__": "serverpod.TableMigration",
|
||||||
|
"name": "account_password",
|
||||||
|
"schema": "public",
|
||||||
|
"addColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnDefinition",
|
||||||
|
"name": "passwordProofKey",
|
||||||
|
"fieldName": "passwordProofKey",
|
||||||
|
"columnType": 5,
|
||||||
|
"isNullable": true,
|
||||||
|
"dartType": "dart:typed_data:ByteData?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deleteColumns": [],
|
||||||
|
"modifyColumns": [
|
||||||
|
{
|
||||||
|
"__className__": "serverpod.ColumnMigration",
|
||||||
|
"columnName": "verifier",
|
||||||
|
"addNullable": true,
|
||||||
|
"removeNullable": false,
|
||||||
|
"changeDefault": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"addIndexes": [],
|
||||||
|
"deleteIndexes": [],
|
||||||
|
"addForeignKeys": [],
|
||||||
|
"deleteForeignKeys": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"warnings": [],
|
||||||
|
"migrationApiVersion": 1
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- ACTION ALTER TABLE
|
||||||
|
--
|
||||||
|
ALTER TABLE "account_password" ADD COLUMN "passwordProofKey" bytea;
|
||||||
|
ALTER TABLE "account_password" ALTER COLUMN "verifier" DROP NOT NULL;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_todo
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_todo', '20261023192913500-simplelogin-keys', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261023192913500-simplelogin-keys', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_base
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_base', '20261023192912859-simplelogin-keys', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261023192912859-simplelogin-keys', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod', '20260824182259319', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260824182259319', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_idp
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_idp', '20260924105404509', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105404509', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR halkyon_oidc
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('halkyon_oidc', '20261023180644988', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20261023180644988', "timestamp" = now();
|
||||||
|
|
||||||
|
--
|
||||||
|
-- MIGRATION VERSION FOR serverpod_auth_core
|
||||||
|
--
|
||||||
|
INSERT INTO "serverpod_migrations" ("module", "version", "timestamp")
|
||||||
|
VALUES ('serverpod_auth_core', '20260924105232991', now())
|
||||||
|
ON CONFLICT ("module")
|
||||||
|
DO UPDATE SET "version" = '20260924105232991', "timestamp" = now();
|
||||||
|
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
@ -17,3 +17,4 @@
|
||||||
20261021110200318-second-factor-paths
|
20261021110200318-second-factor-paths
|
||||||
20261021134804476-reset-hold-outs
|
20261021134804476-reset-hold-outs
|
||||||
20261023181810436-oidc-module
|
20261023181810436-oidc-module
|
||||||
|
20261023192913500-simplelogin-keys
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,14 @@
|
||||||
no account yet: their identity waits (D16), with a
|
no account yet: their identity waits (D16), with a
|
||||||
handle suggested (D17), for the sign-up of step 3. halkyon_oidc's `testing.dart` gives
|
handle suggested (D17), for the sign-up of step 3. halkyon_oidc's `testing.dart` gives
|
||||||
hosts a fake SimpleLogin signing real ID tokens, which the module's tests use too.
|
hosts a fake SimpleLogin signing real ID tokens, which the module's tests use too.
|
||||||
|
- **Built (23 Oct 2026), step 3 so far:** the password's own proof key (`halkyon_keys`'
|
||||||
|
subkey 3 of the master key, D19), which `account_password` keeps in place of SRP's
|
||||||
|
verifier for an account that signs in with SimpleLogin (the verifier becomes nullable:
|
||||||
|
a migration that drops nothing); `simpleLogin.signUp` in one call (D18) and
|
||||||
|
`simpleLogin.checkHandle`, both for someone new's identity alone; `keys.begin` and
|
||||||
|
`keys.unlock`, the proof counted as ADR 0017's; every sign-in into an account kept ten
|
||||||
|
minutes under its attempt as D20's confirmation. The changes (first keys, a new or
|
||||||
|
lost password, a new phrase, the deletion) and the mending come next.
|
||||||
- **Builds on:** ADR 0010 (email sign-in), ADR 0011 (profile pages), ADR 0016 (the
|
- **Builds on:** ADR 0010 (email sign-in), ADR 0011 (profile pages), ADR 0016 (the
|
||||||
register), ADR 0017 (a password, TOTP and the keys).
|
register), ADR 0017 (a password, TOTP and the keys).
|
||||||
- **Changes:** ADR 0017's way in on an instance that offers SimpleLogin (its keys, their
|
- **Changes:** ADR 0017's way in on an instance that offers SimpleLogin (its keys, their
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ abstract class SignInWays
|
||||||
required this.email,
|
required this.email,
|
||||||
bool? simpleLogin,
|
bool? simpleLogin,
|
||||||
bool? password,
|
bool? password,
|
||||||
|
bool? keys,
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
|
@ -28,6 +29,7 @@ abstract class SignInWays
|
||||||
this.accountResetAt,
|
this.accountResetAt,
|
||||||
}) : simpleLogin = simpleLogin ?? false,
|
}) : simpleLogin = simpleLogin ?? false,
|
||||||
password = password ?? false,
|
password = password ?? false,
|
||||||
|
keys = keys ?? false,
|
||||||
authenticator = authenticator ?? false,
|
authenticator = authenticator ?? false,
|
||||||
passwordOnly = passwordOnly ?? false,
|
passwordOnly = passwordOnly ?? false,
|
||||||
secondFactorWorks = secondFactorWorks ?? false;
|
secondFactorWorks = secondFactorWorks ?? false;
|
||||||
|
|
@ -37,6 +39,7 @@ abstract class SignInWays
|
||||||
required bool email,
|
required bool email,
|
||||||
bool? simpleLogin,
|
bool? simpleLogin,
|
||||||
bool? password,
|
bool? password,
|
||||||
|
bool? keys,
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
|
@ -55,6 +58,9 @@ abstract class SignInWays
|
||||||
password: jsonSerialization['password'] == null
|
password: jsonSerialization['password'] == null
|
||||||
? null
|
? null
|
||||||
: _isc.BoolJsonExtension.fromJson(jsonSerialization['password']),
|
: _isc.BoolJsonExtension.fromJson(jsonSerialization['password']),
|
||||||
|
keys: jsonSerialization['keys'] == null
|
||||||
|
? null
|
||||||
|
: _isc.BoolJsonExtension.fromJson(jsonSerialization['keys']),
|
||||||
authenticator: jsonSerialization['authenticator'] == null
|
authenticator: jsonSerialization['authenticator'] == null
|
||||||
? null
|
? null
|
||||||
: _isc.BoolJsonExtension.fromJson(jsonSerialization['authenticator']),
|
: _isc.BoolJsonExtension.fromJson(jsonSerialization['authenticator']),
|
||||||
|
|
@ -93,9 +99,14 @@ abstract class SignInWays
|
||||||
/// instance's SimpleLogin app.
|
/// instance's SimpleLogin app.
|
||||||
bool simpleLogin;
|
bool simpleLogin;
|
||||||
|
|
||||||
/// A password (ADR 0017), which an address needs for resets.
|
/// A password that signs in (ADR 0017, SRP's), which an address needs
|
||||||
|
/// for resets.
|
||||||
bool password;
|
bool password;
|
||||||
|
|
||||||
|
/// The account's keys, under a password that signs in (ADR 0017) or one
|
||||||
|
/// that only opens them, as for SimpleLogin (ADR 0020, D19).
|
||||||
|
bool keys;
|
||||||
|
|
||||||
/// A confirmed authenticator: the password signs in only with one.
|
/// A confirmed authenticator: the password signs in only with one.
|
||||||
bool authenticator;
|
bool authenticator;
|
||||||
|
|
||||||
|
|
@ -130,6 +141,7 @@ abstract class SignInWays
|
||||||
bool? email,
|
bool? email,
|
||||||
bool? simpleLogin,
|
bool? simpleLogin,
|
||||||
bool? password,
|
bool? password,
|
||||||
|
bool? keys,
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
|
@ -145,6 +157,7 @@ abstract class SignInWays
|
||||||
'email': email,
|
'email': email,
|
||||||
'simpleLogin': simpleLogin,
|
'simpleLogin': simpleLogin,
|
||||||
'password': password,
|
'password': password,
|
||||||
|
'keys': keys,
|
||||||
'authenticator': authenticator,
|
'authenticator': authenticator,
|
||||||
'passwordOnly': passwordOnly,
|
'passwordOnly': passwordOnly,
|
||||||
'secondFactorWorks': secondFactorWorks,
|
'secondFactorWorks': secondFactorWorks,
|
||||||
|
|
@ -164,6 +177,7 @@ abstract class SignInWays
|
||||||
'email': email,
|
'email': email,
|
||||||
'simpleLogin': simpleLogin,
|
'simpleLogin': simpleLogin,
|
||||||
'password': password,
|
'password': password,
|
||||||
|
'keys': keys,
|
||||||
'authenticator': authenticator,
|
'authenticator': authenticator,
|
||||||
'passwordOnly': passwordOnly,
|
'passwordOnly': passwordOnly,
|
||||||
'secondFactorWorks': secondFactorWorks,
|
'secondFactorWorks': secondFactorWorks,
|
||||||
|
|
@ -189,6 +203,7 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
required bool email,
|
required bool email,
|
||||||
bool? simpleLogin,
|
bool? simpleLogin,
|
||||||
bool? password,
|
bool? password,
|
||||||
|
bool? keys,
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
|
@ -200,6 +215,7 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
email: email,
|
email: email,
|
||||||
simpleLogin: simpleLogin,
|
simpleLogin: simpleLogin,
|
||||||
password: password,
|
password: password,
|
||||||
|
keys: keys,
|
||||||
authenticator: authenticator,
|
authenticator: authenticator,
|
||||||
passwordOnly: passwordOnly,
|
passwordOnly: passwordOnly,
|
||||||
secondFactorWorks: secondFactorWorks,
|
secondFactorWorks: secondFactorWorks,
|
||||||
|
|
@ -217,6 +233,7 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
bool? email,
|
bool? email,
|
||||||
bool? simpleLogin,
|
bool? simpleLogin,
|
||||||
bool? password,
|
bool? password,
|
||||||
|
bool? keys,
|
||||||
bool? authenticator,
|
bool? authenticator,
|
||||||
bool? passwordOnly,
|
bool? passwordOnly,
|
||||||
bool? secondFactorWorks,
|
bool? secondFactorWorks,
|
||||||
|
|
@ -229,6 +246,7 @@ class _SignInWaysImpl extends SignInWays {
|
||||||
email: email ?? this.email,
|
email: email ?? this.email,
|
||||||
simpleLogin: simpleLogin ?? this.simpleLogin,
|
simpleLogin: simpleLogin ?? this.simpleLogin,
|
||||||
password: password ?? this.password,
|
password: password ?? this.password,
|
||||||
|
keys: keys ?? this.keys,
|
||||||
authenticator: authenticator ?? this.authenticator,
|
authenticator: authenticator ?? this.authenticator,
|
||||||
passwordOnly: passwordOnly ?? this.passwordOnly,
|
passwordOnly: passwordOnly ?? this.passwordOnly,
|
||||||
secondFactorWorks: secondFactorWorks ?? this.secondFactorWorks,
|
secondFactorWorks: secondFactorWorks ?? this.secondFactorWorks,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,14 @@ import 'package:halkyon_base_client/src/protocol/auth/sign_in_ways.dart'
|
||||||
as _ifld8s4r;
|
as _ifld8s4r;
|
||||||
import 'package:halkyon_base_client/src/protocol/instance/instance_basics.dart'
|
import 'package:halkyon_base_client/src/protocol/instance/instance_basics.dart'
|
||||||
as _isnyur2i;
|
as _isnyur2i;
|
||||||
|
import 'package:halkyon_base_client/src/protocol/keys/device_keys.dart'
|
||||||
|
as _invv3u3l;
|
||||||
|
import 'package:halkyon_base_client/src/protocol/keys/keys_challenge.dart'
|
||||||
|
as _ivkzjgkp;
|
||||||
|
import 'package:halkyon_base_client/src/protocol/keys/keys_proof.dart'
|
||||||
|
as _iznbn55x;
|
||||||
|
import 'package:halkyon_base_client/src/protocol/keys/keys_setup.dart'
|
||||||
|
as _iec2fqr0;
|
||||||
import 'package:halkyon_base_client/src/protocol/password/authenticator.dart'
|
import 'package:halkyon_base_client/src/protocol/password/authenticator.dart'
|
||||||
as _ivfmflch;
|
as _ivfmflch;
|
||||||
import 'package:halkyon_base_client/src/protocol/password/authenticator_enrolment.dart'
|
import 'package:halkyon_base_client/src/protocol/password/authenticator_enrolment.dart'
|
||||||
|
|
@ -222,6 +230,43 @@ class EndpointInstance extends _isc.EndpointRef {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The keys of an account that signs in with SimpleLogin (Halkyon Learn's
|
||||||
|
/// ADR 0020, 7 and D19), for its signed-in devices: the password proven
|
||||||
|
/// with its own proof key, which the instance's register checks (ADR 0016).
|
||||||
|
/// Refusals are `PasswordRefusedException`s.
|
||||||
|
/// {@category Endpoint}
|
||||||
|
class EndpointKeys extends _isc.EndpointRef {
|
||||||
|
EndpointKeys(_isc.EndpointCaller caller) : super(caller);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => 'halkyon_base.keys';
|
||||||
|
|
||||||
|
/// The first step of proving your password: the salt and costs your
|
||||||
|
/// device derives the password's keys with, and a nonce to sign with its
|
||||||
|
/// proof key, within two minutes, once. Refused for an account without
|
||||||
|
/// such keys (`PasswordRefusal.noPassword`).
|
||||||
|
_ida.Future<_ivkzjgkp.KeysChallenge> begin() =>
|
||||||
|
caller.callServerEndpoint<_ivkzjgkp.KeysChallenge>(
|
||||||
|
'halkyon_base.keys',
|
||||||
|
'begin',
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Your keys for this device, once [proof] proved your password: your
|
||||||
|
/// public keys and your private keys wrapped under the password's key,
|
||||||
|
/// which the device opens. The proof is bound to the base URL the device
|
||||||
|
/// addressed here, and counts against this session: the tenth wrong in a
|
||||||
|
/// row ends it (`PasswordRefusal.sessionEnded`), and you are warned.
|
||||||
|
/// Refused for a wrong proof (`PasswordRefusal.wrongCredentials`) and a
|
||||||
|
/// challenge unknown, used or too old (`PasswordRefusal.challengeExpired`).
|
||||||
|
_ida.Future<_invv3u3l.DeviceKeys> unlock(_iznbn55x.KeysProof proof) =>
|
||||||
|
caller.callServerEndpoint<_invv3u3l.DeviceKeys>(
|
||||||
|
'halkyon_base.keys',
|
||||||
|
'unlock',
|
||||||
|
{'proof': proof},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Getting back into an account (ADR 0017): a lost authenticator, a lost
|
/// Getting back into an account (ADR 0017): a lost authenticator, a lost
|
||||||
/// password with the recovery phrase, a lost password without it. Called
|
/// password with the recovery phrase, a lost password without it. Called
|
||||||
/// without a session, as the person can't sign in. The instance's register
|
/// without a session, as the person can't sign in. The instance's register
|
||||||
|
|
@ -761,10 +806,14 @@ class EndpointSimpleLogin extends _isc.EndpointRef {
|
||||||
|
|
||||||
/// Ends [attempt] with SimpleLogin's [code], as the caller began it:
|
/// Ends [attempt] with SimpleLogin's [code], as the caller began it:
|
||||||
/// signed out, a session for the account with that identity, or for
|
/// signed out, a session for the account with that identity, or for
|
||||||
/// someone new the handle suggested (their account comes next); signed
|
/// someone new the handle suggested (their account comes with [signUp]);
|
||||||
/// in, SimpleLogin added to the caller's account. Serverpod issues no
|
/// signed in, SimpleLogin added to the caller's account. Serverpod issues
|
||||||
/// session for another person inside a signed-in call, and nobody is
|
/// no session for another person inside a signed-in call, and nobody is
|
||||||
/// switched to another account. Refusals as `completeSimpleLogin`'s.
|
/// switched to another account. For an account, whether it has its keys
|
||||||
|
/// (`keys.unlock` opens them; one without makes them) and its handle; and
|
||||||
|
/// for ten minutes the attempt's ID stands for this sign-in, for a change
|
||||||
|
/// the device asks for (ADR 0020, D20). Refusals as
|
||||||
|
/// `completeSimpleLogin`'s.
|
||||||
_ida.Future<_ianfx7qj.SimpleLoginCompleted> complete({
|
_ida.Future<_ianfx7qj.SimpleLoginCompleted> complete({
|
||||||
required _isc.UuidValue attempt,
|
required _isc.UuidValue attempt,
|
||||||
required String code,
|
required String code,
|
||||||
|
|
@ -776,6 +825,48 @@ class EndpointSimpleLogin extends _isc.EndpointRef {
|
||||||
'code': code,
|
'code': code,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Whether someone new, whose identity waits under [attempt] ([complete]
|
||||||
|
/// said `newcomer`), could take [handle]: null where they could, else why
|
||||||
|
/// not, as saving a profile would say. For the app to say so while it is
|
||||||
|
/// typed; [signUp] checks again. At most 30 for an attempt and 60 from a
|
||||||
|
/// network in an hour (`ProfileRefusal.tooManyHandleChecks`, thrown):
|
||||||
|
/// each answer tells which handles exist. Refused
|
||||||
|
/// (`OidcRefusal.unknownAttempt`) where no identity waits.
|
||||||
|
_ida.Future<_ih722tf9.ProfileRefusal?> checkHandle({
|
||||||
|
required _isc.UuidValue attempt,
|
||||||
|
required String handle,
|
||||||
|
}) => caller.callServerEndpoint<_ih722tf9.ProfileRefusal?>(
|
||||||
|
'halkyon_base.simpleLogin',
|
||||||
|
'checkHandle',
|
||||||
|
{
|
||||||
|
'attempt': attempt,
|
||||||
|
'handle': handle,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Signs up someone new, whose identity waits under [attempt] for half an
|
||||||
|
/// hour after [complete] said `newcomer` (ADR 0020, D16 and D18): an
|
||||||
|
/// account with [handle], private until its person goes public, and the
|
||||||
|
/// keys [setup] describes, all made on the device beforehand; a session
|
||||||
|
/// for it here. Refused, the identity still waiting: for a setup out of
|
||||||
|
/// range (`PasswordRefusal.invalidSetup`) and a handle refused
|
||||||
|
/// (`ProfileRefusedException`, as saving a profile refuses it); for an
|
||||||
|
/// attempt unknown, taken or past its time (`OidcRefusal.unknownAttempt`),
|
||||||
|
/// and called signed in (`OidcRefusal.wrongCaller`).
|
||||||
|
_ida.Future<_iacc.AuthSuccess> signUp({
|
||||||
|
required _isc.UuidValue attempt,
|
||||||
|
required String handle,
|
||||||
|
required _iec2fqr0.KeysSetup setup,
|
||||||
|
}) => caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||||
|
'halkyon_base.simpleLogin',
|
||||||
|
'signUp',
|
||||||
|
{
|
||||||
|
'attempt': attempt,
|
||||||
|
'handle': handle,
|
||||||
|
'setup': setup,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Caller extends _isc.ModuleEndpointCaller {
|
class Caller extends _isc.ModuleEndpointCaller {
|
||||||
|
|
@ -786,6 +877,7 @@ class Caller extends _isc.ModuleEndpointCaller {
|
||||||
gitHubSignIn = EndpointGitHubSignIn(this);
|
gitHubSignIn = EndpointGitHubSignIn(this);
|
||||||
gitHubUpgrade = EndpointGitHubUpgrade(this);
|
gitHubUpgrade = EndpointGitHubUpgrade(this);
|
||||||
instance = EndpointInstance(this);
|
instance = EndpointInstance(this);
|
||||||
|
keys = EndpointKeys(this);
|
||||||
accountRecovery = EndpointAccountRecovery(this);
|
accountRecovery = EndpointAccountRecovery(this);
|
||||||
authenticator = EndpointAuthenticator(this);
|
authenticator = EndpointAuthenticator(this);
|
||||||
password = EndpointPassword(this);
|
password = EndpointPassword(this);
|
||||||
|
|
@ -807,6 +899,8 @@ class Caller extends _isc.ModuleEndpointCaller {
|
||||||
|
|
||||||
late final EndpointInstance instance;
|
late final EndpointInstance instance;
|
||||||
|
|
||||||
|
late final EndpointKeys keys;
|
||||||
|
|
||||||
late final EndpointAccountRecovery accountRecovery;
|
late final EndpointAccountRecovery accountRecovery;
|
||||||
|
|
||||||
late final EndpointAuthenticator authenticator;
|
late final EndpointAuthenticator authenticator;
|
||||||
|
|
@ -829,6 +923,7 @@ class Caller extends _isc.ModuleEndpointCaller {
|
||||||
'halkyon_base.gitHubSignIn': gitHubSignIn,
|
'halkyon_base.gitHubSignIn': gitHubSignIn,
|
||||||
'halkyon_base.gitHubUpgrade': gitHubUpgrade,
|
'halkyon_base.gitHubUpgrade': gitHubUpgrade,
|
||||||
'halkyon_base.instance': instance,
|
'halkyon_base.instance': instance,
|
||||||
|
'halkyon_base.keys': keys,
|
||||||
'halkyon_base.accountRecovery': accountRecovery,
|
'halkyon_base.accountRecovery': accountRecovery,
|
||||||
'halkyon_base.authenticator': authenticator,
|
'halkyon_base.authenticator': authenticator,
|
||||||
'halkyon_base.password': password,
|
'halkyon_base.password': password,
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue