Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

[expo] useLocalCredentials throws "Invalid key provided to SecureStore" during render when the publishable key has base64 padding (=)

已關閉 適合新手
#10,033 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

@RaphaelFakhri 已經在處理了。

開始於 2026年10月2日。

  • #10035 來自 @RaphaelFakhri —— 未關閉

評估

難度
2/5
預估耗時
1-3 小時
新手友好度
88/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
活躍
技術堆疊
react-native, typescript

研究方向

從 packages/expo/src/local-credentials/useLocalCredentials/useLocalCredentials.ts 開始,檢查如何使用 publishable key 組合 SecureStore key 並初始化 hook。在 Android 或 iOS 上使用 issue 中帶有 padding 的 key 重現問題,然後驗證渲染不再擲出錯誤,同時現有的不帶 padding 的 key 仍然可用。

由索引模型根據 Issue 內容生成。

描述

Preliminary Checks
  • I have reviewed the documentation: https://clerk.com/docs
  • I have searched for existing issues: https://github.com/clerk/javascript/issues
  • I have not already reached out to Clerk support via email or Discord
  • This issue is not a question, general help request, or anything other than a bug report directly related to Clerk
Reproduction

No repo link; the bug is two lines in useLocalCredentials and the snippet below reproduces it on any Android or iOS build.

// ClerkProvider publishableKey = "pk_test_dXNlZnVsLWdhdG9yLTU1LmNsZXJrLmFjY291bnRzLmRldiQ="
// (base64 of "useful-gator-55.clerk.accounts.dev$" WITH its trailing "=" padding;
//  parsePublishableKey() accepts it and the rest of the SDK works normally)
import { useLocalCredentials } from "@clerk/expo/local-credentials";

export default function SignIn() {
  useLocalCredentials(); // throws during render, see below
  return null;
}

The error is thrown by expo-secure-store, inside render, and reaches the nearest error boundary:

Error: Invalid key provided to SecureStore. Keys must not be empty and contain only
alphanumeric characters, ".", "-", and "_".
    at SignInScreen
    ...
    isComponentError: true
Publishable key

pk_test_dXNlZnVsLWdhdG9yLTU1LmNsZXJrLmFjY291bnRzLmRldiQ=

Description

useLocalCredentials composes its two secure-store keys from the raw publishable key and reads the first one with the synchronous getItem as a useState initialiser (packages/expo/src/local-credentials/useLocalCredentials/useLocalCredentials.ts):

const key = `__clerk_local_auth_${publishableKey}_identifier`;
const pkey = `__clerk_local_auth_${publishableKey}_password`;
const [hasLocalAuthCredentials, setHasLocalAuthCredentials] = useState(!!getItem(key));

expo-secure-store validates every key against /^[\w.-]+$/ and throws otherwise. A publishable key is pk_*_ + base64 of <frontend host>$, and the base64 of that string carries = padding whenever len(host) + 1 is not a multiple of 3. parsePublishableKey decodes a padded key fine (atob tolerates either form), so the provider, useSignIn, SSO and everything else work with such a key; only this hook crashes, and it crashes the whole screen that renders it rather than the biometric feature alone.

In our case the padded key was produced by base64-encoding the frontend host ourselves for a release build against a dev instance (the keys the dashboard hands out appear to be emitted without padding, which is presumably why this is rarely hit). But since the SDK accepts padded keys everywhere else, this hook should too, and the failure mode (a render-time throw from a useState initialiser) is disproportionate.

Related: #9870 fixed the same class of problem for the offline resource cache by keying on the full publishable key "with trailing = characters removed". The same treatment here fixes it:

const storeKeyBase = publishableKey.replace(/[^\w.-]/g, "");
const key = `__clerk_local_auth_${storeKeyBase}_identifier`;
const pkey = `__clerk_local_auth_${storeKeyBase}_password`;

Keys without padding are unchanged by the replace, so existing stored credentials keep their key. We are shipping exactly this as a pnpm patch on @clerk/[email protected]; I checked 4.8.0 and it still composes the raw key.

Environment
@clerk/expo 4.2.7 (also inspected 4.8.0 dist)
@clerk/shared 4.28.1
expo 57.0.24
expo-secure-store 57.0.4
expo-local-authentication 57.0.3
react-native 0.86.3
react 19.2.3
node 24.10.0
Device: Pixel, Android 17, release (non dev-client) EAS build
主要語言
TypeScript
星號
1.8k
分支
480
平均合併
1 天 19 小時
30 天內合併 PR
285

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

clerk/javascript 的其他 Issue

查看 clerk/javascript 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。