@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/plugin.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
var capacitorPasskeys = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*/
|
|
7
|
+
exports.ErrorCode = void 0;
|
|
8
|
+
(function (ErrorCode) {
|
|
9
|
+
/**
|
|
10
|
+
* The operation was canceled by the user.
|
|
11
|
+
*
|
|
12
|
+
* @since 0.1.0
|
|
13
|
+
*/
|
|
14
|
+
ErrorCode["Canceled"] = "CANCELED";
|
|
15
|
+
/**
|
|
16
|
+
* The passkey could not be created.
|
|
17
|
+
*
|
|
18
|
+
* @since 0.1.0
|
|
19
|
+
*/
|
|
20
|
+
ErrorCode["CreateFailed"] = "CREATE_FAILED";
|
|
21
|
+
/**
|
|
22
|
+
* The app is not associated with the relying party domain.
|
|
23
|
+
*
|
|
24
|
+
* On **Android**, make sure that the Digital Asset Links file is set up
|
|
25
|
+
* correctly. On **iOS**, make sure that the Associated Domains
|
|
26
|
+
* entitlement is set up correctly.
|
|
27
|
+
*
|
|
28
|
+
* @since 0.1.0
|
|
29
|
+
*/
|
|
30
|
+
ErrorCode["DomainNotAssociated"] = "DOMAIN_NOT_ASSOCIATED";
|
|
31
|
+
/**
|
|
32
|
+
* The passkey could not be retrieved.
|
|
33
|
+
*
|
|
34
|
+
* @since 0.1.0
|
|
35
|
+
*/
|
|
36
|
+
ErrorCode["GetFailed"] = "GET_FAILED";
|
|
37
|
+
/**
|
|
38
|
+
* No matching passkey was found.
|
|
39
|
+
*
|
|
40
|
+
* @since 0.1.0
|
|
41
|
+
*/
|
|
42
|
+
ErrorCode["NoCredential"] = "NO_CREDENTIAL";
|
|
43
|
+
/**
|
|
44
|
+
* Passkeys are not supported on this device.
|
|
45
|
+
*
|
|
46
|
+
* @since 0.1.0
|
|
47
|
+
*/
|
|
48
|
+
ErrorCode["NotSupported"] = "NOT_SUPPORTED";
|
|
49
|
+
})(exports.ErrorCode || (exports.ErrorCode = {}));
|
|
50
|
+
|
|
51
|
+
const Passkeys = core.registerPlugin('Passkeys', {
|
|
52
|
+
web: () => Promise.resolve().then(function () { return web; }).then(m => new m.PasskeysWeb()),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
class PasskeysWeb extends core.WebPlugin {
|
|
56
|
+
async createPasskey(options) {
|
|
57
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
58
|
+
throw PasskeysWeb.createNotSupportedException();
|
|
59
|
+
}
|
|
60
|
+
let credential;
|
|
61
|
+
try {
|
|
62
|
+
credential = await navigator.credentials.create({
|
|
63
|
+
publicKey: PasskeysWeb.parseCreationOptions(options),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw PasskeysWeb.createException(error, exports.ErrorCode.CreateFailed);
|
|
68
|
+
}
|
|
69
|
+
if (!(credential instanceof PublicKeyCredential)) {
|
|
70
|
+
throw new core.CapacitorException(PasskeysWeb.errorCreateFailed, undefined, {
|
|
71
|
+
code: exports.ErrorCode.CreateFailed,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return PasskeysWeb.serializeCredential(credential);
|
|
75
|
+
}
|
|
76
|
+
async getPasskey(options) {
|
|
77
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
78
|
+
throw PasskeysWeb.createNotSupportedException();
|
|
79
|
+
}
|
|
80
|
+
let credential;
|
|
81
|
+
try {
|
|
82
|
+
credential = await navigator.credentials.get({
|
|
83
|
+
publicKey: PasskeysWeb.parseRequestOptions(options),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw PasskeysWeb.createException(error, exports.ErrorCode.GetFailed);
|
|
88
|
+
}
|
|
89
|
+
if (!(credential instanceof PublicKeyCredential)) {
|
|
90
|
+
throw new core.CapacitorException(PasskeysWeb.errorGetFailed, undefined, {
|
|
91
|
+
code: exports.ErrorCode.GetFailed,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return PasskeysWeb.serializeCredential(credential);
|
|
95
|
+
}
|
|
96
|
+
async isAvailable() {
|
|
97
|
+
if (!PasskeysWeb.isWebAuthnSupported()) {
|
|
98
|
+
return { available: false };
|
|
99
|
+
}
|
|
100
|
+
const available = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
|
|
101
|
+
return { available };
|
|
102
|
+
}
|
|
103
|
+
static arrayBufferToBase64Url(buffer) {
|
|
104
|
+
const bytes = new Uint8Array(buffer);
|
|
105
|
+
let binary = '';
|
|
106
|
+
for (const byte of bytes) {
|
|
107
|
+
binary += String.fromCharCode(byte);
|
|
108
|
+
}
|
|
109
|
+
return btoa(binary)
|
|
110
|
+
.replace(/\+/g, '-')
|
|
111
|
+
.replace(/\//g, '_')
|
|
112
|
+
.replace(/=+$/, '');
|
|
113
|
+
}
|
|
114
|
+
static base64UrlToArrayBuffer(value) {
|
|
115
|
+
let base64 = value.replace(/-/g, '+').replace(/_/g, '/');
|
|
116
|
+
while (base64.length % 4 > 0) {
|
|
117
|
+
base64 += '=';
|
|
118
|
+
}
|
|
119
|
+
const binary = atob(base64);
|
|
120
|
+
const bytes = new Uint8Array(binary.length);
|
|
121
|
+
for (let index = 0; index < binary.length; index++) {
|
|
122
|
+
bytes[index] = binary.charCodeAt(index);
|
|
123
|
+
}
|
|
124
|
+
return bytes.buffer;
|
|
125
|
+
}
|
|
126
|
+
static createException(error, fallbackCode) {
|
|
127
|
+
let code = fallbackCode;
|
|
128
|
+
if (error instanceof DOMException) {
|
|
129
|
+
if (error.name === 'NotAllowedError') {
|
|
130
|
+
code = exports.ErrorCode.Canceled;
|
|
131
|
+
}
|
|
132
|
+
else if (error.name === 'SecurityError') {
|
|
133
|
+
code = exports.ErrorCode.DomainNotAssociated;
|
|
134
|
+
}
|
|
135
|
+
else if (error.name === 'NotSupportedError') {
|
|
136
|
+
code = exports.ErrorCode.NotSupported;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const message = error instanceof Error ? error.message : 'An unknown error has occurred.';
|
|
140
|
+
return new core.CapacitorException(message, undefined, { code });
|
|
141
|
+
}
|
|
142
|
+
static createNotSupportedException() {
|
|
143
|
+
return new core.CapacitorException(PasskeysWeb.errorNotSupported, undefined, {
|
|
144
|
+
code: exports.ErrorCode.NotSupported,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
static isWebAuthnSupported() {
|
|
148
|
+
return (typeof window !== 'undefined' &&
|
|
149
|
+
typeof window.PublicKeyCredential !== 'undefined');
|
|
150
|
+
}
|
|
151
|
+
static parseCreationOptions(options) {
|
|
152
|
+
var _a;
|
|
153
|
+
if (typeof PublicKeyCredential.parseCreationOptionsFromJSON === 'function') {
|
|
154
|
+
return PublicKeyCredential.parseCreationOptionsFromJSON(options);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
attestation: options.attestation,
|
|
158
|
+
authenticatorSelection: options.authenticatorSelection,
|
|
159
|
+
challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),
|
|
160
|
+
excludeCredentials: (_a = options.excludeCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({
|
|
161
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),
|
|
162
|
+
transports: credential.transports,
|
|
163
|
+
type: credential.type,
|
|
164
|
+
})),
|
|
165
|
+
pubKeyCredParams: options.pubKeyCredParams,
|
|
166
|
+
rp: options.rp,
|
|
167
|
+
timeout: options.timeout,
|
|
168
|
+
user: {
|
|
169
|
+
displayName: options.user.displayName,
|
|
170
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(options.user.id),
|
|
171
|
+
name: options.user.name,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
static parseRequestOptions(options) {
|
|
176
|
+
var _a;
|
|
177
|
+
if (typeof PublicKeyCredential.parseRequestOptionsFromJSON === 'function') {
|
|
178
|
+
return PublicKeyCredential.parseRequestOptionsFromJSON(options);
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
allowCredentials: (_a = options.allowCredentials) === null || _a === void 0 ? void 0 : _a.map(credential => ({
|
|
182
|
+
id: PasskeysWeb.base64UrlToArrayBuffer(credential.id),
|
|
183
|
+
transports: credential.transports,
|
|
184
|
+
type: credential.type,
|
|
185
|
+
})),
|
|
186
|
+
challenge: PasskeysWeb.base64UrlToArrayBuffer(options.challenge),
|
|
187
|
+
rpId: options.rpId,
|
|
188
|
+
timeout: options.timeout,
|
|
189
|
+
userVerification: options.userVerification,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
static serializeCredential(credential) {
|
|
193
|
+
var _a;
|
|
194
|
+
if (typeof credential.toJSON === 'function') {
|
|
195
|
+
return credential.toJSON();
|
|
196
|
+
}
|
|
197
|
+
const authenticatorAttachment = ((_a = credential.authenticatorAttachment) !== null && _a !== void 0 ? _a : undefined);
|
|
198
|
+
const id = credential.id;
|
|
199
|
+
const rawId = PasskeysWeb.arrayBufferToBase64Url(credential.rawId);
|
|
200
|
+
if (credential.response instanceof AuthenticatorAssertionResponse) {
|
|
201
|
+
const response = credential.response;
|
|
202
|
+
return {
|
|
203
|
+
authenticatorAttachment,
|
|
204
|
+
id,
|
|
205
|
+
rawId,
|
|
206
|
+
response: {
|
|
207
|
+
authenticatorData: PasskeysWeb.arrayBufferToBase64Url(response.authenticatorData),
|
|
208
|
+
clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),
|
|
209
|
+
signature: PasskeysWeb.arrayBufferToBase64Url(response.signature),
|
|
210
|
+
userHandle: response.userHandle
|
|
211
|
+
? PasskeysWeb.arrayBufferToBase64Url(response.userHandle)
|
|
212
|
+
: undefined,
|
|
213
|
+
},
|
|
214
|
+
type: 'public-key',
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const response = credential.response;
|
|
218
|
+
return {
|
|
219
|
+
authenticatorAttachment,
|
|
220
|
+
id,
|
|
221
|
+
rawId,
|
|
222
|
+
response: {
|
|
223
|
+
attestationObject: PasskeysWeb.arrayBufferToBase64Url(response.attestationObject),
|
|
224
|
+
clientDataJSON: PasskeysWeb.arrayBufferToBase64Url(response.clientDataJSON),
|
|
225
|
+
transports: typeof response.getTransports === 'function'
|
|
226
|
+
? response.getTransports()
|
|
227
|
+
: undefined,
|
|
228
|
+
},
|
|
229
|
+
type: 'public-key',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
PasskeysWeb.errorCreateFailed = 'The passkey could not be created.';
|
|
234
|
+
PasskeysWeb.errorGetFailed = 'The passkey could not be retrieved.';
|
|
235
|
+
PasskeysWeb.errorNotSupported = 'Passkeys are not supported in this browser.';
|
|
236
|
+
|
|
237
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
238
|
+
__proto__: null,
|
|
239
|
+
PasskeysWeb: PasskeysWeb
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
exports.Passkeys = Passkeys;
|
|
243
|
+
|
|
244
|
+
return exports;
|
|
245
|
+
|
|
246
|
+
})({}, capacitorExports);
|
|
247
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.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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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class CreatePasskeyOptions: NSObject {
|
|
5
|
+
let attestation: String?
|
|
6
|
+
let challenge: Data
|
|
7
|
+
let excludeCredentialIds: [Data]
|
|
8
|
+
let rpId: String
|
|
9
|
+
let userId: Data
|
|
10
|
+
let userName: String
|
|
11
|
+
let userVerification: String?
|
|
12
|
+
|
|
13
|
+
init(_ call: CAPPluginCall) throws {
|
|
14
|
+
self.attestation = CreatePasskeyOptions.getAttestationFromCall(call)
|
|
15
|
+
self.challenge = try CreatePasskeyOptions.getChallengeFromCall(call)
|
|
16
|
+
self.excludeCredentialIds = try CreatePasskeyOptions.getExcludeCredentialIdsFromCall(call)
|
|
17
|
+
self.rpId = try CreatePasskeyOptions.getRpIdFromCall(call)
|
|
18
|
+
self.userId = try CreatePasskeyOptions.getUserIdFromCall(call)
|
|
19
|
+
self.userName = try CreatePasskeyOptions.getUserNameFromCall(call)
|
|
20
|
+
self.userVerification = CreatePasskeyOptions.getUserVerificationFromCall(call)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private static func getAttestationFromCall(_ call: CAPPluginCall) -> String? {
|
|
24
|
+
return call.getString("attestation")
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private static func getChallengeFromCall(_ call: CAPPluginCall) throws -> Data {
|
|
28
|
+
guard let challenge = call.getString("challenge") else {
|
|
29
|
+
throw CustomError.challengeMissing
|
|
30
|
+
}
|
|
31
|
+
guard let data = PasskeysHelper.dataFromBase64Url(challenge) else {
|
|
32
|
+
throw CustomError.challengeInvalid
|
|
33
|
+
}
|
|
34
|
+
return data
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private static func getExcludeCredentialIdsFromCall(_ call: CAPPluginCall) throws -> [Data] {
|
|
38
|
+
guard let excludeCredentials = call.getArray("excludeCredentials") else {
|
|
39
|
+
return []
|
|
40
|
+
}
|
|
41
|
+
var ids: [Data] = []
|
|
42
|
+
for element in excludeCredentials {
|
|
43
|
+
guard let descriptor = element as? [String: Any], let id = descriptor["id"] as? String else {
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
guard let data = PasskeysHelper.dataFromBase64Url(id) else {
|
|
47
|
+
throw CustomError.excludeCredentialsInvalid
|
|
48
|
+
}
|
|
49
|
+
ids.append(data)
|
|
50
|
+
}
|
|
51
|
+
return ids
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private static func getRpIdFromCall(_ call: CAPPluginCall) throws -> String {
|
|
55
|
+
guard let rpId = call.getObject("rp")?["id"] as? String else {
|
|
56
|
+
throw CustomError.rpIdMissing
|
|
57
|
+
}
|
|
58
|
+
return rpId
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private static func getUserIdFromCall(_ call: CAPPluginCall) throws -> Data {
|
|
62
|
+
guard let userId = call.getObject("user")?["id"] as? String else {
|
|
63
|
+
throw CustomError.userIdMissing
|
|
64
|
+
}
|
|
65
|
+
guard let data = PasskeysHelper.dataFromBase64Url(userId) else {
|
|
66
|
+
throw CustomError.userIdInvalid
|
|
67
|
+
}
|
|
68
|
+
return data
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private static func getUserNameFromCall(_ call: CAPPluginCall) throws -> String {
|
|
72
|
+
guard let userName = call.getObject("user")?["name"] as? String else {
|
|
73
|
+
throw CustomError.userNameMissing
|
|
74
|
+
}
|
|
75
|
+
return userName
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private static func getUserVerificationFromCall(_ call: CAPPluginCall) -> String? {
|
|
79
|
+
return call.getObject("authenticatorSelection")?["userVerification"] as? String
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class GetPasskeyOptions: NSObject {
|
|
5
|
+
let allowCredentialIds: [Data]
|
|
6
|
+
let challenge: Data
|
|
7
|
+
let rpId: String
|
|
8
|
+
let userVerification: String?
|
|
9
|
+
|
|
10
|
+
init(_ call: CAPPluginCall) throws {
|
|
11
|
+
self.allowCredentialIds = try GetPasskeyOptions.getAllowCredentialIdsFromCall(call)
|
|
12
|
+
self.challenge = try GetPasskeyOptions.getChallengeFromCall(call)
|
|
13
|
+
self.rpId = try GetPasskeyOptions.getRpIdFromCall(call)
|
|
14
|
+
self.userVerification = GetPasskeyOptions.getUserVerificationFromCall(call)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private static func getAllowCredentialIdsFromCall(_ call: CAPPluginCall) throws -> [Data] {
|
|
18
|
+
guard let allowCredentials = call.getArray("allowCredentials") else {
|
|
19
|
+
return []
|
|
20
|
+
}
|
|
21
|
+
var ids: [Data] = []
|
|
22
|
+
for element in allowCredentials {
|
|
23
|
+
guard let descriptor = element as? [String: Any], let id = descriptor["id"] as? String else {
|
|
24
|
+
continue
|
|
25
|
+
}
|
|
26
|
+
guard let data = PasskeysHelper.dataFromBase64Url(id) else {
|
|
27
|
+
throw CustomError.allowCredentialsInvalid
|
|
28
|
+
}
|
|
29
|
+
ids.append(data)
|
|
30
|
+
}
|
|
31
|
+
return ids
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private static func getChallengeFromCall(_ call: CAPPluginCall) throws -> Data {
|
|
35
|
+
guard let challenge = call.getString("challenge") else {
|
|
36
|
+
throw CustomError.challengeMissing
|
|
37
|
+
}
|
|
38
|
+
guard let data = PasskeysHelper.dataFromBase64Url(challenge) else {
|
|
39
|
+
throw CustomError.challengeInvalid
|
|
40
|
+
}
|
|
41
|
+
return data
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private static func getRpIdFromCall(_ call: CAPPluginCall) throws -> String {
|
|
45
|
+
guard let rpId = call.getString("rpId") else {
|
|
46
|
+
throw CustomError.rpIdTopLevelMissing
|
|
47
|
+
}
|
|
48
|
+
return rpId
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private static func getUserVerificationFromCall(_ call: CAPPluginCall) -> String? {
|
|
52
|
+
return call.getString("userVerification")
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class CreatePasskeyResult: NSObject, Result {
|
|
5
|
+
let attestationObject: Data
|
|
6
|
+
let clientDataJSON: Data
|
|
7
|
+
let credentialId: Data
|
|
8
|
+
|
|
9
|
+
init(attestationObject: Data, clientDataJSON: Data, credentialId: Data) {
|
|
10
|
+
self.attestationObject = attestationObject
|
|
11
|
+
self.clientDataJSON = clientDataJSON
|
|
12
|
+
self.credentialId = credentialId
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@objc public func toJSObject() -> AnyObject {
|
|
16
|
+
let credentialId = PasskeysHelper.base64UrlFromData(self.credentialId)
|
|
17
|
+
var response = JSObject()
|
|
18
|
+
response["attestationObject"] = PasskeysHelper.base64UrlFromData(attestationObject)
|
|
19
|
+
response["clientDataJSON"] = PasskeysHelper.base64UrlFromData(clientDataJSON)
|
|
20
|
+
var result = JSObject()
|
|
21
|
+
result["authenticatorAttachment"] = "platform"
|
|
22
|
+
result["id"] = credentialId
|
|
23
|
+
result["rawId"] = credentialId
|
|
24
|
+
result["response"] = response
|
|
25
|
+
result["type"] = "public-key"
|
|
26
|
+
return result as AnyObject
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class GetPasskeyResult: NSObject, Result {
|
|
5
|
+
let authenticatorData: Data
|
|
6
|
+
let clientDataJSON: Data
|
|
7
|
+
let credentialId: Data
|
|
8
|
+
let signature: Data
|
|
9
|
+
let userHandle: Data
|
|
10
|
+
|
|
11
|
+
init(authenticatorData: Data, clientDataJSON: Data, credentialId: Data, signature: Data, userHandle: Data) {
|
|
12
|
+
self.authenticatorData = authenticatorData
|
|
13
|
+
self.clientDataJSON = clientDataJSON
|
|
14
|
+
self.credentialId = credentialId
|
|
15
|
+
self.signature = signature
|
|
16
|
+
self.userHandle = userHandle
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@objc public func toJSObject() -> AnyObject {
|
|
20
|
+
let credentialId = PasskeysHelper.base64UrlFromData(self.credentialId)
|
|
21
|
+
var response = JSObject()
|
|
22
|
+
response["authenticatorData"] = PasskeysHelper.base64UrlFromData(authenticatorData)
|
|
23
|
+
response["clientDataJSON"] = PasskeysHelper.base64UrlFromData(clientDataJSON)
|
|
24
|
+
response["signature"] = PasskeysHelper.base64UrlFromData(signature)
|
|
25
|
+
response["userHandle"] = PasskeysHelper.base64UrlFromData(userHandle)
|
|
26
|
+
var result = JSObject()
|
|
27
|
+
result["authenticatorAttachment"] = "platform"
|
|
28
|
+
result["id"] = credentialId
|
|
29
|
+
result["rawId"] = credentialId
|
|
30
|
+
result["response"] = response
|
|
31
|
+
result["type"] = "public-key"
|
|
32
|
+
return result as AnyObject
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class IsAvailableResult: NSObject, Result {
|
|
5
|
+
let available: Bool
|
|
6
|
+
|
|
7
|
+
init(available: Bool) {
|
|
8
|
+
self.available = available
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@objc public func toJSObject() -> AnyObject {
|
|
12
|
+
var result = JSObject()
|
|
13
|
+
result["available"] = available
|
|
14
|
+
return result as AnyObject
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public enum CustomError: Error {
|
|
4
|
+
case allowCredentialsInvalid
|
|
5
|
+
case canceled
|
|
6
|
+
case challengeInvalid
|
|
7
|
+
case challengeMissing
|
|
8
|
+
case createFailed
|
|
9
|
+
case domainNotAssociated
|
|
10
|
+
case excludeCredentialsInvalid
|
|
11
|
+
case getFailed
|
|
12
|
+
case rpIdMissing
|
|
13
|
+
case rpIdTopLevelMissing
|
|
14
|
+
case userIdInvalid
|
|
15
|
+
case userIdMissing
|
|
16
|
+
case userNameMissing
|
|
17
|
+
|
|
18
|
+
var code: String? {
|
|
19
|
+
switch self {
|
|
20
|
+
case .canceled:
|
|
21
|
+
return "CANCELED"
|
|
22
|
+
case .createFailed:
|
|
23
|
+
return "CREATE_FAILED"
|
|
24
|
+
case .domainNotAssociated:
|
|
25
|
+
return "DOMAIN_NOT_ASSOCIATED"
|
|
26
|
+
case .getFailed:
|
|
27
|
+
return "GET_FAILED"
|
|
28
|
+
default:
|
|
29
|
+
return nil
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
extension CustomError: LocalizedError {
|
|
35
|
+
public var errorDescription: String? {
|
|
36
|
+
switch self {
|
|
37
|
+
case .allowCredentialsInvalid:
|
|
38
|
+
return NSLocalizedString("allowCredentials contains an invalid id.", comment: "allowCredentialsInvalid")
|
|
39
|
+
case .canceled:
|
|
40
|
+
return NSLocalizedString("The operation was canceled by the user.", comment: "canceled")
|
|
41
|
+
case .challengeInvalid:
|
|
42
|
+
return NSLocalizedString("challenge must be a valid base64url-encoded string.", comment: "challengeInvalid")
|
|
43
|
+
case .challengeMissing:
|
|
44
|
+
return NSLocalizedString("challenge must be provided.", comment: "challengeMissing")
|
|
45
|
+
case .createFailed:
|
|
46
|
+
return NSLocalizedString("The passkey could not be created.", comment: "createFailed")
|
|
47
|
+
case .domainNotAssociated:
|
|
48
|
+
return NSLocalizedString("The app is not associated with the relying party domain.", comment: "domainNotAssociated")
|
|
49
|
+
case .excludeCredentialsInvalid:
|
|
50
|
+
return NSLocalizedString("excludeCredentials contains an invalid id.", comment: "excludeCredentialsInvalid")
|
|
51
|
+
case .getFailed:
|
|
52
|
+
return NSLocalizedString("The passkey could not be retrieved.", comment: "getFailed")
|
|
53
|
+
case .rpIdMissing:
|
|
54
|
+
return NSLocalizedString("rp.id must be provided.", comment: "rpIdMissing")
|
|
55
|
+
case .rpIdTopLevelMissing:
|
|
56
|
+
return NSLocalizedString("rpId must be provided.", comment: "rpIdTopLevelMissing")
|
|
57
|
+
case .userIdInvalid:
|
|
58
|
+
return NSLocalizedString("user.id must be a valid base64url-encoded string.", comment: "userIdInvalid")
|
|
59
|
+
case .userIdMissing:
|
|
60
|
+
return NSLocalizedString("user.id must be provided.", comment: "userIdMissing")
|
|
61
|
+
case .userNameMissing:
|
|
62
|
+
return NSLocalizedString("user.name must be provided.", comment: "userNameMissing")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>$(PRODUCT_NAME)</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>FMWK</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>$(CURRENT_PROJECT_VERSION)</string>
|
|
21
|
+
<key>NSPrincipalClass</key>
|
|
22
|
+
<string></string>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|