electron-webauthn 1.1.1 → 1.3.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.
Files changed (40) hide show
  1. package/README.md +20 -2
  2. package/dist/index.d.ts +10 -3
  3. package/dist/index.js +96 -3
  4. package/package.json +16 -12
  5. package/dist/additional-objc/ASCPublicKeyCredentialDescriptor.d.ts +0 -12
  6. package/dist/additional-objc/ASCPublicKeyCredentialDescriptor.js +0 -2
  7. package/dist/create/authorization-controller.d.ts +0 -10
  8. package/dist/create/authorization-controller.js +0 -77
  9. package/dist/create/handler.d.ts +0 -43
  10. package/dist/create/handler.js +0 -224
  11. package/dist/create/internal-handler.d.ts +0 -35
  12. package/dist/create/internal-handler.js +0 -207
  13. package/dist/get/authorization-controller.d.ts +0 -5
  14. package/dist/get/authorization-controller.js +0 -37
  15. package/dist/get/handler.d.ts +0 -38
  16. package/dist/get/handler.js +0 -137
  17. package/dist/get/internal-handler.d.ts +0 -24
  18. package/dist/get/internal-handler.js +0 -169
  19. package/dist/helpers/client-data.d.ts +0 -14
  20. package/dist/helpers/client-data.js +0 -36
  21. package/dist/helpers/index.d.ts +0 -8
  22. package/dist/helpers/index.js +0 -48
  23. package/dist/helpers/origin.d.ts +0 -19
  24. package/dist/helpers/origin.js +0 -106
  25. package/dist/helpers/presentation.d.ts +0 -1
  26. package/dist/helpers/presentation.js +0 -11
  27. package/dist/helpers/prf.d.ts +0 -5
  28. package/dist/helpers/prf.js +0 -5
  29. package/dist/helpers/public-key.d.ts +0 -1
  30. package/dist/helpers/public-key.js +0 -49
  31. package/dist/helpers/rpid.d.ts +0 -13
  32. package/dist/helpers/rpid.js +0 -59
  33. package/dist/helpers/types.d.ts +0 -1
  34. package/dist/helpers/types.js +0 -1
  35. package/dist/helpers/validation.d.ts +0 -3
  36. package/dist/helpers/validation.js +0 -9
  37. package/dist/list/handler.d.ts +0 -2
  38. package/dist/list/handler.js +0 -71
  39. package/dist/list/types.d.ts +0 -14
  40. package/dist/list/types.js +0 -1
package/README.md CHANGED
@@ -8,6 +8,8 @@ Add native WebAuthn/FIDO2 support to Electron on macOS using its AuthenticationS
8
8
 
9
9
  This package provides JavaScript bindings to Apple's AuthenticationServices framework, allowing you to perform WebAuthn credential creation (registration) and assertions (authentication/signing) in your Electron applications using W3C WebAuthn-compliant APIs.
10
10
 
11
+ The root `electron-webauthn` package is a cross-platform shim that lazy-loads `@electron-webauthn/macos` only on macOS. This keeps Linux/Windows packaging safe for apps that include but do not use WebAuthn outside macOS.
12
+
11
13
  > [!NOTE]
12
14
  > Although this library is called `electron-webauthn`, it can be used in Node.js and Bun projects as well, not just Electron.
13
15
 
@@ -22,6 +24,7 @@ This package provides JavaScript bindings to Apple's AuthenticationServices fram
22
24
  - Credential authentication (assertions) with existing credentials
23
25
  - Seamless integration with Electron's native window system
24
26
  - Passkey listing via `listPasskeys` (macOS 13.3+)
27
+ - Explicit passkey-listing authorization APIs with `getListPasskeyAuthorizationStatus` and `requestListPasskeyAuthorization`
25
28
  - PRF (Pseudo-Random Function) extension support
26
29
  - Large Blob extension support for reading/writing credential-specific data
27
30
  - User verification preference configuration (preferred, required, discouraged)
@@ -34,6 +37,8 @@ This package provides JavaScript bindings to Apple's AuthenticationServices fram
34
37
 
35
38
  ### Prerequisites
36
39
 
40
+ The following prerequisites apply when running on macOS:
41
+
37
42
  - Node.js / Bun
