authowl 0.2.0 copy "authowl: ^0.2.0" to clipboard
authowl: ^0.2.0 copied to clipboard

Official AuthOwl Flutter SDK with localized authentication widgets, provider-managed sessions, and secure-storage integration.

AuthOwl for Flutter #

Complete Flutter guide

Flutter widgets, provider, and session management for AuthOwl.

dependencies:
  authowl: ^0.1.0
  flutter_secure_storage: ^9.0.0

Import the provider, managed authentication screens, and headless client from one canonical entrypoint:

import 'package:authowl/authowl.dart';

Setup #

AuthOwlProvider(
  publishableKey: const String.fromEnvironment('AUTHOWL_PUBLISHABLE_KEY'),
  apiUrl: 'https://api.authowl.dev',
  storage: keychainStorage,     // see below
  child: const MyApp(),
)

Built-in controls use AuthOwl gold (#F5B84C) by default. The project's dashboard color replaces it automatically. An app-level override has highest priority when needed:

AuthOwlProvider(
  primaryColor: const Color(0xff0ea5a4),
  // ...publishableKey, apiUrl, storage, and child
)

The session cookie is a bearer credential - anything holding it is the signed-in user until it expires - so it belongs in the OS keychain, never in SharedPreferences, which is unencrypted:

class KeychainStorage implements AuthOwlStorage {
  final _store = const FlutterSecureStorage();

  @override
  Future<String?> read(String key) => _store.read(key: key);
  @override
  Future<void> write(String key, String value) => _store.write(key: key, value: value);
  @override
  Future<void> delete(String key) => _store.delete(key: key);
}

A pk_live_… key against a plain-http origin is refused outright: passwords and the session cookie would travel in the clear. Loopback http works with a pk_test_… key for local development.

Widgets #

AuthOwlSignIn(
  onSignedIn: () => context.go('/home'),
  onSecondFactorRequired: () => context.go('/mfa'),
  onMfaEnrollmentRequired: () => context.go('/mfa/enrol'),
)

AuthOwlSignUp(onSignedUp: ({required sessionCreated}) =>
  context.go(sessionCreated ? '/home' : '/check-your-email'))

AuthOwlEmailOtpForm(onSignedIn: () => context.go('/home'))

AuthOwlSignIn reports success only once a session exists. A two-factor challenge calls onSecondFactorRequired; a session held at mandatory MFA enrolment calls onMfaEnrollmentRequired. Neither path calls onSignedIn.

AuthOwlSignUp reports whether a session was created. Projects requiring email verification create none.

The provider loads the project's public configuration once. Built-in widgets hide disabled methods, enforce the configured password length, collect required legal consent, and send the accepted consent version automatically.

Session state #

final scope = AuthOwlProvider.of(context);
if (scope.session.isSignedIn) {
  Text('Hi, ${scope.session.user!.email}');
}

A session held at required-MFA enrolment is deliberately not signed in - treating it as authenticated would let an app skip the enrolment gate.

Localization #

AuthOwlProvider(locale: 'ar', ...)

Strings come from lib/src/i18n/catalog.g.dart, generated from @authowl/core so the wording matches the web and React Native SDKs exactly. CI fails if it drifts. It is not auto-detected from the device: a phone set to Arabic does not mean the app is localized, and switching only the auth screens is worse than defaulting. The provider also applies the matching right-to-left text direction to its subtree.

To regenerate after changing the shared catalogs:

pnpm --filter @authowl/core run build && node scripts/generate-dart-i18n.mjs

Social sign-in and passkeys #

Use the headless client with your provider's native SDK:

final result = await scope.client.signInWithIdToken(
  provider: 'google',
  idToken: googleCredential.idToken!,
);

Redirect OAuth is unsupported on purpose - it completes inside a system browser whose cookie jar this client cannot read, so the session would land somewhere the app can never see it.

For phone OTP, call preparePhoneOtp() before sending. The server returns the provider-neutral anti-abuse ceremony. Standard routes use AuthOwlTurnstileChallenge; Akedly Shield routes return an AkedlyShieldChallenge. Solve Shield with Akedly's official SDK for the target platform, then pass an AkedlyShieldProof to startPhoneOtp(). Provider API keys and pipeline IDs never enter the Flutter application.

License #

MIT

2
likes
135
points
121
downloads

Documentation

API reference

Publisher

verified publisherauthowl.dev

Weekly Downloads

Official AuthOwl Flutter SDK with localized authentication widgets, provider-managed sessions, and secure-storage integration.

Homepage
Repository (GitHub)

License

MIT (license)

Dependencies

flutter, http, url_launcher

More

Packages that depend on authowl