From 4d483495fc31ea3cdb9b3189cc23d4cc11520b01 Mon Sep 17 00:00:00 2001 From: Pete Gregory Date: Fri, 12 Dec 2025 09:58:52 +0000 Subject: [PATCH] add secure storage (not working) --- .gitea/workflows/release.yml | 10 ++- lib/services/authservice.dart | 25 +++--- lib/services/tokenStorageService.dart | 36 +++++++++ linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 4 + pubspec.lock | 80 +++++++++++++++++++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 10 files changed, 155 insertions(+), 10 deletions(-) create mode 100644 lib/services/tokenStorageService.dart diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index cd63a77..ce42bd0 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -141,6 +141,15 @@ jobs: - android-build - linux-build steps: + - name: Install jq + run: | + if command -v sudo >/dev/null 2>&1; then + SUDO="sudo" + else + SUDO="" + fi + $SUDO apt-get update + $SUDO apt-get install -y jq - name: Download Android APK if: ${{ github.ref == 'refs/heads/dev' }} uses: actions/download-artifact@v3 @@ -220,7 +229,6 @@ jobs: >/dev/null done - release-master: runs-on: ubuntu-latest needs: diff --git a/lib/services/authservice.dart b/lib/services/authservice.dart index 6144ea5..de3f485 100644 --- a/lib/services/authservice.dart +++ b/lib/services/authservice.dart @@ -1,13 +1,16 @@ import 'package:flutter/foundation.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:mileograph_flutter/objects/objects.dart'; import 'package:mileograph_flutter/services/apiService.dart'; -import 'package:shared_preferences/shared_preferences.dart'; class AuthService extends ChangeNotifier { final ApiService api; static const _tokenKey = 'auth_token'; bool _restoring = false; + // secure storage instance + final FlutterSecureStorage _storage = const FlutterSecureStorage(); + AuthService({required this.api}); AuthenticatedUserData? _user; @@ -73,9 +76,10 @@ class AuthService extends ChangeNotifier { if (_restoring || _user != null) return; _restoring = true; try { - final prefs = await SharedPreferences.getInstance(); - final token = prefs.getString(_tokenKey); + // read token from secure storage + final token = await _storage.read(key: _tokenKey); if (token == null || token.isEmpty) return; + final userResponse = await api.get( '/users/me', headers: { @@ -83,6 +87,7 @@ class AuthService extends ChangeNotifier { 'accept': 'application/json', }, ); + setLoginData( userId: userResponse['user_id'], username: userResponse['username'], @@ -98,13 +103,11 @@ class AuthService extends ChangeNotifier { } Future _persistToken(String token) async { - final prefs = await SharedPreferences.getInstance(); - await prefs.setString(_tokenKey, token); + await _storage.write(key: _tokenKey, value: token); } Future _clearToken() async { - final prefs = await SharedPreferences.getInstance(); - await prefs.remove(_tokenKey); + await _storage.delete(key: _tokenKey); } Future register({ @@ -126,9 +129,13 @@ class AuthService extends ChangeNotifier { await api.postForm('/register', formData); } - void logout() { + Future handleTokenExpired() async { _user = null; - _clearToken(); + await _clearToken(); notifyListeners(); } + + void logout() { + handleTokenExpired(); // reuse + } } diff --git a/lib/services/tokenStorageService.dart b/lib/services/tokenStorageService.dart new file mode 100644 index 0000000..b82ed79 --- /dev/null +++ b/lib/services/tokenStorageService.dart @@ -0,0 +1,36 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class TokenStorageService { + // Singleton pattern (optional but usually handy for services) + TokenStorageService._internal(); + + static final TokenStorageService _instance = TokenStorageService._internal(); + + factory TokenStorageService() => _instance; + + static const _tokenKey = 'auth_token'; + + // Use const constructor for secure storage + final FlutterSecureStorage _storage = const FlutterSecureStorage(); + + /// Save or update the token + Future setToken(String token) async { + await _storage.write(key: _tokenKey, value: token); + } + + /// Retrieve the stored token (null if none) + Future getToken() async { + return _storage.read(key: _tokenKey); + } + + /// Delete the token + Future clearToken() async { + await _storage.delete(key: _tokenKey); + } + + /// Optional: check quickly if a token exists + Future hasToken() async { + final token = await getToken(); + return token != null && token.isNotEmpty; + } +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 675b719..4b6d98a 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,9 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 3e303c1..e19acfc 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color + flutter_secure_storage_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b5dc9c5..6fe77f3 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,9 +6,13 @@ import FlutterMacOS import Foundation import dynamic_color +import flutter_secure_storage_darwin +import path_provider_foundation import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) + FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 136d950..e9e1239 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -94,6 +94,54 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: da922f2aab2d733db7e011a6bcc4a825b844892d4edd6df83ff156b09a9b2e40 + url: "https://pub.dev" + source: hosted + version: "10.0.0" + flutter_secure_storage_darwin: + dependency: transitive + description: + name: flutter_secure_storage_darwin + sha256: "8878c25136a79def1668c75985e8e193d9d7d095453ec28730da0315dc69aee3" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "2b5c76dce569ab752d55a1cee6a2242bcc11fdba927078fb88c503f150767cda" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: "8ceea1223bee3c6ac1a22dabd8feefc550e4729b3675de4b5900f55afcb435d6" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: "6a1137df62b84b54261dca582c1c09ea72f4f9a4b2fcee21b025964132d5d0c3" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: "3b7c8e068875dfd46719ff57c90d8c459c87f2302ed6b00ff006b3c9fcad1613" + url: "https://pub.dev" + source: hosted + version: "4.1.0" flutter_test: dependency: "direct dev" description: flutter @@ -216,6 +264,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "3b4c1fc3aa55ddc9cd4aa6759984330d5c8e66aa7702a6223c61540dc6380c37" + url: "https://pub.dev" + source: hosted + version: "2.2.19" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" + url: "https://pub.dev" + source: hosted + version: "2.4.2" path_provider_linux: dependency: transitive description: @@ -405,6 +477,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e650c32..98f00ae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,7 @@ dependencies: http: ^1.4.0 provider: ^6.1.5 dynamic_color: ^1.6.6 + flutter_secure_storage: ^10.0.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index e4899a6..76514d8 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,11 @@ #include "generated_plugin_registrant.h" #include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 841e8c4..a1b5170 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color + flutter_secure_storage_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST