chore: release v1.1.6
Build and Push / release (push) Successful in 3s
Build and Push / build (push) Successful in 3m3s

Auth moved to standalone controller outside Riverpod:
- New AuthController runs in main() before runApp()
- Handles callback, token exchange, and /auth/sync before app starts
- If auth not ready (redirecting), app doesn't start at all
- AuthProvider now just loads stored tokens (no async OIDC logic)
- Fixes "Cannot use Ref after disposed" errors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeroen Schweitzer
2026-01-04 17:14:20 +01:00
co-authored by Claude Opus 4.5
parent f90b4a0963
commit 5f3ff7f31a
5 changed files with 313 additions and 44 deletions
+3 -42
View File
@@ -40,51 +40,12 @@ class AuthNotifier extends _$AuthNotifier {
@override
Future<AuthState> build() async {
// On web with auth required, use silent OIDC to get JWT
if (kIsWeb && AppConfig.requiresAuth) {
// Skip silent OIDC if we're on the callback page (it will handle auth)
final currentUrl = web_utils.getCurrentUrl();
if (currentUrl.contains('/callback')) {
developer.log('Web: On callback page, skipping silent OIDC', name: 'auth');
return const AuthState();
}
// First check if we have stored tokens
final storedAuth = await _loadStoredAuth();
if (storedAuth.isAuthenticated && !storedAuth.isTokenExpired) {
developer.log('Web: Using stored tokens for ${storedAuth.userName}', name: 'auth');
return storedAuth;
}
// No valid tokens - initiate silent OIDC
// NPM forward auth ensures user has Authentik session
// prompt=none will get us a token instantly without UI
developer.log('Web: No valid tokens, initiating silent OIDC', name: 'auth');
_initiateSilentOidc();
// Return unauthenticated state - will redirect before this matters
return const AuthState();
}
// Mobile/LAN: Load stored auth from SharedPreferences
// AuthController.initialize() in main() handles OIDC flow before app starts.
// By the time we get here, tokens are already stored (or we're in LAN mode).
// Just load the stored auth state.
return _loadStoredAuth();
}
/// Initiate silent OIDC flow on web.
///
/// Uses prompt=none to get a token without showing login UI.
/// Relies on existing Authentik session (established via NPM forward auth).
Future<void> _initiateSilentOidc() async {
try {
final oidcService = OidcServiceWeb();
final authUrl = await oidcService.getAuthorizationUrl(silent: true);
developer.log('Redirecting to silent OIDC: $authUrl', name: 'auth');
web_utils.redirectTo(authUrl);
} catch (e) {
developer.log('Failed to initiate silent OIDC: $e', name: 'auth');
}
}
Future<AuthState> _loadStoredAuth() async {
try {
final prefs = await SharedPreferences.getInstance();