at_client_flutter 1.1.4
at_client_flutter: ^1.1.4 copied to clipboard
A Flutter extension to the at_client library which adds support for mobile, desktop and IoT devices.
at_client_flutter #
The Flutter layer on top of at_client. Adds
pre-built onboarding / authentication dialogs, device-keychain storage
for atKeys, and Flutter-specific extensions — so a new Flutter app can
go from "user has an atSign" to "authenticated AtClient in hand" with
a few widget calls.
Supports mobile, desktop, and IoT targets via Flutter. Flutter web is not supported — atSign onboarding and key handling rely on platform plugins (key-chain, file storage) that don't have web implementations today.
What's in the box #
| Capability | API |
|---|---|
| Select atSign + root domain | AtSignSelectionDialog.show(context) |
| Onboard a new atSign (CRAM) | RegistrarCramDialog.show(...) then CramDialog.show(...) |
Authenticate via .atKeys file |
AtKeysFileDialog.show(...) then PkamDialog.show(...) |
| Authenticate via device keychain | KeychainStorage() + PkamDialog.show(...) |
| Enroll a new device via APKAM | ApkamActivationDialog.show(...) (request side) / ApkamDialog.show(...) (approve side) |
| Keychain read / write / delete | KeychainStorage (lib/src/keychain/keychain_storage.dart) |
| Flutter helpers on core types | import 'package:at_client_flutter/extensions.dart'; |
Examples #
The authoritative, end-to-end walkthroughs live in this package's example app. Read these rather than copying snippets from here:
example/lib/walkthrough.dart— all four authentication / onboarding flows (CRAM onboarding, atKeys-file login, keychain login, APKAM enrollment) with the post-authAtClientinitialization. If you only read one file, read this one.example/lib/apkam_example.dart— the approve/deny side of APKAM (e.g. a "manager" device approving a new phone's enrollment request).example/lib/main.dart— minimal host app wiring the two flows above into navigation.
Smaller copy/paste snippets live under
example/lib/snippets:
example/lib/snippets/at_invitation.dart— replacement for the deprecatedat_invitation_flutterpackage. It keeps the SMS/email invite flow as app-owned code instead of a separate Flutter package.
For a full Flutter app using at_client_flutter in anger, see
the two flagship examples — deliberately positioned side-by-side
to make a fundamental SDK trade-off visible:
todos — the idiomatic AtCollection<T> Flutter app #
examples/todos/ is the first
place to look when building a real Flutter application on the
Atsign Protocol that needs a typed shared dataset. It drives
every common collection-shaped pattern through the mobile /
desktop widget stack: typed AtCollection<T> with fromJson /
typeTag, sub-collections (notes per todo), the Query<T>
builder with reactive watch() / watchWithSub / watchSingle,
sharedWith updates, built-in read receipts, scheduled visibility
via availableAt. Wire-compatible with the
CLI sibling
so the same data flows live between TUI and Flutter instances.
Full design, source tour, and multi-device demo in
examples/todos/README.md.
dockerstats — live container telemetry #
examples/dockerstats/ is the
canonical worked example of an SDK pattern the API doesn't
impose: deliver via short-lived notifications, store in a
relational database. The publisher (a Dart CLI)
emits one docker stats sample per container per cycle as a
single notificationService.send(...) — no AtCollection, no
keystore writes, no sync queue. The Flutter dashboard subscribes,
persists every sample as-received to a per-atSign SQLite
database (no roll-up, no compaction at rest), and renders charts
off that local store with a user-selectable window (5 m → all).
Each window change runs one SQL GROUP BY query sized to the
chart's pixel budget, so even an "all" view over years of raw
data stays responsive; live notifications fold into the visible
buckets incrementally.
It exists to demonstrate the trade-off explicitly: mis-applying
AtCollection<T> to a high-frequency observation stream — where
query / aggregation / windowing is the dominant design concern —
would be wrong. AtCollection<T> is for typed shared datasets
(the todos example above); notifications + local DB is for
streams of observations.
Full design, query-time aggregation semantics, and the seed-DB
workflow for cross-window chart development are in
examples/dockerstats/README.md.
Onboarding, provisioning & timeouts #
Registering a brand-new atSign and having its atServer provisioned are two
separate steps — provisioning can lag registration by anything from seconds to a
few minutes. The SDK handles that wait for you: AuthService.onboard polls for
the atServer to come up for 5 minutes by default
(AtNetworkTimeouts.defaultOnboardingTimeout), retrying every retryDelay with
each individual network probe capped at 60s. Returning-user sign-in
(authenticate) instead fails fast at 30s, because an existing atSign is
already provisioned and a dead network there should surface quickly.
What a Flutter app should do:
-
Call
onboard()with notimeout. The 5-minute provisioning poll is built in — don't wrap your own retry loop around it (that just re-stacks the retries this design removed). -
Show progress from
AuthService.progressStream, not a blind spinner. A multi-minute wait behind an indeterminate spinner reads as "hung." Subscribe before callingonboard— it's a broadcast stream and won't replay events you missed:final sub = authService.progressStream.listen((e) { setState(() => _status = e.msg); // e.type: info / success / warning / error }); try { await authService.onboard(request, cramSecret); // no timeout → full 5-min poll } on AtTimeoutException { // provisioning still not ready after 5 minutes — offer Retry (step 3) } finally { await sub.cancel(); } -
On
AtTimeoutException, offer Retry rather than a longer timeout. In the rare case provisioning runs past 5 minutes, a "Still setting up your atSign — tap to keep waiting" button that re-callsonboard()(a fresh 5-minute poll) beats baking in a 15-minute single timeout that makes every genuine failure feel broken. -
Override
timeoutonly to widen the window, and only when you know the provisioner is slow — e.g. a self-hosted atServer or custom atDirectory. Never pass a shorttimeouttoonboard()for a new atSign; it truncates the very wait you need. -
Returning users go through
authenticate()and keep the 30s fail-fast — don't borrow onboarding's patience for routine sign-in.
Note:
onboard()has no cancellation token, so the 5-minute poll runs to completion or timeout even if the user navigates away — a "Cancel" button can only change the UI, not abort the in-flight poll. True cancellation is tracked in #2075.
Post-authentication initialization #
Every auth flow ends the same way: create an AtClientPreference, then
call AtClientManager.setCurrentAtSign(...) with the atChops and
atLookUp from the returned AuthResponse. The details (chosen
storage directory, namespace, enrollment id) are all in
example/lib/walkthrough.dart in the
_setupAtClient(...) function.
Keychain storage #
KeychainStorage wraps the device keychain (iOS / Android / macOS /
Windows via biometric_storage) and stores atKeys and enrollment data.
The PKAM / APKAM dialogs accept a KeychainAtKeysIo instance as a
backup target so successful logins automatically populate the keychain
for next time.
Windows apps additionally need:
dependencies:
biometric_storage: ^4.1.3
Direct usage is rare, but when you need it:
final keychainStorage = KeychainStorage();
AtKeys? alice = await keychainStorage.getAtsign('@alice');
List<String> stored = await keychainStorage.getAllAtsigns();
await keychainStorage.appendAtKeysToKeychain(atKeys);
await keychainStorage.removeAtsignFromKeychain('@alice');
Exporting atKeys #
End users must back up their master atKeys (see at_auth's lifecycle writeup). The keychain → file export:
final atSign = AtClientManager.getInstance().atClient.getCurrentAtSign()!;
final atKeys = await KeychainStorage().getAtsign(atSign);
if (atKeys == null) throw Exception('No keys found for $atSign');
final atKeysIo = FileAtKeysIo(
filePath: (_) => '/path/to/${atSign}_key.atKeys',
);
atKeysIo.write(atSign, atKeys);
Where to go next #
at_client— the SDK whoseAtClientyou end up with after authenticationat_auth— detailed writeup of the atSign provisioning / onboarding / APKAM lifecycle, platform-neutralat_commons—AtKey,Metadata, and friends
Open source usage and contributions #
BSD3-licensed. See CONTRIBUTING.md for
guidance on setting up tools, running tests, and raising a PR.