38
43
  - Xcode Command Line Tools (Run `xcode-select --install` to install)
39
44
  - `pkg-config` from Homebrew (Run `brew install pkgconf` to install)
@@ -84,7 +89,7 @@ This library implements the W3C WebAuthn standard using Apple's native Authentic
84
89
 
85
90
  ## Error Handling
86
91
 
87
- `createCredential`, `getCredential`, and `listPasskeys` all return a result object with a `success` field. Always check this field:
92
+ `createCredential`, `getCredential`, `getListPasskeyAuthorizationStatus`, `requestListPasskeyAuthorization`, and `listPasskeys` all return a result object with a `success` field. Always check this field:
88
93
 
89
94
  ```typescript
90
95
  const result = await createCredential(publicKeyOptions, additionalOptions);
@@ -122,7 +127,14 @@ console.log("Credential ID:", result.data.credentialId);
122
127
  `listPasskeys` returns an `Error` object (not a string code) when unsuccessful:
123
128
 
124
129
  ```typescript
125
- const result = await listPasskeys("example.com");
130
+ const permission = await getListPasskeyAuthorizationStatus();
131
+ if (permission.success && permission.status === "notDetermined") {
132
+ await requestListPasskeyAuthorization();
133
+ }
134
+
135
+ const result = await listPasskeys("example.com", {
136
+ requestAuthorization: false,
137
+ });
126
138
 
