@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 +4 -0
- package/README.md +16 -0
- package/dist/index.d.ts +25 -1
- package/dist/index.js +26 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
|
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
|
|
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":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;;;;;;;;;;AAuBH,4DAYC;AAGD,sDAYC;AAaD,0CAgBC;AAsCD,0DA4CC;AA/JD,sCAOuB;AACvB,qCAAkE;AAOlE,2CAAyB;AACzB,mDAAiC;AAEjC,kFAAkF;AAElF,gFAAgF;AAChF,SAAgB,wBAAwB,CACtC,KAA8B,EAC9B,UAA+B,EAC/B,IAAa;IAEb,OAAO;QACL,qEAAqE;QACrE,SAAS,EAAE,KAAK,CAAC,SAAmB;QACpC,kBAAkB,EAAE,UAAU,CAAC,QAAQ,CAAC,iBAAiB;QACzD,gBAAgB,EAAE,UAAU,CAAC,QAAQ,CAAC,cAAc;QACpD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1B,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,SAAgB,qBAAqB,CACnC,KAA8B,EAC9B,SAA2B;IAE3B,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAgB;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAmB;QACpC,aAAa,EAAE,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE;QACpD,kBAAkB,EAAE,SAAS,CAAC,QAAQ,CAAC,iBAAiB;QACxD,gBAAgB,EAAE,SAAS,CAAC,QAAQ,CAAC,cAAc;QACnD,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,SAAS;KACxC,CAAC;AACJ,CAAC;AASD;;;GAGG;AACI,KAAK,UAAU,eAAe,CAAC,IAKrC;IACC,MAAM,MAAM,GAAG,IAAA,yBAAgB,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE7C,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAA0B,8BAA8B,EAAE,EAAE,CAAC,CAAC;IAC7F,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IAEzE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,wBAAwB,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE,IAAI,CAAC,CAAC;IACxE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAClD,CAAC;AAwBD;;;;;;;;;;;;;GAaG;AACI,KAAK,UAAU,uBAAuB,CAAC,IAO7C;IACC,MAAM,MAAM,GAAG,IAAA,yBAAgB,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAE/C,MAAM,KAAK,GAAG,MAAM,IAAA,uBAAkB,EAAC,MAAM,EAAE;QAC7C,OAAO,EACL,YAAY,IAAI,eAAe;YAC7B,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE;gBAC3B,IAAI,CAAC,KAAK;oBAAE,OAAO,YAAY,IAAI,IAAI,CAAC;gBACxC,IAAI,CAAC,eAAe;oBAAE,OAAO,IAAI,CAAC;gBAClC,MAAM,QAAQ,GAAG,MAAM,IAAA,0BAAqB,EAAC,MAAM,CAAC,CAAC;gBACrD,OAAO,eAAe,CAAC;oBACrB,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,IAAI,IAAI;oBAC9C,OAAO,EAAE,OAAO,IAAI,kBAAkB;iBACvC,CAAC,CAAC;YACL,CAAC;YACH,CAAC,CAAC,IAAI;KACX,CAAC,CAAC;IACH,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IAE/E,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAC9B,oCAAoC,EACpC,IAAI,CACL,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IAElF,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;QACtD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlasauth/expo-passkeys",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
7
|
+
"@atlasauth/js": "0.16.0"
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
10
|
"react-native": ">=0.73",
|