Changelog
Notable changes to the authyra package.
Mirrors packages/authyra/CHANGELOG.md in the repository, the source of truth.
Unreleased
Added
TokenRefresher: background token-refresh scheduler with configurable check interval, expiry threshold, and linear retry policy. Owned bySessionManager; wired up byAuthyraClientat construction time.SessionManager.refreshActiveSession(): on-demand refresh delegating toTokenRefresherwith the same retry policy.SessionManager.setRefreshCallbacks(onSuccess, onFailure): hook forAuthyraClientto emitTokenRefreshEvent/SessionExpiredEventon refresh outcome.AuthyraClientBuilder: fluent builder for configuring and instantiatingAuthyraClientwith custom providers, storage, config, and event bus.AuthyraPlugin: extension interface for adding cross-cutting behaviour (audit logging, rate limiting) viainstall(client)plus optionalonBeforeSignIn/onAfterSignIn/onSessionExpiredhooks. Registered viaAuthyraClient(plugins: [...])orAuthyraClientBuilder.addPlugin().AuthAccountmodel: provider-linked account entry with tokens andproviderData.SessionMetadatamodel: optional device/network context (ipAddress,userAgent,deviceId,country) attached to a session.- Typed
AuthSignInParamshierarchy:CredentialsSignInParams,OAuth2SignInParams. ReplacesMap<String, dynamic>for provider params. AuthyraClient.events: per-instanceAuthEventBuswith typedon<T>()/off<T>()listeners and a raw broadcaststream.- Auto-refresh in
getSession(): transparently refreshes the token when expiring soon (autoRefresh: true). EmitsSessionExpiredEventand returnsnullon failure.
Changed
AuthSessionis now a pointer to the activeAuthAccount: token fields (accessToken,refreshToken,expiresAt,providerId) are computed getters delegating toactiveAccount. The new required fieldactiveAccountIdidentifies the active entry inlinkedAccounts. Storage format migrates gracefully from the legacy flat structure.AuthProvider.signInand all callbacks now acceptAuthSignInParams?instead ofMap<String, dynamic>?.AuthSession.linkedProviders: List<String>replaced bylinkedAccounts: List<AuthAccount>. AddedlinkedProviderIdsgetter and updatedhasLinkedProvider().AuthSessiongainsmetadata: SessionMetadata?.AuthEventBusis no longer a singleton, eachAuthyraClientowns its own instance.AuthyraClient.signInauto-generates anAuthAccountwhen the provider doesn't supply one.
Fixed
AuthEventBus.on<T>(): switched toList<Function>with dynamic dispatch to fix a Dart contravariance cast error.getSession()readsactiveSessiondirectly (bypassing the expiry guard) before handing off to auto-refresh logic.SessionManagerno longer persists the wholeSessionRegistryas a single JSON blob. Each account is now stored under its ownsession:{userId}key, so refreshing or removing one account no longer rewrites every other account's tokens. Existing installs migrate the legacy blob automatically on first load.AuthCallbacks.onBeforeAccountSwitch,onBeforeTokenRefresh, andonBeforeAccountRemovewere defined but never invoked. They're now called fromAccountManager.switchTo()/signOut()and from the token-refresh path, so overriding them actually gates the corresponding operation.AccountSwitchEventandAccountRemovedEventwere documented in the event catalogue but never emitted.AccountManagernow emits both.TokenRefresherretried a denied or unsupported refresh up tomaxRetriestimes before expiring the session, even though retrying could never succeed. ARefreshProvidercan now throwRefreshDeniedExceptionto signal a non-retryable refresh;TokenRefresherexpires the session immediately instead of wasting the retry budget.- A storage write failure partway through a multi-account save no longer leaves the in-memory registry claiming a mutation succeeded when storage doesn't back it up; it rolls back to the pre-mutation state instead.
0.1.0 (2026-02-23)
Added
AccountManager: high-level multi-account facade withgetAll(),switchTo(),signOut(),signOutAll(), andcleanExpired().SessionManager.cleanExpiredSessions().AuthConfig.copyWith,toJson,fromJson.AuthStateextendsEquatable: deduplicates identical consecutive states in streams.InMemoryStorage: non-persistentAuthStorageimplementation for tests and development.
Changed
MultiAccountManagerrenamed toAccountManager.
Fixed
AccountManager.cleanExpired()now delegates toSessionManager.cleanExpiredSessions()instead of overwriting a single session.AccountManager.signOut()notifies the reactive layer after removing the active account.AuthSession.fromJson():accessTokenandexpiresAtcast as nullable, fixing crashes in cookie-based flows.SessionRegistryaccount election after expiry removal now orders bylastUsedAt(deterministic).AuthUser.copyWith(): removed phantom parameters that were silently ignored.
0.0.1 (2025-01-01)
Added
- Initial package scaffold:
AuthyraClient,AuthyraInstance,AuthProviderwithCredentialsProvider,AuthStorage,SessionManager, and the core models (AuthUser,AuthSession,AuthState,AuthConfig,SessionRegistry).