127
139
  if (!result.success) {
128
140
  console.error("Failed to list passkeys:", result.error.message);
@@ -149,6 +161,12 @@ console.log(`Found ${result.credentials.length} passkeys`);
149
161
 
150
162
  - **NotAllowedError**: No valid credentials available for the specified rpId
151
163
 
164
+ #### Passkey Authorization / Listing
165
+
166
+ - **`getListPasskeyAuthorizationStatus()`**: Returns `authorized`, `denied`, or `notDetermined` without prompting
167
+ - **`requestListPasskeyAuthorization()`**: Shows the macOS permission prompt only when the current state is `notDetermined`
168
+ - **`listPasskeys(..., { requestAuthorization: false })`**: Returns an `Error` when permission has not been decided yet instead of triggering the prompt automatically
169
+
152
170
  ## Feature Support
153
171
 
154
172
  **Currently Supported:**
package/dist/index.d.ts CHANGED
@@ -1,3 +1,10 @@
1
- export * from "./get/handler.js";
2
- export * from "./create/handler.js";
3
- export * from "./list/handler.js";
1
+ import type { CreateCredentialResult, GetCredentialResult, ListPasskeysOptions, ListPasskeysError, ListPasskeysResult, PasskeyAuthorizationError, PasskeyAuthorizationResult, WebauthnCreateRequestOptions, WebauthnGetRequestOptions, WebauthnModule } from "@electron-webauthn/types";
2
+ export type { CreateCredentialErrorCodes, CreateCredentialResult, CreateCredentialSuccessData, CreateCredentialSuccessResult, CreateCredentialErrorResult, GetCredentialErrorCodes, GetCredentialResult, GetCredentialSuccessData, GetCredentialSuccessResult, GetCredentialErrorResult, ListPasskeysOptions, ListPasskeysError, ListPasskeysResult, PasskeyAuthorizationError, PasskeyAuthorizationResult, PasskeyAuthorizationStatus, PasskeyCredential, WebauthnCreateRequestOptions, WebauthnGetRequestOptions, WebauthnModule, } from "@electron-webauthn/types";
3
+ type MacosLoader = () => Promise<WebauthnModule>;
4
+ export declare function createCredential(publicKeyOptions: PublicKeyCredentialCreationOptions | undefined, additionalOptions: WebauthnCreateRequestOptions): Promise<CreateCredentialResult>;
5
+ export declare function getCredential(publicKeyOptions: PublicKeyCredentialRequestOptions | undefined, additionalOptions: WebauthnGetRequestOptions): Promise<GetCredentialResult>;
6
+ export declare function getListPasskeyAuthorizationStatus(): Promise<PasskeyAuthorizationResult | PasskeyAuthorizationError>;
7
+ export declare function requestListPasskeyAuthorization(): Promise<PasskeyAuthorizationResult | PasskeyAuthorizationError>;
8
+ export declare function listPasskeys(relyingPartyId: string, options?: ListPasskeysOptions): Promise<ListPasskeysResult | ListPasskeysError>;
9
+ export declare function __setMacosLoaderForTesting(loader: MacosLoader | null): void;
10
+ export declare function __setPlatformForTesting(platform: NodeJS.Platform | null): void;
package/dist/index.js CHANGED
@@ -1,3 +1,96 @@
1
- export * from "./get/handler.js";
2
- export * from "./create/handler.js";
3
- export * from "./list/handler.js";
1
+ const unsupportedGetResult = {
2
+ success: false,
3
+ error: "NotAllowedError",
4
+ errorObject: new Error("electron-webauthn is only available on macOS. Install @electron-webauthn/macos on Darwin hosts."),
5
+ };
6
+ const unsupportedCreateResult = {
7
+ success: false,
8
+ error: "NotAllowedError",
9
+ errorObject: new Error("electron-webauthn is only available on macOS. Install @electron-webauthn/macos on Darwin hosts."),
10
+ };
11
+ const unsupportedListResult = {
12
+ success: false,
13
+ error: new Error("electron-webauthn is only available on macOS. Install @electron-webauthn/macos on Darwin hosts."),
14
+ };
15
+ const unsupportedPasskeyAuthorizationResult = {
16
+ success: false,
17
+ error: new Error("electron-webauthn is only available on macOS. Install @electron-webauthn/macos on Darwin hosts."),
18
+ };
19
+ let moduleCache = null;
20
+ let modulePromise = null;
21
+ let platformOverride = null;
22
+ const defaultLoader = () => import("@electron-webauthn/macos");
23
+ let macosLoader = defaultLoader;
24
+ function runtimePlatform() {
25
+ return platformOverride ?? process.platform;
26
+ }
27
+ async function getMacosModule() {
28
+ if (runtimePlatform() !== "darwin") {
29
+ return null;
30
+ }
31
+ if (moduleCache) {
32
+ return moduleCache;
33
+ }
34
+ if (modulePromise) {
35
+ return modulePromise;
36
+ }
37
+ modulePromise = (async () => {
38
+ try {
39
+ const module = await macosLoader();
40
+ moduleCache = module;
41
+ return module;
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ finally {
47
+ modulePromise = null;
48
+ }
49
+ })();
50
+ return modulePromise;
51
+ }
52
+ export async function createCredential(publicKeyOptions, additionalOptions) {
53
+ const module = await getMacosModule();
54
+ if (!module) {
55
+ return unsupportedCreateResult;
56
+ }
57
+ return module.createCredential(publicKeyOptions, additionalOptions);
58
+ }
59
+ export async function getCredential(publicKeyOptions, additionalOptions) {
60
+ const module = await getMacosModule();
61
+ if (!module) {
62
+ return unsupportedGetResult;
63
+ }
64
+ return module.getCredential(publicKeyOptions, additionalOptions);
65
+ }
66
+ export async function getListPasskeyAuthorizationStatus() {
67
+ const module = await getMacosModule();
68
+ if (!module) {
69
+ return unsupportedPasskeyAuthorizationResult;
70
+ }
71
+ return module.getListPasskeyAuthorizationStatus();
72
+ }
73
+ export async function requestListPasskeyAuthorization() {
74
+ const module = await getMacosModule();
75
+ if (!module) {
76
+ return unsupportedPasskeyAuthorizationResult;
77
+ }
78
+ return module.requestListPasskeyAuthorization();
79
+ }
80
+ export async function listPasskeys(relyingPartyId, options) {
81
+ const module = await getMacosModule();
82
+ if (!module) {
83
+ return unsupportedListResult;
84
+ }
85
+ return module.listPasskeys(relyingPartyId, options);
86
+ }
87
+ export function __setMacosLoaderForTesting(loader) {
88
+ macosLoader = loader ?? defaultLoader;
89
+ moduleCache = null;
90
+ modulePromise = null;
91
+ }
92
+ export function __setPlatformForTesting(platform) {
93
+ platformOverride = platform;
94
+ moduleCache = null;
95
+ modulePromise = null;
96
+ }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "electron-webauthn",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "repository": "https://github.com/iamEvanYT/electron-webauthn.git",
5
5
  "homepage": "https://github.com/iamEvanYT/electron-webauthn#readme",
6
- "description": "Add support for WebAuthn for Electron.",
6
+ "description": "Cross-platform loader for native WebAuthn support on macOS.",
7
7
  "main": "dist/index.js",
8
8
  "module": "dist/index.js",
9
9
  "types": "dist/index.d.ts",
@@ -15,25 +15,29 @@
15
15
  }
16
16
  },
