bloonio_auth_passkeys 0.1.2
bloonio_auth_passkeys: ^0.1.2 copied to clipboard
Bloonio passkeys (FIDO2/WebAuthn) SDK for Flutter — username-less sign-in, enrollment, and device management against your tenant backend's WebAuthn endpoints.
bloonio_auth_passkeys #
Flutter passkeys (FIDO2/WebAuthn) SDK for Bloonio tenant apps. It runs the
native passkey ceremony behind a stable interface and drives the tenant
backend's /auth/webauthn/* endpoints — username-less sign-in, enrollment,
and device management ("Mes appareils").
- Mobile never touches the relay directly. All calls go to the tenant backend (which holds the relay HMAC secret and forwards). Identity stays in your existing token layer; this SDK only adds passkeys on top.
- No Corbado cloud. It wraps the
passkeyspackage as a pure WebAuthn client against your relying party (bloonio.com). - Swappable core. The native ceremony lives behind
PasskeyAuthenticator; no Corbado types leak into the public API.
Install #
# pubspec.yaml of the tenant app (ligabloo_app, lokotroo_app, …)
dependencies:
bloonio_auth_passkeys: ^0.1.0
Or flutter pub add bloonio_auth_passkeys.
Configure once #
import 'package:bloonio_auth_passkeys/bloonio_auth_passkeys.dart';
BloonioAuth.configure(BloonioPasskeysConfig(
baseUrl: 'https://api.example.com', // your tenant backend
rpId: 'bloonio.com', // the Relying Party
androidOrigin: 'android:apk-key-hash:…', // from relay_webauthn_origins.json (Android only)
tokenProvider: () => myAuth.currentAccessToken, // for enroll/list/manage
onSession: (session) => myAuth.persist(session), // store like password login
));
Sign in (≤5 lines) #
final session = await BloonioAuth.passkeys.signIn(); // username-less, discoverable
// session.accessToken / session.refreshToken / session.user — same shape as password login.
// (onSession already persisted it; the return value is for immediate use.)
With a hint: await BloonioAuth.passkeys.signInWithHint('jo@bloonio.com').
Enroll, list, manage #
await BloonioAuth.passkeys.register(deviceLabel: 'Mon téléphone'); // requires sign-in + paired authenticator
final devices = await BloonioAuth.passkeys.list();
await BloonioAuth.passkeys.rename(devices.first.credentialRef, 'Pixel 9');
await BloonioAuth.passkeys.revoke(devices.first.credentialRef);
Drop-in device management screen (French "Mes appareils"):
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => const PasskeyDevicesScreen(),
));
Graceful degradation #
if (!await BloonioAuth.passkeys.isSupported()) {
// Old OS / no platform authenticator → show password/OTP instead.
}
try {
await BloonioAuth.passkeys.signIn();
} on PasskeyCancelled { // user dismissed the prompt
} on PasskeyNoCredential { // nothing enrolled on this device
} on PasskeyUnsupported { // device/OS can't do passkeys
} on PasskeyPairingRequired { // enroll needs the Bloonio Authenticator paired first
} on PasskeyRateLimited { // back off (see retryAfterSeconds)
} on PasskeyFailed { // everything else
}
All errors are PasskeyException subtypes — switch and fall back cleanly.
Platform setup (per consuming app) #
These mirror the .well-known association the relay serves (see
bloonio_auth_relay/PASSKEY_ONBOARDING.md). Passkeys fail silently without them.
Android
minSdkVersion 23builds; passkeys require API 28+ at runtime (isSupported()returns false below that).MainActivitycan stay a plainFlutterActivity.- The app's Play App Signing key SHA-256 must be in
https://bloonio.com/.well-known/assetlinks.json(M2). The same key'sandroid:apk-key-hash:is theandroidOriginyou pass toconfigure.
iOS
- Add the Associated Domains entitlement
webcredentials:bloonio.com. - The app's
TEAMID.BUNDLEIDmust be inhttps://bloonio.com/.well-known/apple-app-site-association(M2). - Passkeys require iOS 16+ at runtime.
Onboarding a new app to passkeys #
- Add the app's identity to the relay's
wellknown/passkey_identities.yaml, regenerate, deploy, and apply tenant origins (see the relay'sPASSKEY_ONBOARDING.md). - Copy the app's
android:apk-key-hash:fromwellknown/generated/relay_webauthn_origins.jsonintoandroidOrigin. - Add the platform entitlements above.
BloonioAuth.configure(...)and wire a "Mes appareils" route.
Notes #
- Enrollment precondition: the backend requires a paired Bloonio
Authenticator before
register()(HTTP 409 →PasskeyPairingRequired). Route the user through pairing first. Sign-in has no such requirement. - State-management agnostic:
tokenProvider/onSessionare plain callbacks andPasskeyDevicesScreenis a self-contained widget, so apps on Riverpod, Provider, or RxDart all integrate the same way.
Test #
flutter test # unit tests with a mocked authenticator + fake API (no device)
flutter analyze