From af2048b4cdacb059ed64c71ed11102b4d582cd38 Mon Sep 17 00:00:00 2001 From: amaliadwiy Date: Mon, 11 May 2026 17:11:05 +0800 Subject: [PATCH] fix: ganti penyimpanan token dari AsyncStorage ke SecureStore Token autentikasi kini disimpan di Keychain (iOS) / Keystore (Android) sehingga otomatis terhapus saat uninstall dan tidak bisa dipulihkan lewat Google Backup. @notification_permission tetap di AsyncStorage karena bukan data sensitif. --- bun.lock | 3 +++ package.json | 1 + providers/AuthProvider.tsx | 9 +++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bun.lock b/bun.lock index 952f9ff..613e278 100644 --- a/bun.lock +++ b/bun.lock @@ -46,6 +46,7 @@ "expo-modules-core": "^2.5.0", "expo-notifications": "~0.31.3", "expo-router": "~5.1.4", + "expo-secure-store": "~14.2.4", "expo-sharing": "^13.1.5", "expo-splash-screen": "~0.30.8", "expo-status-bar": "~2.2.3", @@ -1103,6 +1104,8 @@ "expo-router": ["expo-router@5.1.11", "", { "dependencies": { "@expo/metro-runtime": "5.0.5", "@expo/schema-utils": "^0.1.0", "@expo/server": "^0.6.3", "@radix-ui/react-slot": "1.2.0", "@react-navigation/bottom-tabs": "^7.3.10", "@react-navigation/native": "^7.1.6", "@react-navigation/native-stack": "^7.3.10", "client-only": "^0.0.1", "invariant": "^2.2.4", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.1.6", "semver": "~7.6.3", "server-only": "^0.0.1", "shallowequal": "^1.1.0" }, "peerDependencies": { "@react-navigation/drawer": "^7.3.9", "expo": "*", "expo-constants": "*", "expo-linking": "*", "react-native-reanimated": "*", "react-native-safe-area-context": "*", "react-native-screens": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@react-navigation/drawer", "react-native-reanimated", "react-server-dom-webpack"] }, "sha512-6YQGqQM2rviVSiU6++hrJDPMByHZ7Oiux4XmgoSaGdaHku5QOn9911f2puEUZh2H9ALKBipw5v3ZkrECBd6Zbw=="], + "expo-secure-store": ["expo-secure-store@14.2.4", "", { "peerDependencies": { "expo": "*" } }, "sha512-ePaz4fnTitJJZjAiybaVYGfLWWyaEtepZC+vs9ZBMhQMfG5HUotIcVsDaSo3FnwpHmgwsLVPY2qFeryI6AtULw=="], + "expo-sharing": ["expo-sharing@13.1.5", "", { "peerDependencies": { "expo": "*" } }, "sha512-X/5sAEiWXL2kdoGE3NO5KmbfcmaCWuWVZXHu8OQef7Yig4ZgHFkGD11HKJ5KqDrDg+SRZe4ISd6MxE7vGUgm4w=="], "expo-splash-screen": ["expo-splash-screen@0.30.10", "", { "dependencies": { "@expo/prebuild-config": "^9.0.10" }, "peerDependencies": { "expo": "*" } }, "sha512-Tt9va/sLENQDQYeOQ6cdLdGvTZ644KR3YG9aRlnpcs2/beYjOX1LHT510EGzVN9ljUTg+1ebEo5GGt2arYtPjw=="], diff --git a/package.json b/package.json index bb9c889..94f34bf 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "expo-modules-core": "^2.5.0", "expo-notifications": "~0.31.3", "expo-router": "~5.1.4", + "expo-secure-store": "~14.2.4", "expo-sharing": "^13.1.5", "expo-splash-screen": "~0.30.8", "expo-status-bar": "~2.2.3", diff --git a/providers/AuthProvider.tsx b/providers/AuthProvider.tsx index a1793cd..94e25d2 100644 --- a/providers/AuthProvider.tsx +++ b/providers/AuthProvider.tsx @@ -2,6 +2,7 @@ import { ConstEnv } from '@/constants/ConstEnv'; import { apiRegisteredToken, apiUnregisteredToken } from '@/lib/api'; import { getToken } from '@/lib/useNotification'; import AsyncStorage from '@react-native-async-storage/async-storage'; +import * as SecureStore from 'expo-secure-store'; import { useQueryClient } from '@tanstack/react-query'; import CryptoES from "crypto-es"; import { router } from "expo-router"; @@ -35,7 +36,7 @@ export default function AuthProvider({ children }: { children: ReactNode }): Rea useEffect(() => { (async (): Promise => { - const token = await AsyncStorage.getItem('@token'); + const token = await SecureStore.getItemAsync('@token'); tokenRef.current = token || ''; setIsLoading(false); })() @@ -62,14 +63,14 @@ export default function AuthProvider({ children }: { children: ReactNode }): Rea } catch (error) { console.error(error) } finally { - await AsyncStorage.setItem('@token', token); + await SecureStore.setItemAsync('@token', token); tokenRef.current = token; router.replace('/home') return true } } else { await apiRegisteredToken({ user: hasil, token: "" }) - await AsyncStorage.setItem('@token', token); + await SecureStore.setItemAsync('@token', token); tokenRef.current = token; router.replace('/home') } @@ -87,7 +88,7 @@ export default function AuthProvider({ children }: { children: ReactNode }): Rea } catch (error) { console.error(error) } finally { - await AsyncStorage.setItem('@token', ''); + await SecureStore.deleteItemAsync('@token'); tokenRef.current = null; queryClient.clear(); router.replace('/');