altcha 3.0.4 → 3.0.6
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/README.md +68 -0
- package/dist/external/altcha.js +52 -22
- package/dist/external/altcha.min.js +1 -1
- package/dist/external/altcha.umd.cjs +52 -22
- package/dist/external/altcha.umd.min.cjs +1 -1
- package/dist/main/altcha.i18n.js +52 -22
- package/dist/main/altcha.i18n.min.js +1 -1
- package/dist/main/altcha.i18n.umd.cjs +52 -22
- package/dist/main/altcha.i18n.umd.min.cjs +1 -1
- package/dist/main/altcha.js +52 -22
- package/dist/main/altcha.min.js +1 -1
- package/dist/main/altcha.umd.cjs +52 -22
- package/dist/main/altcha.umd.min.cjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -228,6 +228,74 @@ For simple implementations, the widget supports a subset of configuration option
|
|
|
228
228
|
- **`timeout`**: Verification timeout in milliseconds (Default: `90_000`).
|
|
229
229
|
- **`verifyFunction`**: A custom verification handler that overrides default network verification.
|
|
230
230
|
|
|
231
|
+
## Algorithms
|
|
232
|
+
|
|
233
|
+
ALTCHA supports multiple proof-of-work algorithms. `PBKDF2/*` and `SHA-*` are bundled with the main widget by default. `Argon2` and `Scrypt` are memory-bound algorithms that resist hardware acceleration (ASICs/GPUs) but require importing their workers separately.
|
|
234
|
+
|
|
235
|
+
**Supported algorithms:**
|
|
236
|
+
|
|
237
|
+
- `PBKDF2/SHA-256` (default, bundled)
|
|
238
|
+
- `PBKDF2/SHA-384` (bundled)
|
|
239
|
+
- `PBKDF2/SHA-512` (bundled)
|
|
240
|
+
- `SHA-256` (bundled)
|
|
241
|
+
- `SHA-384` (bundled)
|
|
242
|
+
- `SHA-512` (bundled)
|
|
243
|
+
- `ARGON2ID` (requires separate worker import)
|
|
244
|
+
- `SCRYPT` (requires separate worker import)
|
|
245
|
+
|
|
246
|
+
If you use `Argon2` or `Scrypt`, import their workers and register them via the `$altcha.algorithms` global before the widget initializes.
|
|
247
|
+
|
|
248
|
+
### Adding Argon2 / Scrypt Workers (Vite)
|
|
249
|
+
|
|
250
|
+
Works with both `altcha` and `altcha/external`:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import 'altcha'; // or 'altcha/external'
|
|
254
|
+
import Argon2idWorker from 'altcha/workers/argon2id?worker';
|
|
255
|
+
import ScryptWorker from 'altcha/workers/scrypt?worker';
|
|
256
|
+
|
|
257
|
+
$altcha.algorithms.set('ARGON2ID', () => new Argon2idWorker());
|
|
258
|
+
$altcha.algorithms.set('SCRYPT', () => new ScryptWorker());
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Without Bundler Worker Import Support
|
|
262
|
+
|
|
263
|
+
If your environment does not support `?worker` imports, load the prebuilt worker files directly:
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
import 'altcha';
|
|
267
|
+
|
|
268
|
+
$altcha.algorithms.set(
|
|
269
|
+
'ARGON2ID',
|
|
270
|
+
() => new Worker('/path/to/node_modules/altcha/dist/workers/argon2id.js')
|
|
271
|
+
);
|
|
272
|
+
$altcha.algorithms.set(
|
|
273
|
+
'SCRYPT',
|
|
274
|
+
() => new Worker('/path/to/node_modules/altcha/dist/workers/scrypt.js')
|
|
275
|
+
);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Using `altcha/external`
|
|
279
|
+
|
|
280
|
+
`altcha/external` excludes all bundled workers, requiring you to register every algorithm explicitly. Use this for full control over which workers are loaded:
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
import 'altcha/external';
|
|
284
|
+
import Argon2idWorker from 'altcha/workers/argon2id?worker';
|
|
285
|
+
import Pbkdf2Worker from 'altcha/workers/pbkdf2?worker';
|
|
286
|
+
import ScryptWorker from 'altcha/workers/scrypt?worker';
|
|
287
|
+
import ShaWorker from 'altcha/workers/sha?worker';
|
|
288
|
+
|
|
289
|
+
$altcha.algorithms.set('PBKDF2/SHA-256', () => new Pbkdf2Worker());
|
|
290
|
+
$altcha.algorithms.set('PBKDF2/SHA-384', () => new Pbkdf2Worker());
|
|
291
|
+
$altcha.algorithms.set('PBKDF2/SHA-512', () => new Pbkdf2Worker());
|
|
292
|
+
$altcha.algorithms.set('SHA-256', () => new ShaWorker());
|
|
293
|
+
$altcha.algorithms.set('SHA-384', () => new ShaWorker());
|
|
294
|
+
$altcha.algorithms.set('SHA-512', () => new ShaWorker());
|
|
295
|
+
$altcha.algorithms.set('ARGON2ID', () => new Argon2idWorker());
|
|
296
|
+
$altcha.algorithms.set('SCRYPT', () => new ScryptWorker());
|
|
297
|
+
```
|
|
298
|
+
|
|
231
299
|
## Cookies
|
|
232
300
|
|
|
233
301
|
By default, the widget sends the ALTCHA payload as a form field by creating a hidden input. It can also be configured to send the payload via a cookie.
|
package/dist/external/altcha.js
CHANGED
|
@@ -5363,7 +5363,7 @@ function Code($$anchor, $$props) {
|
|
|
5363
5363
|
button.disabled = get(audioState) === AudioState.LOADING || get(audioState) === AudioState.ERROR;
|
|
5364
5364
|
set_attribute(button, "aria-label", get(audioState) === AudioState.LOADING ? strings().loading : strings().getAudioChallenge);
|
|
5365
5365
|
});
|
|
5366
|
-
|
|
5366
|
+
event("click", button, () => onPlayAudio(), true);
|
|
5367
5367
|
append($$anchor2, button);
|
|
5368
5368
|
};
|
|
5369
5369
|
if_block(node_1, ($$render) => {
|
|
@@ -5418,12 +5418,12 @@ function Code($$anchor, $$props) {
|
|
|
5418
5418
|
event("submit", form, onSubmitCapture, true);
|
|
5419
5419
|
delegated("keydown", input, onInputKeyDown);
|
|
5420
5420
|
bind_value(input, () => get(code), ($$value) => set(code, $$value));
|
|
5421
|
-
|
|
5422
|
-
|
|
5421
|
+
event("click", button_1, () => onReload()?.(), true);
|
|
5422
|
+
event("click", button_3, () => onCancel()?.(), true);
|
|
5423
5423
|
append($$anchor, div);
|
|
5424
5424
|
return pop($$exports);
|
|
5425
5425
|
}
|
|
5426
|
-
delegate(["keydown"
|
|
5426
|
+
delegate(["keydown"]);
|
|
5427
5427
|
create_custom_element(
|
|
5428
5428
|
Code,
|
|
5429
5429
|
{
|
|
@@ -5446,7 +5446,7 @@ var root_3$1 = /* @__PURE__ */ from_html(`<div role="button" class="altcha-popov
|
|
|
5446
5446
|
var root$1 = /* @__PURE__ */ from_html(`<!> <div><!> <!> <div class="altcha-popover-content"><!></div></div>`, 1);
|
|
5447
5447
|
function Popover($$anchor, $$props) {
|
|
5448
5448
|
push($$props, true);
|
|
5449
|
-
let anchor = prop($$props, "anchor"), children = prop($$props, "children"), display = prop($$props, "display", 7, "standard"), backdrop = prop($$props, "backdrop", 7, false), onClickOutside = prop($$props, "onClickOutside"), onClickOutsideDelay = prop($$props, "onClickOutsideDelay", 7, 600), onClose = prop($$props, "onClose"), placement = prop($$props, "placement", 7, "auto"), variant = prop($$props, "variant", 7, "neutral"), rest = /* @__PURE__ */ rest_props($$props, [
|
|
5449
|
+
let anchor = prop($$props, "anchor"), children = prop($$props, "children"), display = prop($$props, "display", 7, "standard"), backdrop = prop($$props, "backdrop", 7, false), onClickOutside = prop($$props, "onClickOutside"), onClickOutsideDelay = prop($$props, "onClickOutsideDelay", 7, 600), onClose = prop($$props, "onClose"), placement = prop($$props, "placement", 7, "auto"), updateUISignal = prop($$props, "updateUISignal"), variant = prop($$props, "variant", 7, "neutral"), rest = /* @__PURE__ */ rest_props($$props, [
|
|
5450
5450
|
"$$slots",
|
|
5451
5451
|
"$$events",
|
|
5452
5452
|
"$$legacy",
|
|
@@ -5459,6 +5459,7 @@ function Popover($$anchor, $$props) {
|
|
|
5459
5459
|
"onClickOutsideDelay",
|
|
5460
5460
|
"onClose",
|
|
5461
5461
|
"placement",
|
|
5462
|
+
"updateUISignal",
|
|
5462
5463
|
"variant"
|
|
5463
5464
|
]);
|
|
5464
5465
|
let el = /* @__PURE__ */ state(void 0);
|
|
@@ -5470,6 +5471,11 @@ function Popover($$anchor, $$props) {
|
|
|
5470
5471
|
set(top, placement() === "top");
|
|
5471
5472
|
}
|
|
5472
5473
|
});
|
|
5474
|
+
user_effect(() => {
|
|
5475
|
+
if (updateUISignal()) {
|
|
5476
|
+
reposition();
|
|
5477
|
+
}
|
|
5478
|
+
});
|
|
5473
5479
|
onMount(() => {
|
|
5474
5480
|
const moveToBody = display() === "bottomsheet" || display() === "overlay";
|
|
5475
5481
|
if (moveToBody) {
|
|
@@ -5492,7 +5498,7 @@ function Popover($$anchor, $$props) {
|
|
|
5492
5498
|
}
|
|
5493
5499
|
function onWindowClick(ev) {
|
|
5494
5500
|
const target = ev.target;
|
|
5495
|
-
if (!get(el)?.contains(target) &&
|
|
5501
|
+
if (!get(el)?.contains(target) && (!onClickOutsideDelay() || get(mountedAt) + onClickOutsideDelay() < Date.now())) {
|
|
5496
5502
|
onClickOutside()?.();
|
|
5497
5503
|
}
|
|
5498
5504
|
}
|
|
@@ -5569,6 +5575,13 @@ function Popover($$anchor, $$props) {
|
|
|
5569
5575
|
placement($$value);
|
|
5570
5576
|
flushSync();
|
|
5571
5577
|
},
|
|
5578
|
+
get updateUISignal() {
|
|
5579
|
+
return updateUISignal();
|
|
5580
|
+
},
|
|
5581
|
+
set updateUISignal($$value) {
|
|
5582
|
+
updateUISignal($$value);
|
|
5583
|
+
flushSync();
|
|
5584
|
+
},
|
|
5572
5585
|
get variant() {
|
|
5573
5586
|
return variant();
|
|
5574
5587
|
},
|
|
@@ -5578,7 +5591,7 @@ function Popover($$anchor, $$props) {
|
|
|
5578
5591
|
}
|
|
5579
5592
|
};
|
|
5580
5593
|
var fragment = root$1();
|
|
5581
|
-
event("click", $window, onWindowClick);
|
|
5594
|
+
event("click", $window, onWindowClick, true);
|
|
5582
5595
|
event("resize", $window, onWindowResize);
|
|
5583
5596
|
event("scroll", $window, onWindowScroll);
|
|
5584
5597
|
var node = first_child(fragment);
|
|
@@ -5615,7 +5628,7 @@ function Popover($$anchor, $$props) {
|
|
|
5615
5628
|
{
|
|
5616
5629
|
var consequent_2 = ($$anchor2) => {
|
|
5617
5630
|
var div_3 = root_3$1();
|
|
5618
|
-
|
|
5631
|
+
event("click", div_3, onCloseClick, true);
|
|
5619
5632
|
append($$anchor2, div_3);
|
|
5620
5633
|
};
|
|
5621
5634
|
if_block(node_2, ($$render) => {
|
|
@@ -5631,7 +5644,6 @@ function Popover($$anchor, $$props) {
|
|
|
5631
5644
|
append($$anchor, fragment);
|
|
5632
5645
|
return pop($$exports);
|
|
5633
5646
|
}
|
|
5634
|
-
delegate(["click"]);
|
|
5635
5647
|
create_custom_element(
|
|
5636
5648
|
Popover,
|
|
5637
5649
|
{
|
|
@@ -5643,6 +5655,7 @@ create_custom_element(
|
|
|
5643
5655
|
onClickOutsideDelay: {},
|
|
5644
5656
|
onClose: {},
|
|
5645
5657
|
placement: {},
|
|
5658
|
+
updateUISignal: {},
|
|
5646
5659
|
variant: {}
|
|
5647
5660
|
},
|
|
5648
5661
|
[],
|
|
@@ -5909,6 +5922,7 @@ function Widget($$anchor, $$props) {
|
|
|
5909
5922
|
let checked = /* @__PURE__ */ state(false);
|
|
5910
5923
|
let codeChallenge = /* @__PURE__ */ state(null);
|
|
5911
5924
|
let currentController = /* @__PURE__ */ state(null);
|
|
5925
|
+
let currentDisplay = /* @__PURE__ */ state(null);
|
|
5912
5926
|
let currentState = /* @__PURE__ */ state(proxy(State.UNVERIFIED));
|
|
5913
5927
|
let elAnchorArrow = /* @__PURE__ */ state(void 0);
|
|
5914
5928
|
let elFloatingAnchor = /* @__PURE__ */ state(void 0);
|
|
@@ -5919,6 +5933,7 @@ function Widget($$anchor, $$props) {
|
|
|
5919
5933
|
let expirationTimeout = /* @__PURE__ */ state(null);
|
|
5920
5934
|
let payload = /* @__PURE__ */ state(null);
|
|
5921
5935
|
let plugins = /* @__PURE__ */ state(proxy([]));
|
|
5936
|
+
let updateUISignal = /* @__PURE__ */ state(0);
|
|
5922
5937
|
let userConfig = /* @__PURE__ */ state(proxy({}));
|
|
5923
5938
|
let visible = /* @__PURE__ */ state(true);
|
|
5924
5939
|
const config = /* @__PURE__ */ user_derived(() => ({
|
|
@@ -5998,7 +6013,9 @@ function Widget($$anchor, $$props) {
|
|
|
5998
6013
|
}
|
|
5999
6014
|
});
|
|
6000
6015
|
user_effect(() => {
|
|
6001
|
-
|
|
6016
|
+
if (get(currentDisplay) !== get(config).display) {
|
|
6017
|
+
setDisplay(get(config).display);
|
|
6018
|
+
}
|
|
6002
6019
|
});
|
|
6003
6020
|
user_effect(() => {
|
|
6004
6021
|
if (get(checked) && get(currentState) === State.VERIFYING) {
|
|
@@ -6049,7 +6066,7 @@ function Widget($$anchor, $$props) {
|
|
|
6049
6066
|
}
|
|
6050
6067
|
});
|
|
6051
6068
|
onMount(() => {
|
|
6052
|
-
log("mounted", "3.0.
|
|
6069
|
+
log("mounted", "3.0.6");
|
|
6053
6070
|
if (instance) {
|
|
6054
6071
|
globalThis.$altcha.instances.add(instance);
|
|
6055
6072
|
}
|
|
@@ -6300,9 +6317,6 @@ function Widget($$anchor, $$props) {
|
|
|
6300
6317
|
}
|
|
6301
6318
|
}
|
|
6302
6319
|
function onCloseClick() {
|
|
6303
|
-
if (get(currentController)) {
|
|
6304
|
-
get(currentController).abort();
|
|
6305
|
-
}
|
|
6306
6320
|
setDisplay(get(config).display);
|
|
6307
6321
|
reset$1();
|
|
6308
6322
|
}
|
|
@@ -6321,9 +6335,6 @@ function Widget($$anchor, $$props) {
|
|
|
6321
6335
|
}
|
|
6322
6336
|
}
|
|
6323
6337
|
function onFormReset() {
|
|
6324
|
-
if (get(currentController)) {
|
|
6325
|
-
get(currentController).abort();
|
|
6326
|
-
}
|
|
6327
6338
|
setDisplay(get(config).display);
|
|
6328
6339
|
reset$1();
|
|
6329
6340
|
}
|
|
@@ -6342,8 +6353,11 @@ function Widget($$anchor, $$props) {
|
|
|
6342
6353
|
});
|
|
6343
6354
|
}
|
|
6344
6355
|
}
|
|
6345
|
-
function onWindowPageshow() {
|
|
6346
|
-
|
|
6356
|
+
function onWindowPageshow(ev) {
|
|
6357
|
+
if (ev.persisted) {
|
|
6358
|
+
setDisplay(get(config).display);
|
|
6359
|
+
reset$1();
|
|
6360
|
+
}
|
|
6347
6361
|
}
|
|
6348
6362
|
function onWindowResize() {
|
|
6349
6363
|
updateUI();
|
|
@@ -6463,6 +6477,9 @@ function Widget($$anchor, $$props) {
|
|
|
6463
6477
|
case "standard":
|
|
6464
6478
|
show();
|
|
6465
6479
|
}
|
|
6480
|
+
if (get(currentDisplay) !== value) {
|
|
6481
|
+
set(currentDisplay, value, true);
|
|
6482
|
+
}
|
|
6466
6483
|
}
|
|
6467
6484
|
function setChallengeExpiration(expiresAt) {
|
|
6468
6485
|
if (get(expirationTimeout)) {
|
|
@@ -6561,6 +6578,9 @@ function Widget($$anchor, $$props) {
|
|
|
6561
6578
|
set(checked, false);
|
|
6562
6579
|
set(error, err, true);
|
|
6563
6580
|
set(payload, null);
|
|
6581
|
+
if (get(currentController)) {
|
|
6582
|
+
get(currentController).abort();
|
|
6583
|
+
}
|
|
6564
6584
|
if (get(expirationTimeout)) {
|
|
6565
6585
|
clearTimeout(get(expirationTimeout));
|
|
6566
6586
|
set(expirationTimeout, null);
|
|
@@ -6583,6 +6603,7 @@ function Widget($$anchor, $$props) {
|
|
|
6583
6603
|
case "floating":
|
|
6584
6604
|
return repositionFloating();
|
|
6585
6605
|
}
|
|
6606
|
+
set(updateUISignal, get(updateUISignal) + 1);
|
|
6586
6607
|
}
|
|
6587
6608
|
async function verify(options = {}) {
|
|
6588
6609
|
const {
|
|
@@ -6598,8 +6619,8 @@ function Widget($$anchor, $$props) {
|
|
|
6598
6619
|
if (hook !== void 0) {
|
|
6599
6620
|
return hook;
|
|
6600
6621
|
}
|
|
6601
|
-
set(currentController, controller, true);
|
|
6602
6622
|
reset$1(State.VERIFYING);
|
|
6623
|
+
set(currentController, controller, true);
|
|
6603
6624
|
try {
|
|
6604
6625
|
if (!isSecureContext) {
|
|
6605
6626
|
throw new Error("Secure context (HTTPS) required.");
|
|
@@ -6610,6 +6631,10 @@ function Widget($$anchor, $$props) {
|
|
|
6610
6631
|
if (get(config).test) {
|
|
6611
6632
|
log("running test mode with null challenge");
|
|
6612
6633
|
await delay(Math.max(0, minDuration - (performance.now() - start)));
|
|
6634
|
+
if (get(currentController)?.signal.aborted) {
|
|
6635
|
+
reset$1();
|
|
6636
|
+
return null;
|
|
6637
|
+
}
|
|
6613
6638
|
set(payload, btoa(JSON.stringify({ challenge: null, solution: null, test: true })), true);
|
|
6614
6639
|
log("verified");
|
|
6615
6640
|
setState(State.VERIFIED);
|
|
@@ -6740,7 +6765,7 @@ function Widget($$anchor, $$props) {
|
|
|
6740
6765
|
if (get(config).overlayContent) $$render(consequent_1);
|
|
6741
6766
|
});
|
|
6742
6767
|
}
|
|
6743
|
-
|
|
6768
|
+
event("click", div_2, onCloseClick, true);
|
|
6744
6769
|
append($$anchor2, fragment_1);
|
|
6745
6770
|
};
|
|
6746
6771
|
if_block(node_1, ($$render) => {
|
|
@@ -6885,6 +6910,9 @@ function Widget($$anchor, $$props) {
|
|
|
6885
6910
|
get dir() {
|
|
6886
6911
|
return get(dir);
|
|
6887
6912
|
},
|
|
6913
|
+
get updateUISignal() {
|
|
6914
|
+
return get(updateUISignal);
|
|
6915
|
+
},
|
|
6888
6916
|
children: ($$anchor3, $$slotProps) => {
|
|
6889
6917
|
var fragment_9 = comment();
|
|
6890
6918
|
var node_10 = first_child(fragment_9);
|
|
@@ -6950,6 +6978,9 @@ function Widget($$anchor, $$props) {
|
|
|
6950
6978
|
get dir() {
|
|
6951
6979
|
return get(dir);
|
|
6952
6980
|
},
|
|
6981
|
+
get updateUISignal() {
|
|
6982
|
+
return get(updateUISignal);
|
|
6983
|
+
},
|
|
6953
6984
|
children: ($$anchor4, $$slotProps) => {
|
|
6954
6985
|
var fragment_12 = root_19();
|
|
6955
6986
|
var node_12 = first_child(fragment_12);
|
|
@@ -7021,7 +7052,6 @@ function Widget($$anchor, $$props) {
|
|
|
7021
7052
|
$$cleanup();
|
|
7022
7053
|
return $$pop;
|
|
7023
7054
|
}
|
|
7024
|
-
delegate(["click"]);
|
|
7025
7055
|
if (typeof window !== "undefined" && window.customElements) customElements.define("altcha-widget", create_custom_element(
|
|
7026
7056
|
Widget,
|
|
7027
7057
|
{
|