From ccf96e27716e660cee9c1731411751efe29d735e Mon Sep 17 00:00:00 2001 From: heznpc Date: Thu, 2 Jul 2026 21:04:02 +0900 Subject: [PATCH] fix: guard secure store session writes --- .github/workflows/cd-android.yml | 4 ++-- .github/workflows/cd-ios.yml | 4 ++-- .github/workflows/dependabot-auto-merge.yml | 7 +++++++ README.md | 2 ++ lib/auth-context.js | 20 +++++++++++++++++++- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cd-android.yml b/.github/workflows/cd-android.yml index d16ab3b..0e8a12d 100644 --- a/.github/workflows/cd-android.yml +++ b/.github/workflows/cd-android.yml @@ -58,7 +58,7 @@ jobs: fi - name: Setup Expo CLI - uses: expo/expo-github-action@v8 + uses: expo/expo-github-action@c7b66a9c327a43a8fa7c0158e7f30d6040d2481e # v8 with: eas-version: latest token: ${{ secrets.EXPO_TOKEN }} @@ -70,7 +70,7 @@ jobs: run: eas submit --platform android --profile production --non-interactive - name: Create GitHub Release - uses: softprops/action-gh-release@v3 + uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3 with: tag_name: v${{ steps.version.outputs.version }}-android name: v${{ steps.version.outputs.version }} (Android) diff --git a/.github/workflows/cd-ios.yml b/.github/workflows/cd-ios.yml index 3e74670..21cc65f 100644 --- a/.github/workflows/cd-ios.yml +++ b/.github/workflows/cd-ios.yml @@ -58,7 +58,7 @@ jobs: fi - name: Setup Expo CLI - uses: expo/expo-github-action@v8 + uses: expo/expo-github-action@c7b66a9c327a43a8fa7c0158e7f30d6040d2481e # v8 with: eas-version: latest token: ${{ secrets.EXPO_TOKEN }} @@ -70,7 +70,7 @@ jobs: run: eas submit --platform ios --profile production --non-interactive - name: Create GitHub Release - uses: softprops/action-gh-release@v3 + uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3 with: tag_name: v${{ steps.version.outputs.version }}-ios name: v${{ steps.version.outputs.version }} (iOS) diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 3e8adf4..fbf7f86 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -7,7 +7,14 @@ permissions: pull-requests: write jobs: + # Run the same checks as ci.yml so the merge below is gated on CI even on + # repos that haven't configured required-status-check branch protection. + ci: + if: github.event.pull_request.user.login == 'dependabot[bot]' + uses: ./.github/workflows/ci.yml + auto-merge: + needs: ci if: github.event.pull_request.user.login == 'dependabot[bot]' runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index 55b4818..3ce43c0 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,8 @@ Google sign-in is **built in** with `expo-auth-session` + `expo-secure-store`. R Without client IDs, the login button surfaces a clear error message — it won't crash. Swap providers by replacing `expo-auth-session/providers/google` inside `lib/auth-context.js`. +> **SecureStore 2048-byte limit (Android).** `expo-secure-store` warns (and may silently drop the write) when a single value exceeds 2048 bytes. To stay well under it, only the `id_token` and minimal user claims are persisted — the access token is kept in memory only — and the write is read back and verified so a dropped write surfaces as a sign-in error instead of a session that vanishes on the next cold start. If you persist extra fields, keep the serialized blob small. + Docs: [Expo Google authentication guide](https://docs.expo.dev/guides/google-authentication/). ### What about TypeScript? diff --git a/lib/auth-context.js b/lib/auth-context.js index 3171d2e..c387ce0 100644 --- a/lib/auth-context.js +++ b/lib/auth-context.js @@ -119,7 +119,25 @@ export async function handleAuthResult(response, setSession, deps = {}) { 'Google sign-in returned no usable id_token; not persisting session.', ); } - await store.setItemAsync(STORAGE_KEY, JSON.stringify(session)); + // Persist only what restore actually needs (the id_token + minimal user + // claims). The access token is never read on cold start, so keep it out of + // the SecureStore blob — this trims the payload well clear of Android + // SecureStore's 2048-byte per-value warning threshold, above which the + // write can be silently dropped (only a console.warn, no throw). + const persisted = { user, tokens: { idToken } }; + const serialized = JSON.stringify(persisted); + await store.setItemAsync(STORAGE_KEY, serialized); + // Verify-after-write: expo-secure-store may drop an oversized value without + // throwing, so read it back. If it didn't land, surface an error via the + // caller's .catch -> setError instead of pretending the session persisted. + const readBack = await store.getItemAsync(STORAGE_KEY); + if (readBack !== serialized) { + throw new Error( + 'Failed to persist session to secure storage (value may exceed the ' + + 'platform size limit); not treating sign-in as complete.', + ); + } + // Keep the access token in in-memory state only (not persisted above). setSession(session); return; }