@capawesome/capacitor-passkeys 0.0.1
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/CapawesomeCapacitorPasskeys.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +472 -0
- package/android/build.gradle +61 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/Passkeys.java +173 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/PasskeysPlugin.java +115 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/classes/CustomException.java +20 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/classes/CustomExceptions.java +12 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/classes/options/CreatePasskeyOptions.java +38 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/classes/options/GetPasskeyOptions.java +33 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/classes/results/CreatePasskeyResult.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/classes/results/GetPasskeyResult.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/classes/results/IsAvailableResult.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/interfaces/Callback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/interfaces/NonEmptyResultCallback.java +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/passkeys/interfaces/Result.java +7 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +1091 -0
- package/dist/esm/definitions.d.ts +567 -0
- package/dist/esm/definitions.js +47 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +18 -0
- package/dist/esm/web.js +184 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +244 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +247 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Classes/Options/CreatePasskeyOptions.swift +81 -0
- package/ios/Plugin/Classes/Options/GetPasskeyOptions.swift +54 -0
- package/ios/Plugin/Classes/Results/CreatePasskeyResult.swift +28 -0
- package/ios/Plugin/Classes/Results/GetPasskeyResult.swift +34 -0
- package/ios/Plugin/Classes/Results/IsAvailableResult.swift +16 -0
- package/ios/Plugin/Enums/CustomError.swift +65 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/Passkeys.swift +118 -0
- package/ios/Plugin/PasskeysHelper.swift +20 -0
- package/ios/Plugin/PasskeysPlugin.swift +86 -0
- package/ios/Plugin/Protocols/Result.swift +5 -0
- package/package.json +91 -0
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { CapacitorException, WebPlugin } from '@capacitor/core';
|
|
2
|
+
import { ErrorCode } from './definitions';
|
|
3
|
+
export class PasskeysWeb extends WebPlugin {
|
|
4
|
+
async createPasskey(options) {
|
|
5
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
6
|
+
throw PasskeysWeb.createNotSupportedException();
|
|
7
|
+
}
|
|
8
|
+
let credential;
|
|
9
|
+
try {
|
|
10
|
+
credential = await navigator.credentials.create({
|
|
11
|
+
publicKey: PasskeysWeb.parseCreationOptions(options),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw PasskeysWeb.createException(error, ErrorCode.CreateFailed);
|
|
16
|
+
}
|
|
17
|
+
if (!(credential instanceof PublicKeyCredential)) {
|
|
18
|
+
throw new CapacitorException(PasskeysWeb.errorCreateFailed, undefined, {
|
|
19
|
+
code: ErrorCode.CreateFailed,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return PasskeysWeb.serializeCredential(credential);
|
|
23
|
+
}
|
|
24
|
+
async getPasskey(options) {
|
|
25
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
26
|
+
throw PasskeysWeb.createNotSupportedException();
|
|
27
|
+
}
|
|
28
|
+
let credential;
|
|
29
|
+
try {
|
|
30
|
+
credential = await navigator.credentials.get({
|
|
31
|
+
publicKey: PasskeysWeb.parseRequestOptions(options),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
throw PasskeysWeb.createException(error, ErrorCode.GetFailed);
|
|
36
|
+
}
|
|
37
|
+
if (!(credential instanceof PublicKeyCredential)) {
|
|
38
|
+
throw new CapacitorException(PasskeysWeb.errorGetFailed, undefined, {
|
|
39
|
+
code: ErrorCode.GetFailed,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return PasskeysWeb.serializeCredential(credential);
|
|
43
|
+
}
|
|
44
|
+
async isAvailable() {
|
|
45
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
46
|
+
return { available: false };
|
|
47
|
+
}
|
|
48
|
+
const available = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
|
|
49
|
+
return { available };
|
|
50
|
+
}
|
|
51
|
+
static arrayBufferToBase64Url(buffer) {
|
|
52
|
+
const bytes = new Uint8Array(buffer);
|
|
53
|
+
let binary = '';
|
|
54
|
+
for (const byte of bytes) {
|
|
55
|
+
binary += String.fromCharCode(byte);
|
|
56
|
+
}
|
|
57
|
+
return btoa(binary)
|
|
58
|
+
.replace(/\+/g, '-')
|
|
59
|
+
.replace(/\//g, '_')
|
|
60
|
+
.replace(/=+$/, '');
|
|
61
|
+
}
|
|
62
|
+
static base64UrlToArrayBuffer(value) {
|
|
63
|
+
let base64 = value.replace(/-/g, '+').replace(/_/g, '/');
|
|
64
|
+
while (base64.length % 4 > 0) {
|
|
65
|
+
base64 += '=';
|
|
66
|
+
}
|
|
67
|
+
const binary = atob(base64);
|
|
68
|
+
const bytes = new Uint8Array(binary.length);
|
|
69
|
+
for (let index = 0; index < binary.length; index++) {
|
|
70
|
+
bytes[index] = binary.charCodeAt(index);
|
|
71
|
+
}
|
|
72
|
+
return bytes.buffer;
|
|
73
|
+
}
|
|
74
|
+
static createException(error, fallbackCode) {
|
|
75
|
+
let code = fallbackCode;
|
|
76
|
+
if (error instanceof DOMException) {
|
|
77
|
+
if (error.name === 'NotAllowedError') {
|
|
78
|
+
code = ErrorCode.Canceled;
|
|
79
|
+
}
|
|
80
|
+
else if (error.name === 'SecurityError') {
|
|
81
|
+
code = ErrorCode.DomainNotAssociated;
|
|
82
|
+
}
|
|
83
|
+
else if (error.name === 'NotSupportedError') {
|
|
84
|
+
code = ErrorCode.NotSupported;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const message = error instanceof Error ? error.message : 'An unknown error has occurred.';
|
|
88
|
+
return new CapacitorException(message, undefined, { code });
|
|
89
|
+
}
|
|
90
|
+
static createNotSupportedException() {
|
|
91
|
+
return new CapacitorException(PasskeysWeb.errorNotSupported, undefined, {
|
|
92
|
+
code: ErrorCode.NotSupported,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
static isWebAuthnSupported() {
|
|
96
|
+
return (typeof window !== 'undefined' &&
|
|
97
|
+
typeof window.PublicKeyCredential !== 'undefined');
|
|
98
|
+
}
|
|
99
|
+
static parseCreationOptions(options) {
|
|
100
|
+
var _a;
|
|
101
|
+
if (typeof PublicKeyCredential.parseCreationOptionsFromJSON === 'function') {
|
|
102
|
+
return PublicKeyCredential.parseCreationOptionsFromJSON(options);
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
attestation: options.attestation,
|
|
106
|
+
authenticatorSelection: options.authenticatorSelection,
|
|
107
|
+
challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),
|
|
108
|
+
excludeCredentials: (_a = options.excludeCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({
|
|
109
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),
|
|
110
|
+
transports: credential.transports,
|
|
111
|
+
type: credential.type,
|
|
112
|
+
})),
|
|
113
|
+
pubKeyCredParams: options.pubKeyCredParams,
|
|
114
|
+
rp: options.rp,
|
|
115
|
+
timeout: options.timeout,
|
|
116
|
+
user: {
|
|
117
|
+
displayName: options.user.displayName,
|
|
118
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(options.user.id),
|
|
119
|
+
name: options.user.name,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
static parseRequestOptions(options) {
|
|
124
|
+
var _a;
|
|
125
|
+
if (typeof PublicKeyCredential.parseRequestOptionsFromJSON === 'function') {
|
|
126
|
+
return PublicKeyCredential.parseRequestOptionsFromJSON(options);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
allowCredentials: (_a = options.allowCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({
|
|
130
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),
|
|
131
|
+
transports: credential.transports,
|
|
132
|
+
type: credential.type,
|
|
133
|
+
})),
|
|
134
|
+
challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),
|
|
135
|
+
rpId: options.rpId,
|
|
136
|
+
timeout: options.timeout,
|
|
137
|
+
userVerification: options.userVerification,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
static serializeCredential(credential) {
|
|
141
|
+
var _a;
|
|
142
|
+
if (typeof credential.toJSON === 'function') {
|
|
143
|
+
return credential.toJSON();
|
|
144
|
+
}
|
|
145
|
+
const authenticatorAttachment = ((_a = credential.authenticatorAttachment) !== null && _a !== void 0 ? _a : undefined);
|
|
146
|
+
const id = credential.id;
|
|
147
|
+
const rawId = PasskeysWeb.arrayBufferToBase64Url(credential.rawId);
|
|
148
|
+
if (credential.response instanceof AuthenticatorAssertionResponse) {
|
|
149
|
+
const response = credential.response;
|
|
150
|
+
return {
|
|
151
|
+
authenticatorAttachment,
|
|
152
|
+
id,
|
|
153
|
+
rawId,
|
|
154
|
+
response: {
|
|
155
|
+
authenticatorData: PasskeysWeb.arrayBufferToBase64Url(response.authenticatorData),
|
|
156
|
+
clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),
|
|
157
|
+
signature: PasskeysWeb.arrayBufferToBase64Url(response.signature),
|
|
158
|
+
userHandle: response.userHandle
|
|
159
|
+
? PasskeysWeb.arrayBufferToBase64Url(response.userHandle)
|
|
160
|
+
: undefined,
|
|
161
|
+
},
|
|
162
|
+
type: 'public-key',
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const response = credential.response;
|
|
166
|
+
return {
|
|
167
|
+
authenticatorAttachment,
|
|
168
|
+
id,
|
|
169
|
+
rawId,
|
|
170
|
+
response: {
|
|
171
|
+
attestationObject: PasskeysWeb.arrayBufferToBase64Url(response.attestationObject),
|
|
172
|
+
clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),
|
|
173
|
+
transports: typeof response.getTransports === 'function'
|
|
174
|
+
? response.getTransports()
|
|
175
|
+
: undefined,
|
|
176
|
+
},
|
|
177
|
+
type: 'public-key',
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
PasskeysWeb.errorCreateFailed = 'The passkey could not be created.';
|
|
182
|
+
PasskeysWeb.errorGetFailed = 'The passkey could not be retrieved.';
|
|
183
|
+
PasskeysWeb.errorNotSupported = 'Passkeys are not supported in this browser.';
|
|
184
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { CapacitorException, WebPlugin } from '@capacitor/core';\n\nimport { ErrorCode } from './definitions';\nimport type {\n CreatePasskeyOptions,\n CreatePasskeyResult,\n GetPasskeyOptions,\n GetPasskeyResult,\n IsAvailableResult,\n PasskeyAuthenticatorAttachment,\n PasskeyTransport,\n PasskeysPlugin,\n} from './definitions';\n\nexport class PasskeysWeb extends WebPlugin implements PasskeysPlugin {\n private static readonly errorCreateFailed =\n 'The passkey could not be created.';\n private static readonly errorGetFailed =\n 'The passkey could not be retrieved.';\n private static readonly errorNotSupported =\n 'Passkeys are not supported in this browser.';\n\n async createPasskey(\n options: CreatePasskeyOptions,\n ): Promise<CreatePasskeyResult> {\n if (!PasskeysWeb.isWebAuthnSupported()) {\n throw PasskeysWeb.createNotSupportedException();\n }\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create({\n publicKey: PasskeysWeb.parseCreationOptions(options),\n });\n } catch (error) {\n throw PasskeysWeb.createException(error, ErrorCode.CreateFailed);\n }\n if (!(credential instanceof PublicKeyCredential)) {\n throw new CapacitorException(PasskeysWeb.errorCreateFailed, undefined, {\n code: ErrorCode.CreateFailed,\n });\n }\n return PasskeysWeb.serializeCredential(credential) as CreatePasskeyResult;\n }\n\n async getPasskey(options: GetPasskeyOptions): Promise<GetPasskeyResult> {\n if (!PasskeysWeb.isWebAuthnSupported()) {\n throw PasskeysWeb.createNotSupportedException();\n }\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.get({\n publicKey: PasskeysWeb.parseRequestOptions(options),\n });\n } catch (error) {\n throw PasskeysWeb.createException(error, ErrorCode.GetFailed);\n }\n if (!(credential instanceof PublicKeyCredential)) {\n throw new CapacitorException(PasskeysWeb.errorGetFailed, undefined, {\n code: ErrorCode.GetFailed,\n });\n }\n return PasskeysWeb.serializeCredential(credential) as GetPasskeyResult;\n }\n\n async isAvailable(): Promise<IsAvailableResult> {\n if (!PasskeysWeb.isWebAuthnSupported()) {\n return { available: false };\n }\n const available =\n await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n return { available };\n }\n\n private static arrayBufferToBase64Url(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n }\n\n private static base64UrlToArrayBuffer(value: string): ArrayBuffer {\n let base64 = value.replace(/-/g, '+').replace(/_/g, '/');\n while (base64.length % 4 > 0) {\n base64 += '=';\n }\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index++) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes.buffer;\n }\n\n private static createException(\n error: unknown,\n fallbackCode: ErrorCode,\n ): CapacitorException {\n let code = fallbackCode;\n if (error instanceof DOMException) {\n if (error.name === 'NotAllowedError') {\n code = ErrorCode.Canceled;\n } else if (error.name === 'SecurityError') {\n code = ErrorCode.DomainNotAssociated;\n } else if (error.name === 'NotSupportedError') {\n code = ErrorCode.NotSupported;\n }\n }\n const message =\n error instanceof Error ? error.message : 'An unknown error has occurred.';\n return new CapacitorException(message, undefined, { code });\n }\n\n private static createNotSupportedException(): CapacitorException {\n return new CapacitorException(PasskeysWeb.errorNotSupported, undefined, {\n code: ErrorCode.NotSupported,\n });\n }\n\n private static isWebAuthnSupported(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.PublicKeyCredential !== 'undefined'\n );\n }\n\n private static parseCreationOptions(\n options: CreatePasskeyOptions,\n ): PublicKeyCredentialCreationOptions {\n if (\n typeof PublicKeyCredential.parseCreationOptionsFromJSON === 'function'\n ) {\n return PublicKeyCredential.parseCreationOptionsFromJSON(options);\n }\n return {\n attestation: options.attestation,\n authenticatorSelection: options.authenticatorSelection,\n challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),\n excludeCredentials: options.excludeCredentials?.map(credential => ({\n id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),\n transports: credential.transports as AuthenticatorTransport[],\n type: credential.type,\n })),\n pubKeyCredParams: options.pubKeyCredParams,\n rp: options.rp,\n timeout: options.timeout,\n user: {\n displayName: options.user.displayName,\n id: PasskeysWeb.base64UrlToArrayBuffer(options.user.id),\n name: options.user.name,\n },\n };\n }\n\n private static parseRequestOptions(\n options: GetPasskeyOptions,\n ): PublicKeyCredentialRequestOptions {\n if (typeof PublicKeyCredential.parseRequestOptionsFromJSON === 'function') {\n return PublicKeyCredential.parseRequestOptionsFromJSON(options);\n }\n return {\n allowCredentials: options.allowCredentials?.map(credential => ({\n id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),\n transports: credential.transports as AuthenticatorTransport[],\n type: credential.type,\n })),\n challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),\n rpId: options.rpId,\n timeout: options.timeout,\n userVerification: options.userVerification,\n };\n }\n\n private static serializeCredential(\n credential: PublicKeyCredential,\n ): CreatePasskeyResult | GetPasskeyResult {\n if (typeof credential.toJSON === 'function') {\n return credential.toJSON() as unknown as\n | CreatePasskeyResult\n | GetPasskeyResult;\n }\n const authenticatorAttachment = (credential.authenticatorAttachment ??\n undefined) as PasskeyAuthenticatorAttachment | undefined;\n const id = credential.id;\n const rawId = PasskeysWeb.arrayBufferToBase64Url(credential.rawId);\n if (credential.response instanceof AuthenticatorAssertionResponse) {\n const response = credential.response;\n return {\n authenticatorAttachment,\n id,\n rawId,\n response: {\n authenticatorData: PasskeysWeb.arrayBufferToBase64Url(\n response.authenticatorData,\n ),\n clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(\n response.clientDataJSON,\n ),\n signature: PasskeysWeb.arrayBufferToBase64Url(response.signature),\n userHandle: response.userHandle\n ? PasskeysWeb.arrayBufferToBase64Url(response.userHandle)\n : undefined,\n },\n type: 'public-key',\n };\n }\n const response = credential.response as AuthenticatorAttestationResponse;\n return {\n authenticatorAttachment,\n id,\n rawId,\n response: {\n attestationObject: PasskeysWeb.arrayBufferToBase64Url(\n response.attestationObject,\n ),\n clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(\n response.clientDataJSON,\n ),\n transports:\n typeof response.getTransports === 'function'\n ? (response.getTransports() as PasskeyTransport[])\n : undefined,\n },\n type: 'public-key',\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @since 0.1.0
|
|
7
|
+
*/
|
|
8
|
+
exports.ErrorCode = void 0;
|
|
9
|
+
(function (ErrorCode) {
|
|
10
|
+
/**
|
|
11
|
+
* The operation was canceled by the user.
|
|
12
|
+
*
|
|
13
|
+
* @since 0.1.0
|
|
14
|
+
*/
|
|
15
|
+
ErrorCode["Canceled"] = "CANCELED";
|
|
16
|
+
/**
|
|
17
|
+
* The passkey could not be created.
|
|
18
|
+
*
|
|
19
|
+
* @since 0.1.0
|
|
20
|
+
*/
|
|
21
|
+
ErrorCode["CreateFailed"] = "CREATE_FAILED";
|
|
22
|
+
/**
|
|
23
|
+
* The app is not associated with the relying party domain.
|
|
24
|
+
*
|
|
25
|
+
* On **Android**, make sure that the Digital Asset Links file is set up
|
|
26
|
+
* correctly. On **iOS**, make sure that the Associated Domains
|
|
27
|
+
* entitlement is set up correctly.
|
|
28
|
+
*
|
|
29
|
+
* @since 0.1.0
|
|
30
|
+
*/
|
|
31
|
+
ErrorCode["DomainNotAssociated"] = "DOMAIN_NOT_ASSOCIATED";
|
|
32
|
+
/**
|
|
33
|
+
* The passkey could not be retrieved.
|
|
34
|
+
*
|
|
35
|
+
* @since 0.1.0
|
|
36
|
+
*/
|
|
37
|
+
ErrorCode["GetFailed"] = "GET_FAILED";
|
|
38
|
+
/**
|
|
39
|
+
* No matching passkey was found.
|
|
40
|
+
*
|
|
41
|
+
* @since 0.1.0
|
|
42
|
+
*/
|
|
43
|
+
ErrorCode["NoCredential"] = "NO_CREDENTIAL";
|
|
44
|
+
/**
|
|
45
|
+
* Passkeys are not supported on this device.
|
|
46
|
+
*
|
|
47
|
+
* @since 0.1.0
|
|
48
|
+
*/
|
|
49
|
+
ErrorCode["NotSupported"] = "NOT_SUPPORTED";
|
|
50
|
+
})(exports.ErrorCode || (exports.ErrorCode = {}));
|
|
51
|
+
|
|
52
|
+
const Passkeys = core.registerPlugin('Passkeys', {
|
|
53
|
+
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.PasskeysWeb()),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
class PasskeysWeb extends core.WebPlugin {
|
|
57
|
+
async createPasskey(options) {
|
|
58
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
59
|
+
throw PasskeysWeb.createNotSupportedException();
|
|
60
|
+
}
|
|
61
|
+
let credential;
|
|
62
|
+
try {
|
|
63
|
+
credential = await navigator.credentials.create({
|
|
64
|
+
publicKey: PasskeysWeb.parseCreationOptions(options),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
throw PasskeysWeb.createException(error, exports.ErrorCode.CreateFailed);
|
|
69
|
+
}
|
|
70
|
+
if (!(credential instanceof PublicKeyCredential)) {
|
|
71
|
+
throw new core.CapacitorException(PasskeysWeb.errorCreateFailed, undefined, {
|
|
72
|
+
code: exports.ErrorCode.CreateFailed,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return PasskeysWeb.serializeCredential(credential);
|
|
76
|
+
}
|
|
77
|
+
async getPasskey(options) {
|
|
78
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
79
|
+
throw PasskeysWeb.createNotSupportedException();
|
|
80
|
+
}
|
|
81
|
+
let credential;
|
|
82
|
+
try {
|
|
83
|
+
credential = await navigator.credentials.get({
|
|
84
|
+
publicKey: PasskeysWeb.parseRequestOptions(options),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw PasskeysWeb.createException(error, exports.ErrorCode.GetFailed);
|
|
89
|
+
}
|
|
90
|
+
if (!(credential instanceof PublicKeyCredential)) {
|
|
91
|
+
throw new core.CapacitorException(PasskeysWeb.errorGetFailed, undefined, {
|
|
92
|
+
code: exports.ErrorCode.GetFailed,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return PasskeysWeb.serializeCredential(credential);
|
|
96
|
+
}
|
|
97
|
+
async isAvailable() {
|
|
98
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
99
|
+
return { available: false };
|
|
100
|
+
}
|
|
101
|
+
const available = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
|
|
102
|
+
return { available };
|
|
103
|
+
}
|
|
104
|
+
static arrayBufferToBase64Url(buffer) {
|
|
105
|
+
const bytes = new Uint8Array(buffer);
|
|
106
|
+
let binary = '';
|
|
107
|
+
for (const byte of bytes) {
|
|
108
|
+
binary += String.fromCharCode(byte);
|
|
109
|
+
}
|
|
110
|
+
return btoa(binary)
|
|
111
|
+
.replace(/\+/g, '-')
|
|
112
|
+
.replace(/\//g, '_')
|
|
113
|
+
.replace(/=+$/, '');
|
|
114
|
+
}
|
|
115
|
+
static base64UrlToArrayBuffer(value) {
|
|
116
|
+
let base64 = value.replace(/-/g, '+').replace(/_/g, '/');
|
|
117
|
+
while (base64.length % 4 > 0) {
|
|
118
|
+
base64 += '=';
|
|
119
|
+
}
|
|
120
|
+
const binary = atob(base64);
|
|
121
|
+
const bytes = new Uint8Array(binary.length);
|
|
122
|
+
for (let index = 0; index < binary.length; index++) {
|
|
123
|
+
bytes[index] = binary.charCodeAt(index);
|
|
124
|
+
}
|
|
125
|
+
return bytes.buffer;
|
|
126
|
+
}
|
|
127
|
+
static createException(error, fallbackCode) {
|
|
128
|
+
let code = fallbackCode;
|
|
129
|
+
if (error instanceof DOMException) {
|
|
130
|
+
if (error.name === 'NotAllowedError') {
|
|
131
|
+
code = exports.ErrorCode.Canceled;
|
|
132
|
+
}
|
|
133
|
+
else if (error.name === 'SecurityError') {
|
|
134
|
+
code = exports.ErrorCode.DomainNotAssociated;
|
|
135
|
+
}
|
|
136
|
+
else if (error.name === 'NotSupportedError') {
|
|
137
|
+
code = exports.ErrorCode.NotSupported;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const message = error instanceof Error ? error.message : 'An unknown error has occurred.';
|
|
141
|
+
return new core.CapacitorException(message, undefined, { code });
|
|
142
|
+
}
|
|
143
|
+
static createNotSupportedException() {
|
|
144
|
+
return new core.CapacitorException(PasskeysWeb.errorNotSupported, undefined, {
|
|
145
|
+
code: exports.ErrorCode.NotSupported,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
static isWebAuthnSupported() {
|
|
149
|
+
return (typeof window !== 'undefined' &&
|
|
150
|
+
typeof window.PublicKeyCredential !== 'undefined');
|
|
151
|
+
}
|
|
152
|
+
static parseCreationOptions(options) {
|
|
153
|
+
var _a;
|
|
154
|
+
if (typeof PublicKeyCredential.parseCreationOptionsFromJSON === 'function') {
|
|
155
|
+
return PublicKeyCredential.parseCreationOptionsFromJSON(options);
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
attestation: options.attestation,
|
|
159
|
+
authenticatorSelection: options.authenticatorSelection,
|
|
160
|
+
challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),
|
|
161
|
+
excludeCredentials: (_a = options.excludeCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({
|
|
162
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),
|
|
163
|
+
transports: credential.transports,
|
|
164
|
+
type: credential.type,
|
|
165
|
+
})),
|
|
166
|
+
pubKeyCredParams: options.pubKeyCredParams,
|
|
167
|
+
rp: options.rp,
|
|
168
|
+
timeout: options.timeout,
|
|
169
|
+
user: {
|
|
170
|
+
displayName: options.user.displayName,
|
|
171
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(options.user.id),
|
|
172
|
+
name: options.user.name,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
static parseRequestOptions(options) {
|
|
177
|
+
var _a;
|
|
178
|
+
if (typeof PublicKeyCredential.parseRequestOptionsFromJSON === 'function') {
|
|
179
|
+
return PublicKeyCredential.parseRequestOptionsFromJSON(options);
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
allowCredentials: (_a = options.allowCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({
|
|
183
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),
|
|
184
|
+
transports: credential.transports,
|
|
185
|
+
type: credential.type,
|
|
186
|
+
})),
|
|
187
|
+
challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),
|
|
188
|
+
rpId: options.rpId,
|
|
189
|
+
timeout: options.timeout,
|
|
190
|
+
userVerification: options.userVerification,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
static serializeCredential(credential) {
|
|
194
|
+
var _a;
|
|
195
|
+
if (typeof credential.toJSON === 'function') {
|
|
196
|
+
return credential.toJSON();
|
|
197
|
+
}
|
|
198
|
+
const authenticatorAttachment = ((_a = credential.authenticatorAttachment) !== null && _a !== void 0 ? _a : undefined);
|
|
199
|
+
const id = credential.id;
|
|
200
|
+
const rawId = PasskeysWeb.arrayBufferToBase64Url(credential.rawId);
|
|
201
|
+
if (credential.response instanceof AuthenticatorAssertionResponse) {
|
|
202
|
+
const response = credential.response;
|
|
203
|
+
return {
|
|
204
|
+
authenticatorAttachment,
|
|
205
|
+
id,
|
|
206
|
+
rawId,
|
|
207
|
+
response: {
|
|
208
|
+
authenticatorData: PasskeysWeb.arrayBufferToBase64Url(response.authenticatorData),
|
|
209
|
+
clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),
|
|
210
|
+
signature: PasskeysWeb.arrayBufferToBase64Url(response.signature),
|
|
211
|
+
userHandle: response.userHandle
|
|
212
|
+
? PasskeysWeb.arrayBufferToBase64Url(response.userHandle)
|
|
213
|
+
: undefined,
|
|
214
|
+
},
|
|
215
|
+
type: 'public-key',
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const response = credential.response;
|
|
219
|
+
return {
|
|
220
|
+
authenticatorAttachment,
|
|
221
|
+
id,
|
|
222
|
+
rawId,
|
|
223
|
+
response: {
|
|
224
|
+
attestationObject: PasskeysWeb.arrayBufferToBase64Url(response.attestationObject),
|
|
225
|
+
clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),
|
|
226
|
+
transports: typeof response.getTransports === 'function'
|
|
227
|
+
? response.getTransports()
|
|
228
|
+
: undefined,
|
|
229
|
+
},
|
|
230
|
+
type: 'public-key',
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
PasskeysWeb.errorCreateFailed = 'The passkey could not be created.';
|
|
235
|
+
PasskeysWeb.errorGetFailed = 'The passkey could not be retrieved.';
|
|
236
|
+
PasskeysWeb.errorNotSupported = 'Passkeys are not supported in this browser.';
|
|
237
|
+
|
|
238
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
239
|
+
__proto__: null,
|
|
240
|
+
PasskeysWeb: PasskeysWeb
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
exports.Passkeys = Passkeys;
|
|
244
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["/**\n * @since 0.1.0\n */\nexport var ErrorCode;\n(function (ErrorCode) {\n /**\n * The operation was canceled by the user.\n *\n * @since 0.1.0\n */\n ErrorCode[\"Canceled\"] = \"CANCELED\";\n /**\n * The passkey could not be created.\n *\n * @since 0.1.0\n */\n ErrorCode[\"CreateFailed\"] = \"CREATE_FAILED\";\n /**\n * The app is not associated with the relying party domain.\n *\n * On **Android**, make sure that the Digital Asset Links file is set up\n * correctly. On **iOS**, make sure that the Associated Domains\n * entitlement is set up correctly.\n *\n * @since 0.1.0\n */\n ErrorCode[\"DomainNotAssociated\"] = \"DOMAIN_NOT_ASSOCIATED\";\n /**\n * The passkey could not be retrieved.\n *\n * @since 0.1.0\n */\n ErrorCode[\"GetFailed\"] = \"GET_FAILED\";\n /**\n * No matching passkey was found.\n *\n * @since 0.1.0\n */\n ErrorCode[\"NoCredential\"] = \"NO_CREDENTIAL\";\n /**\n * Passkeys are not supported on this device.\n *\n * @since 0.1.0\n */\n ErrorCode[\"NotSupported\"] = \"NOT_SUPPORTED\";\n})(ErrorCode || (ErrorCode = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst Passkeys = registerPlugin('Passkeys', {\n web: () => import('./web').then(m => new m.PasskeysWeb()),\n});\nexport * from './definitions';\nexport { Passkeys };\n//# sourceMappingURL=index.js.map","import { CapacitorException, WebPlugin } from '@capacitor/core';\nimport { ErrorCode } from './definitions';\nexport class PasskeysWeb extends WebPlugin {\n async createPasskey(options) {\n if (!PasskeysWeb.isWebAuthnSupported()) {\n throw PasskeysWeb.createNotSupportedException();\n }\n let credential;\n try {\n credential = await navigator.credentials.create({\n publicKey: PasskeysWeb.parseCreationOptions(options),\n });\n }\n catch (error) {\n throw PasskeysWeb.createException(error, ErrorCode.CreateFailed);\n }\n if (!(credential instanceof PublicKeyCredential)) {\n throw new CapacitorException(PasskeysWeb.errorCreateFailed, undefined, {\n code: ErrorCode.CreateFailed,\n });\n }\n return PasskeysWeb.serializeCredential(credential);\n }\n async getPasskey(options) {\n if (!PasskeysWeb.isWebAuthnSupported()) {\n throw PasskeysWeb.createNotSupportedException();\n }\n let credential;\n try {\n credential = await navigator.credentials.get({\n publicKey: PasskeysWeb.parseRequestOptions(options),\n });\n }\n catch (error) {\n throw PasskeysWeb.createException(error, ErrorCode.GetFailed);\n }\n if (!(credential instanceof PublicKeyCredential)) {\n throw new CapacitorException(PasskeysWeb.errorGetFailed, undefined, {\n code: ErrorCode.GetFailed,\n });\n }\n return PasskeysWeb.serializeCredential(credential);\n }\n async isAvailable() {\n if (!PasskeysWeb.isWebAuthnSupported()) {\n return { available: false };\n }\n const available = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n return { available };\n }\n static arrayBufferToBase64Url(buffer) {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n }\n static base64UrlToArrayBuffer(value) {\n let base64 = value.replace(/-/g, '+').replace(/_/g, '/');\n while (base64.length % 4 > 0) {\n base64 += '=';\n }\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index++) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes.buffer;\n }\n static createException(error, fallbackCode) {\n let code = fallbackCode;\n if (error instanceof DOMException) {\n if (error.name === 'NotAllowedError') {\n code = ErrorCode.Canceled;\n }\n else if (error.name === 'SecurityError') {\n code = ErrorCode.DomainNotAssociated;\n }\n else if (error.name === 'NotSupportedError') {\n code = ErrorCode.NotSupported;\n }\n }\n const message = error instanceof Error ? error.message : 'An unknown error has occurred.';\n return new CapacitorException(message, undefined, { code });\n }\n static createNotSupportedException() {\n return new CapacitorException(PasskeysWeb.errorNotSupported, undefined, {\n code: ErrorCode.NotSupported,\n });\n }\n static isWebAuthnSupported() {\n return (typeof window !== 'undefined' &&\n typeof window.PublicKeyCredential !== 'undefined');\n }\n static parseCreationOptions(options) {\n var _a;\n if (typeof PublicKeyCredential.parseCreationOptionsFromJSON === 'function') {\n return PublicKeyCredential.parseCreationOptionsFromJSON(options);\n }\n return {\n attestation: options.attestation,\n authenticatorSelection: options.authenticatorSelection,\n challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),\n excludeCredentials: (_a = options.excludeCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({\n id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),\n transports: credential.transports,\n type: credential.type,\n })),\n pubKeyCredParams: options.pubKeyCredParams,\n rp: options.rp,\n timeout: options.timeout,\n user: {\n displayName: options.user.displayName,\n id: PasskeysWeb.base64UrlToArrayBuffer(options.user.id),\n name: options.user.name,\n },\n };\n }\n static parseRequestOptions(options) {\n var _a;\n if (typeof PublicKeyCredential.parseRequestOptionsFromJSON === 'function') {\n return PublicKeyCredential.parseRequestOptionsFromJSON(options);\n }\n return {\n allowCredentials: (_a = options.allowCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({\n id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),\n transports: credential.transports,\n type: credential.type,\n })),\n challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),\n rpId: options.rpId,\n timeout: options.timeout,\n userVerification: options.userVerification,\n };\n }\n static serializeCredential(credential) {\n var _a;\n if (typeof credential.toJSON === 'function') {\n return credential.toJSON();\n }\n const authenticatorAttachment = ((_a = credential.authenticatorAttachment) !== null && _a !== void 0 ? _a : undefined);\n const id = credential.id;\n const rawId = PasskeysWeb.arrayBufferToBase64Url(credential.rawId);\n if (credential.response instanceof AuthenticatorAssertionResponse) {\n const response = credential.response;\n return {\n authenticatorAttachment,\n id,\n rawId,\n response: {\n authenticatorData: PasskeysWeb.arrayBufferToBase64Url(response.authenticatorData),\n clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),\n signature: PasskeysWeb.arrayBufferToBase64Url(response.signature),\n userHandle: response.userHandle\n ? PasskeysWeb.arrayBufferToBase64Url(response.userHandle)\n : undefined,\n },\n type: 'public-key',\n };\n }\n const response = credential.response;\n return {\n authenticatorAttachment,\n id,\n rawId,\n response: {\n attestationObject: PasskeysWeb.arrayBufferToBase64Url(response.attestationObject),\n clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),\n transports: typeof response.getTransports === 'function'\n ? response.getTransports()\n : undefined,\n },\n type: 'public-key',\n };\n }\n}\nPasskeysWeb.errorCreateFailed = 'The passkey could not be created.';\nPasskeysWeb.errorGetFailed = 'The passkey could not be retrieved.';\nPasskeysWeb.errorNotSupported = 'Passkeys are not supported in this browser.';\n//# sourceMappingURL=web.js.map"],"names":["ErrorCode","registerPlugin","WebPlugin","CapacitorException"],"mappings":"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"}
|