@atlasauth/expo-passkeys 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @atlasauth/expo-passkeys changelog
2
2
 
3
+ ## 0.2.0 — 2026-10-23
4
+ - **Passkey sign-in takes the sign-in captcha.** `authenticateWithPasskey()` accepts `captchaToken` (sent on the start) and `getCaptchaToken` (asked for a fresh token after a `CAPTCHA_REQUIRED` / `CAPTCHA_FAILED` refusal; the start is retried once). Needed when the app challenges every sign-in.
5
+ - Built on `@atlasauth/js` 0.16.0.
6
+
3
7
  ## 0.1.1
4
8
  - **`frontendApi` is validated at client creation.** A missing, empty or malformed value now throws an
5
9
  `AtlasConfigError` (from `@atlasauth/js`; `code: 'FRONTEND_API_REQUIRED'` or `'FRONTEND_API_INVALID'`)
package/README.md CHANGED
@@ -64,5 +64,21 @@ if (result.status === 'complete' && result.ticket) {
64
64
  }
65
65
  ```
66
66
 
67
+ ### When the app challenges every sign-in
68
+
69
+ If the app asks for a security check on every sign-in, the sign-in start needs a captcha token.
70
+ Pass a solved `captchaToken`, or a `getCaptchaToken` callback, or both. The callback is called after
71
+ the server refuses the start (`CAPTCHA_REQUIRED` or `CAPTCHA_FAILED`). It receives the app's public
72
+ sign-in captcha settings (provider, site key). Run that provider's challenge, for example in a
73
+ WebView, and return the solved token. The start is then retried once with it.
74
+
75
+ ```ts
76
+ const result = await authenticateWithPasskey({
77
+ config,
78
+ passkey: Passkey,
79
+ getCaptchaToken: async ({ captcha }) => solveInWebView(captcha), // your own challenge screen
80
+ });
81
+ ```
82
+
67
83
  `toRegistrationFinishBody` / `toAssertionFinishBody` are exported as pure helpers
68
84
  if you want to drive the two HTTP calls yourself.
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  * register: POST /v1/client/me/passkeys/begin → Passkey.create → /finish
13
13
  * sign in : POST /v1/client/sign_ins/passkey/begin → Passkey.get → /finish
14
14
  */
15
- import type { FieldError, PasskeyAssertionBody, PasskeyRegistrationBody } from '@atlasauth/js';
15
+ import { type FieldError, type FlowCaptcha, type PasskeyAssertionBody, type PasskeyRegistrationBody } from '@atlasauth/js';
16
16
  import { type AtlasFapiConfig } from './client';
17
17
  import type { PasskeyCreateResult, PasskeyGetResult, ReactNativePasskey } from './passkey-native';
18
18
  export * from './client';
@@ -43,13 +43,37 @@ export interface PasskeySignInResult {
43
43
  attemptStatus?: string;
44
44
  errors: FieldError[];
45
45
  }
46
+ /** What {@link authenticateWithPasskey}'s `getCaptchaToken` is asked for. */
47
+ export interface PasskeyCaptchaTokenRequest {
48
+ /** Always `signIn`: the passkey begin takes the sign-in challenge. */
49
+ flow: 'signIn';
50
+ /**
51
+ * The instance's public sign-in captcha settings (provider, site key, widget
52
+ * mode) from `GET /v1/appearance`; null if they could not be read.
53
+ */
54
+ captcha: FlowCaptcha | null;
55
+ /** The refusal that prompted the ask. */
56
+ refused: 'CAPTCHA_REQUIRED' | 'CAPTCHA_FAILED';
57
+ }
46
58
  /**
47
59
  * Sign in with a passkey. Runs begin → platform ceremony → finish and returns
48
60
  * the attempt outcome: `complete` carries a one-time `ticket` to exchange for a
49
61
  * session (hand it to `@atlasauth/expo`), `needs_more` means a factor is still
50
62
  * owed.
63
+ *
64
+ * When the instance challenges every sign-in (an always-on sign-in captcha, or
65
+ * a force-challenge switch) the begin needs a `captcha_token`. Pass a solved
66
+ * `captchaToken` up front, and/or a `getCaptchaToken` callback: after a
67
+ * `CAPTCHA_REQUIRED` / `CAPTCHA_FAILED` refusal it is asked for a FRESH token
68
+ * (run the provider's challenge, e.g. in a WebView, with `captcha.siteKey`) and
69
+ * the begin is retried once. Without either, the refusal comes back as the
70
+ * result's error.
51
71
  */
52
72
  export declare function authenticateWithPasskey(opts: {
53
73
  config: AtlasFapiConfig;
54
74
  passkey: ReactNativePasskey;
75
+ /** A solved sign-in captcha token, sent on the first begin. */
76
+ captchaToken?: string;
77
+ /** Asked for a fresh token after a captcha refusal; the begin is then retried once. */
78
+ getCaptchaToken?: (request: PasskeyCaptchaTokenRequest) => Promise<string | null>;
55
79
  }): Promise<PasskeySignInResult>;
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ exports.toRegistrationFinishBody = toRegistrationFinishBody;
32
32
  exports.toAssertionFinishBody = toAssertionFinishBody;
33
33
  exports.registerPasskey = registerPasskey;
34
34
  exports.authenticateWithPasskey = authenticateWithPasskey;
35
+ const js_1 = require("@atlasauth/js");
35
36
  const client_1 = require("./client");
36
37
  __exportStar(require("./client"), exports);
37
38
  __exportStar(require("./passkey-native"), exports);
@@ -76,10 +77,34 @@ async function registerPasskey(opts) {
76
77
  * the attempt outcome: `complete` carries a one-time `ticket` to exchange for a
77
78
  * session (hand it to `@atlasauth/expo`), `needs_more` means a factor is still
78
79
  * owed.
80
+ *
81
+ * When the instance challenges every sign-in (an always-on sign-in captcha, or
82
+ * a force-challenge switch) the begin needs a `captcha_token`. Pass a solved
83
+ * `captchaToken` up front, and/or a `getCaptchaToken` callback: after a
84
+ * `CAPTCHA_REQUIRED` / `CAPTCHA_FAILED` refusal it is asked for a FRESH token
85
+ * (run the provider's challenge, e.g. in a WebView, with `captcha.siteKey`) and
86
+ * the begin is retried once. Without either, the refusal comes back as the
87
+ * result's error.
79
88
  */
80
89
  async function authenticateWithPasskey(opts) {
81
90
  const client = (0, client_1.createFapiClient)(opts.config);
82
- const begin = await client.post('/v1/client/sign_ins/passkey/begin', {});
91
+ const { captchaToken, getCaptchaToken } = opts;
92
+ const begin = await (0, js_1.beginPasskeySignIn)(client, {
93
+ captcha: captchaToken || getCaptchaToken
94
+ ? async ({ retry, refused }) => {
95
+ if (!retry)
96
+ return captchaToken ?? null;
97
+ if (!getCaptchaToken)
98
+ return null;
99
+ const settings = await (0, js_1.fetchInstanceSettings)(client);
100
+ return getCaptchaToken({
101
+ flow: 'signIn',
102
+ captcha: settings?.captchaFlows.signIn ?? null,
103
+ refused: refused ?? 'CAPTCHA_REQUIRED',
104
+ });
105
+ }
106
+ : null,
107
+ });
83
108
  if (!begin.ok || !begin.data)
84
109
  return { status: 'error', errors: begin.errors };
85
110
  const assertion = await opts.passkey.get(begin.data);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@atlasauth/expo-passkeys",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "dependencies": {
7
- "@atlasauth/js": "0.6.0"
7
+ "@atlasauth/js": "0.16.0"
8
8
  },
9
9
  "peerDependencies": {
10
10
  "react-native": ">=0.73",