17
17
  "files": [
18
- "dist/"
18
+ "dist",
19
+ "dist/**"
19
20
  ],
20
21
  "type": "module",
22
+ "workspaces": [
23
+ "packages/*"
24
+ ],
21
25
  "scripts": {
22
- "build": "rm -rf dist && tsc && rm -rf dist/test",
23
- "test": "bun run src/test/index.ts"
26
+ "build": "rm -rf dist && tsc -p tsconfig.json",
27
+ "build:macos": "cd packages/macos && bun run build",
28
+ "build:all": "bun run build && bun run build:macos",
29
+ "test": "bun test"
24
30
  },
25
31
  "devDependencies": {
26
32
  "@types/bun": "latest"
27
33
  },
28
34
  "peerDependencies": {
29
- "typescript": "^5"
35
+ "typescript": "^6.0.2"
30
36
  },
31
37
  "dependencies": {
32
- "@oslojs/webauthn": "^1.0.0",
33
- "objc-js": "^1.3.1",
34
- "objcjs-types": "^0.5.1"
38
+ "@electron-webauthn/types": "^1.3.0"
35
39
  },
36
- "trustedDependencies": [
37
- "objc-js"
38
- ]
40
+ "optionalDependencies": {
41
+ "@electron-webauthn/macos": "^1.3.0"
42
+ }
39
43
  }
@@ -1,12 +0,0 @@
1
- import type { _NSArray, _NSData, _NSObject, _NSSecureCoding } from "objcjs-types/Foundation";
2
- export declare class _ASCPublicKeyCredentialDescriptor extends _NSObject {
3
- static alloc(): _ASCPublicKeyCredentialDescriptor;
4
- static new(): _ASCPublicKeyCredentialDescriptor;
5
- init(): _ASCPublicKeyCredentialDescriptor;
6
- initWithCredentialID$transports$(credentialID: _NSData, allowedTransports: _NSArray | null): _ASCPublicKeyCredentialDescriptor;
7
- credentialID(): _NSData;
8
- transports(): _NSArray | null;
9
- }
10
- export interface _ASCPublicKeyCredentialDescriptor extends _NSSecureCoding {
11
- }
12
- export declare const ASCPublicKeyCredentialDescriptor: typeof _ASCPublicKeyCredentialDescriptor;
@@ -1,2 +0,0 @@
1
- import { AuthenticationServices } from "objcjs-types/AuthenticationServices";
2
- export const ASCPublicKeyCredentialDescriptor = AuthenticationServices.ASCPublicKeyCredentialDescriptor;
@@ -1,10 +0,0 @@
1
- import { NobjcObject } from "objc-js";
2
- import type { ExcludeCredential } from "./internal-handler.js";
3
- import type { ASAuthorizationController } from "objcjs-types/AuthenticationServices";
4
- export interface PublicKeyCredentialParams {
5
- type: "public-key";
6
- algorithm: number;
7
- }
8
- export declare function setControllerState(self: NobjcObject, clientDataHash: Buffer, pubKeyCredParams: PublicKeyCredentialParams[], residentKeyRequired: boolean, excludeCredentialIds: ExcludeCredential[]): void;
9
- export declare function removeControllerState(self: NobjcObject): void;
10
- export declare const WebauthnCreateController: typeof ASAuthorizationController;
@@ -1,77 +0,0 @@
1
- import { NobjcClass, NobjcObject, getPointer } from "objc-js";
2
- import { NSDataFromBuffer } from "objcjs-types/nsdata";
3
- import { NSArrayFromObjects, NSStringFromString } from "objcjs-types/helpers";
4
- import { NSNumber } from "objcjs-types/Foundation";
5
- import { ASCPublicKeyCredentialDescriptor } from "../additional-objc/ASCPublicKeyCredentialDescriptor.js";
6
- const createControllerState = new Map();
7
- function getObjectPointerString(self) {
8
- return getPointer(self).toString("base64");
9
- }
10
- export function setControllerState(self, clientDataHash, pubKeyCredParams, residentKeyRequired, excludeCredentialIds) {
11
- const selfPointer = getObjectPointerString(self);
12
- createControllerState.set(selfPointer, [
13
- clientDataHash,
14
- pubKeyCredParams,
15
- residentKeyRequired,
16
- excludeCredentialIds,
17
- ]);
18
- }
19
- export function removeControllerState(self) {
20
- const selfPointer = getObjectPointerString(self);
21
- createControllerState.delete(selfPointer);
22
- }
23
- export const WebauthnCreateController = NobjcClass.define({
24
- name: "WebauthnCreateController",
25
- superclass: "ASAuthorizationController",
26
- methods: {
27
- _requestContextWithRequests$error$: {
28
- types: "@@:@^@",
29
- implementation: (self, requests, outError) => {
30
- const context = NobjcClass.super(self, "_requestContextWithRequests$error$", requests, outError);
31
- const selfPointer = getObjectPointerString(self);
32
- if (context && createControllerState.has(selfPointer)) {
33
- let isSecurityKey = false;
34
- let registrationOptions = context.platformKeyCredentialCreationOptions();
35
- if (!registrationOptions) {
36
- registrationOptions =
37
- context.securityKeyCredentialCreationOptions();
38
- isSecurityKey = true;
39
- }
40
- const [clientDataHash, pubKeyCredParams, residentKeyRequired, excludeCredentials,] = createControllerState.get(selfPointer);
41
- registrationOptions.setClientDataHash$(NSDataFromBuffer(clientDataHash));
42
- registrationOptions.setChallenge$(null);
43
- const supportedAlgos = [];
44
- for (const param of pubKeyCredParams) {
45
- if (param.type === "public-key") {
46
- const nsNum = NSNumber.numberWithInteger$(param.algorithm);
47
- supportedAlgos.push(nsNum);
48
- }
49
- }
50
- if (supportedAlgos.length > 0) {
51
- registrationOptions.setSupportedAlgorithmIdentifiers$(NSArrayFromObjects(supportedAlgos));
52
- }
53
- if (!isSecurityKey) {
54
- registrationOptions.setShouldRequireResidentKey$(residentKeyRequired);
55
- }
56
- const excludeList = [];
57
- for (const cred of excludeCredentials) {
58
- const transports = [];
59
- if (cred.transports) {
60
- for (const transport of cred.transports) {
61
- transports.push(NSStringFromString(transport));
62
- }
63
- }
64
- const credentialID = NSDataFromBuffer(cred.id);
65
- const transportsArray = NSArrayFromObjects(transports);
66
- const initializedDescriptor = ASCPublicKeyCredentialDescriptor.alloc().initWithCredentialID$transports$(credentialID, transportsArray);
67
- excludeList.push(initializedDescriptor);
68
- }
69
- if (excludeList.length > 0) {
70
- registrationOptions.setExcludedCredentials$(NSArrayFromObjects(excludeList));
71
- }
72
- }
73
- return context;
74
- },
75
- },
76
- },
77
- });
@@ -1,43 +0,0 @@
1
- export type CreateCredentialErrorCodes = "TypeError" | "AbortError" | "NotAllowedError" | "SecurityError" | "InvalidStateError";
2
- export interface CreateCredentialSuccessData {
3
- credentialId: string;
4
- clientDataJSON: string;
5
- attestationObject: string;
6
- authData: string;
7
- publicKey: string;
8
- publicKeyAlgorithm: number;
9
- transports: string[];
10
- extensions: {
11
- credProps?: {
12
- rk: boolean;
13
- };
14
- prf?: {
15
- enabled?: boolean;
16
- results: {
17
- first?: string;
18
- second?: string;
19
- };
20
- };
21
- largeBlob?: {
22
- supported?: boolean;
23
- };
24
- };
25
- }
26
- interface WebauthnCreateRequestOptions {
27
- currentOrigin: string;
28
- topFrameOrigin: string | undefined;
29
- isPublicSuffix?: (domain: string) => boolean;
30
- nativeWindowHandle: Buffer;
31
- }
32
- interface CreateCredentialSuccessResult {
33
- success: true;
34
- data: CreateCredentialSuccessData;
35
- }
36
- interface CreateCredentialErrorResult {
37
- success: false;
38
- error: CreateCredentialErrorCodes;
39
- errorObject?: Error;
40
- }
41
- export type CreateCredentialResult = CreateCredentialSuccessResult | CreateCredentialErrorResult;
42
- export declare function createCredential(publicKeyOptions: PublicKeyCredentialCreationOptions | undefined, additionalOptions: WebauthnCreateRequestOptions): Promise<CreateCredentialResult>;
43
- export {};
@@ -1,224 +0,0 @@
1
- import { bufferSourceToBuffer, bufferToBase64Url } from "../helpers/index.js";
2
- import { isRpIdAllowedForOrigin } from "../helpers/rpid.js";
3
- import { isNumber, isObject, isString } from "../helpers/validation.js";
4
- import { createCredentialInternal, } from "./internal-handler.js";
5
- function getExtensionsConfiguration(extensionsData) {
6
- if (!(extensionsData && typeof extensionsData === "object")) {
7
- return {
8
- extensions: [],
9
- };
10
- }
11
- const extensions = [];
12
- let largeBlobSupport;
13
- if (isObject(extensionsData.largeBlob)) {
14
- extensions.push("largeBlob");
15
- const largeBlobConfig = extensionsData.largeBlob;
16
- if (largeBlobConfig.support === "required") {
17
- largeBlobSupport = "required";
18
- }
19
- else if (largeBlobConfig.support === "preferred") {
20
- largeBlobSupport = "preferred";
21
- }
22
- }
23
- let prf;
24
- if (isObject(extensionsData.prf)) {
25
- const prfEval = extensionsData.prf.eval;
26
- if (prfEval) {
27
- const first = bufferSourceToBuffer(prfEval.first);
28
- const second = bufferSourceToBuffer(prfEval.second);
29
- if (first) {
30
- prf = {
31
- first: first ? first : null,
32
- second: second ? second : undefined,
33
- };
34
- }
35
- else {
36
- console.warn("[electron-webauthn] prf is enabled but prf.first is not valid, skipping PRF evaluation");
37
- }
38
- }
39
- }
40
- return {
41
- extensions,
42
- largeBlobSupport,
43
- prf,
44
- };
45
- }
46
- export async function createCredential(publicKeyOptions, additionalOptions) {
47
- if (!publicKeyOptions) {
48
- return null;
49
- }
50
- const rpInfo = publicKeyOptions.rp;
51
- if (!isObject(rpInfo)) {
52
- return { success: false, error: "TypeError" };
53
- }
54
- let rpId = rpInfo.id;
55
- if (!rpId) {
56
- try {
57
- const url = new URL(additionalOptions.currentOrigin);
58
- rpId = url.hostname;
59
- }
60
- catch { }
61
- }
62
- if (!isString(rpId)) {
63
- return { success: false, error: "TypeError" };
64
- }
65
- let timeout = publicKeyOptions.timeout;
66
- if (!isNumber(timeout) || timeout <= 0) {
67
- timeout = 10 * 60 * 1000;
68
- }
69
- else if (timeout > 60 * 60 * 1000) {
70
- timeout = 60 * 60 * 1000;
71
- }
72
- const challenge = bufferSourceToBuffer(publicKeyOptions.challenge);
73
- if (!challenge) {
74
- return { success: false, error: "TypeError" };
75
- }
76
- if (!isObject(publicKeyOptions.user)) {
77
- return { success: false, error: "TypeError" };
78
- }
79
- const userName = publicKeyOptions.user.name;
80
- const userDisplayName = publicKeyOptions.user.displayName;
81
- if (!isString(userName) || !isString(userDisplayName)) {
82
- return { success: false, error: "TypeError" };
83
- }
84
- const userID = bufferSourceToBuffer(publicKeyOptions.user.id);
85
- if (!userID) {
86
- return { success: false, error: "TypeError" };
87
- }
88
- const attestationPreference = publicKeyOptions.attestation;
89
- if (attestationPreference && !isString(attestationPreference)) {
90
- return { success: false, error: "TypeError" };
91
- }
92
- const pubKeyCredParams = publicKeyOptions.pubKeyCredParams;
93
- const supportedAlgorithmIdentifiers = [];
94
- if (pubKeyCredParams) {
95
- if (Array.isArray(pubKeyCredParams)) {
96
- for (const param of pubKeyCredParams) {
97
- if (!isObject(param))
98
- continue;
99
- if (!isNumber(param.alg))
100
- continue;
101
- supportedAlgorithmIdentifiers.push({
102
- type: "public-key",
103
- algorithm: param.alg,
104
- });
105
- }
106
- }
107
- else {
108
- return { success: false, error: "TypeError" };
109
- }
110
- }
111
- if (supportedAlgorithmIdentifiers.length === 0) {
112
- supportedAlgorithmIdentifiers.push({
113
- type: "public-key",
114
- algorithm: -7,
115
- });
116
- supportedAlgorithmIdentifiers.push({
117
- type: "public-key",
118
- algorithm: -257,
119
- });
120
- }
121
- const excludeCredentials = [];
122
- if (publicKeyOptions.excludeCredentials &&
123
- Array.isArray(publicKeyOptions.excludeCredentials)) {
124
- for (const excludeCredential of publicKeyOptions.excludeCredentials) {
125
- if (!isObject(excludeCredential))
126
- continue;
127
- if (excludeCredential.type !== "public-key")
128
- continue;
129
- const idBuffer = bufferSourceToBuffer(excludeCredential.id);
130
- if (!idBuffer)
131
- continue;
132
- excludeCredentials.push({
133
- id: idBuffer,
134
- transports: excludeCredential.transports,
135
- });
136
- }
137
- }
138
- const { extensions, largeBlobSupport, prf } = getExtensionsConfiguration(publicKeyOptions.extensions);
139
- let residentKeyRequired = false;
140
- let userVerificationPreference = "preferred";
141
- let preferredAuthenticatorAttachment = "all";
142
- if (publicKeyOptions.authenticatorSelection) {
143
- if (publicKeyOptions.authenticatorSelection.residentKey === "required") {
144
- residentKeyRequired = true;
145
- }
146
- else if (publicKeyOptions.authenticatorSelection.requireResidentKey) {
147
- residentKeyRequired = true;
148
- }
149
- const userVerifyParam = publicKeyOptions.authenticatorSelection.userVerification;
150
- if (userVerifyParam === "required") {
151
- userVerificationPreference = "required";
152
- }
153
- else if (userVerifyParam === "discouraged") {
154
- userVerificationPreference = "discouraged";
155
- }
156
- else {
157
- userVerificationPreference = "preferred";
158
- }
159
- const attachment = publicKeyOptions.authenticatorSelection.authenticatorAttachment;
160
- if (attachment === "cross-platform") {
161
- preferredAuthenticatorAttachment = "cross-platform";
162
- }
163
- else if (attachment === "platform") {
164
- preferredAuthenticatorAttachment = "platform";
165
- }
166
- }
167
- const { currentOrigin, topFrameOrigin, isPublicSuffix, nativeWindowHandle } = additionalOptions;
168
- const isRpIdAllowed = isRpIdAllowedForOrigin(currentOrigin, rpId, {
169
- isPublicSuffix,
170
- });
171
- if (!isRpIdAllowed.ok) {
172
- return { success: false, error: "NotAllowedError" };
173
- }
174
- let errorResult = null;
175
- const result = await createCredentialInternal(rpId, challenge, userName, userID, nativeWindowHandle, currentOrigin, timeout, extensions, attestationPreference, supportedAlgorithmIdentifiers, excludeCredentials, residentKeyRequired, preferredAuthenticatorAttachment, userVerificationPreference, {
176
- topFrameOrigin,
177
- largeBlobSupport,
178
- prf,
179
- }).catch((error) => {
180
- errorResult = error;
181
- if (error.message.includes("(com.apple.AuthenticationServices.AuthorizationError error 1006.)")) {
182
- return "InvalidStateError";
183
- }
184
- if (error.message.startsWith("The operation couldn’t be completed.")) {
185
- return "NotAllowedError";
186
- }
187
- return null;
188
- });
189
- if (typeof result === "string") {
190
- return { success: false, error: result, errorObject: errorResult };
191
- }
192
- const data = {
193
- credentialId: bufferToBase64Url(result.credentialId),
194
- clientDataJSON: bufferToBase64Url(result.clientDataJSON),
195
- attestationObject: bufferToBase64Url(result.attestationObject),
196
- authData: bufferToBase64Url(result.authenticatorData),
197
- publicKey: bufferToBase64Url(result.publicKey),
198
- publicKeyAlgorithm: result.publicKeyAlgorithm,
199
- transports: result.transports,
200
- extensions: {},
201
- };
202
- if (publicKeyOptions.extensions?.credProps) {
203
- data.extensions.credProps = {
204
- rk: result.isResidentKey,
205
- };
206
- }
207
- if (result.isLargeBlobSupported !== null) {
208
- data.extensions.largeBlob = {
209
- supported: result.isLargeBlobSupported,
210
- };
211
- }
212
- if (result.isPRFSupported !== null) {
213
- const prfFirst = result.prfFirst;
214
- const prfSecond = result.prfSecond;
215
- data.extensions.prf = {
216
- enabled: result.isPRFSupported,
217
- results: {
218
- first: prfFirst ? bufferToBase64Url(prfFirst) : undefined,
219
- second: prfSecond ? bufferToBase64Url(prfSecond) : undefined,
220
- },
221
- };
222
- }
223
- return { success: true, data };
224
- }
@@ -1,35 +0,0 @@
1
- import { type PRFInput } from "../helpers/prf.js";
2
- import { type PublicKeyCredentialParams } from "./authorization-controller.js";
3
- export type AuthenticatorAttachmentWithExtra = AuthenticatorAttachment | "all";
4
- export interface CreateCredentialResult {
5
- credentialId: Buffer;
6
- clientDataJSON: Buffer;
7
- attestationObject: Buffer;
8
- authenticatorData: Buffer;
9
- attachment: AuthenticatorAttachment;
10
- transports: string[];
11
- isResidentKey: boolean;
12
- publicKeyAlgorithm: number;
13
- publicKey: Buffer;
14
- isLargeBlobSupported: boolean | null;
15
- isPRFSupported: boolean | null;
16
- prfFirst: Buffer | null;
17
- prfSecond: Buffer | null;
18
- }
19
- type CredentialUserVerificationPreference = "required" | "preferred" | "discouraged";
20
- type CredentialAttestationPreference = "direct" | "enterprise" | "indirect" | "none";
21
- declare const VALID_EXTENSIONS: readonly ["largeBlob", "prf"];
22
- export type CredentialCreationExtensions = (typeof VALID_EXTENSIONS)[number];
23
- export type LargeBlobSupport = "required" | "preferred" | "unspecified";
24
- interface CreateCredentialAdditionalOptions {
25
- topFrameOrigin?: string;
26
- userDisplayName?: string;
27
- largeBlobSupport?: LargeBlobSupport;
28
- prf?: PRFInput;
29
- }
30
- export interface ExcludeCredential {
31
- id: Buffer;
32
- transports?: string[];
33
- }
34
- declare function createCredentialInternal(rpid: string, challenge: Buffer, username: string, userID: Buffer, nativeWindowHandle: Buffer, origin: string, timeout: number, enabledExtensions: CredentialCreationExtensions[], attestation: CredentialAttestationPreference, supportedAlgorithmIdentifiers: PublicKeyCredentialParams[], excludeCredentials: ExcludeCredential[], residentKeyRequired?: boolean, preferredAuthenticatorAttachment?: AuthenticatorAttachmentWithExtra, userVerification?: CredentialUserVerificationPreference, additionalOptions?: CreateCredentialAdditionalOptions): Promise<CreateCredentialResult>;
35
- export { createCredentialInternal };