@witnium-tech/witniumchain 0.12.0 → 0.12.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/dist/index.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +51 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +51 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -119,6 +119,11 @@ var WitniumchainClient = class {
|
|
|
119
119
|
// first BearerJWT call (and any concurrent fan-out) awaits one in-flight
|
|
120
120
|
// mint rather than minting N tokens.
|
|
121
121
|
sessionExchangeInFlight;
|
|
122
|
+
// Bumped whenever the cached credentials stop being valid (sign-out, the
|
|
123
|
+
// TOTP-confirm epoch bump). A mint or refresh that started under an older
|
|
124
|
+
// generation must not store its result: it could be a previous user's
|
|
125
|
+
// token, or one the server has already ended.
|
|
126
|
+
credentialGeneration = 0;
|
|
122
127
|
/** Subscriptions / billing helpers. See {@link Subscriptions}. */
|
|
123
128
|
subscriptions;
|
|
124
129
|
/** Delegated-key namespace including the one-call {@link DelegatedKeys.provision} flow. */
|
|
@@ -500,18 +505,16 @@ var WitniumchainClient = class {
|
|
|
500
505
|
}
|
|
501
506
|
/**
|
|
502
507
|
* Confirming bumps the user's security epoch server-side, which ends every
|
|
503
|
-
* session-minted access token
|
|
504
|
-
* call mints a fresh
|
|
508
|
+
* session-minted access token and OAuth artifact of the user. Cached and
|
|
509
|
+
* in-flight tokens are dropped so the next bearer call mints a fresh one
|
|
510
|
+
* from the (surviving) session.
|
|
505
511
|
*/
|
|
506
512
|
async confirmTotp(body) {
|
|
507
513
|
const res = await this.req("POST", "/v1/account/mfa/totp/confirm", {
|
|
508
514
|
auth: "SessionCookie",
|
|
509
515
|
body
|
|
510
516
|
});
|
|
511
|
-
|
|
512
|
-
this.accessToken = void 0;
|
|
513
|
-
this.accessTokenFromSession = false;
|
|
514
|
-
}
|
|
517
|
+
this.invalidateCredentials();
|
|
515
518
|
return res;
|
|
516
519
|
}
|
|
517
520
|
/** Step-up: 403 `mfa_step_up_failed` on a wrong proof, 429 `mfa_rate_limited`. */
|
|
@@ -789,14 +792,16 @@ var WitniumchainClient = class {
|
|
|
789
792
|
*/
|
|
790
793
|
async refreshAccessToken() {
|
|
791
794
|
if (this.refreshInFlight) return this.refreshInFlight;
|
|
792
|
-
|
|
795
|
+
let flight = void 0;
|
|
796
|
+
flight = (async () => {
|
|
793
797
|
try {
|
|
794
798
|
return await this.refreshAccessTokenInternal();
|
|
795
799
|
} finally {
|
|
796
|
-
this.refreshInFlight = void 0;
|
|
800
|
+
if (this.refreshInFlight === flight) this.refreshInFlight = void 0;
|
|
797
801
|
}
|
|
798
802
|
})();
|
|
799
|
-
|
|
803
|
+
this.refreshInFlight = flight;
|
|
804
|
+
return flight;
|
|
800
805
|
}
|
|
801
806
|
/**
|
|
802
807
|
* Exchange the logged-in session (the `wac_session` cookie) for a short-lived
|
|
@@ -821,9 +826,12 @@ var WitniumchainClient = class {
|
|
|
821
826
|
*/
|
|
822
827
|
async exchangeSessionForToken() {
|
|
823
828
|
if (this.sessionExchangeInFlight) return this.sessionExchangeInFlight;
|
|
824
|
-
|
|
829
|
+
const generation = this.credentialGeneration;
|
|
830
|
+
let flight = void 0;
|
|
831
|
+
flight = (async () => {
|
|
825
832
|
try {
|
|
826
833
|
const res = await this.req("POST", "/v1/auth/access-token", { auth: "SessionCookie" });
|
|
834
|
+
this.assertCredentialGeneration(generation);
|
|
827
835
|
this.accessToken = res.accessToken;
|
|
828
836
|
this.accessTokenFromSession = true;
|
|
829
837
|
this.refreshToken = void 0;
|
|
@@ -833,10 +841,32 @@ var WitniumchainClient = class {
|
|
|
833
841
|
expiresAt: Math.floor(new Date(res.expiresAt).getTime() / 1e3)
|
|
834
842
|
};
|
|
835
843
|
} finally {
|
|
836
|
-
this.sessionExchangeInFlight = void 0;
|
|
844
|
+
if (this.sessionExchangeInFlight === flight) this.sessionExchangeInFlight = void 0;
|
|
837
845
|
}
|
|
838
846
|
})();
|
|
839
|
-
|
|
847
|
+
this.sessionExchangeInFlight = flight;
|
|
848
|
+
return flight;
|
|
849
|
+
}
|
|
850
|
+
assertCredentialGeneration(generation) {
|
|
851
|
+
if (generation !== this.credentialGeneration) {
|
|
852
|
+
throw new WitniumchainApiError({
|
|
853
|
+
status: 0,
|
|
854
|
+
message: "WitniumchainClient: the session changed (sign-out or MFA confirmation) while a token request was in flight; its token was discarded."
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Forget every cached credential and orphan in-flight mints/refreshes, so
|
|
860
|
+
* none of them can store a token afterwards.
|
|
861
|
+
*/
|
|
862
|
+
invalidateCredentials() {
|
|
863
|
+
this.credentialGeneration++;
|
|
864
|
+
this.accessToken = void 0;
|
|
865
|
+
this.accessTokenFromSession = false;
|
|
866
|
+
this.refreshToken = void 0;
|
|
867
|
+
this.hasRefreshCookie = false;
|
|
868
|
+
this.sessionExchangeInFlight = void 0;
|
|
869
|
+
this.refreshInFlight = void 0;
|
|
840
870
|
}
|
|
841
871
|
/**
|
|
842
872
|
* Best-effort transparent mint for the `BearerJWT` path: if no access token
|
|
@@ -848,7 +878,8 @@ var WitniumchainClient = class {
|
|
|
848
878
|
if (this.accessToken) return;
|
|
849
879
|
try {
|
|
850
880
|
await this.exchangeSessionForToken();
|
|
851
|
-
} catch {
|
|
881
|
+
} catch (err) {
|
|
882
|
+
if (!(err instanceof WitniumchainApiError && err.status === 401)) throw err;
|
|
852
883
|
}
|
|
853
884
|
}
|
|
854
885
|
/**
|
|
@@ -889,10 +920,7 @@ var WitniumchainClient = class {
|
|
|
889
920
|
* dropped — which it is, here.
|
|
890
921
|
*/
|
|
891
922
|
signOut() {
|
|
892
|
-
this.
|
|
893
|
-
this.accessTokenFromSession = false;
|
|
894
|
-
this.refreshToken = void 0;
|
|
895
|
-
this.hasRefreshCookie = false;
|
|
923
|
+
this.invalidateCredentials();
|
|
896
924
|
this.pendingLogins.clear();
|
|
897
925
|
}
|
|
898
926
|
// ────────────────────────────────────────────────────────────────────────
|
|
@@ -1012,6 +1040,7 @@ var WitniumchainClient = class {
|
|
|
1012
1040
|
message: "WitniumchainClient: no refresh credential available. Call `completeOAuthLogin` first \u2014 the server delivers the refresh token either in the response body (Node) or as an HttpOnly cookie (browser)."
|
|
1013
1041
|
});
|
|
1014
1042
|
}
|
|
1043
|
+
const generation = this.credentialGeneration;
|
|
1015
1044
|
const discovery = await this.fetchDiscovery();
|
|
1016
1045
|
const form = new URLSearchParams();
|
|
1017
1046
|
form.set("grant_type", "refresh_token");
|
|
@@ -1019,15 +1048,18 @@ var WitniumchainClient = class {
|
|
|
1019
1048
|
if (this.refreshToken) {
|
|
1020
1049
|
form.set("refresh_token", this.refreshToken);
|
|
1021
1050
|
}
|
|
1051
|
+
let tokens;
|
|
1022
1052
|
try {
|
|
1023
|
-
|
|
1024
|
-
return this.persistTokenResponse(tokens);
|
|
1053
|
+
tokens = await this.postTokenEndpoint(discovery.token_endpoint, form);
|
|
1025
1054
|
} catch (err) {
|
|
1055
|
+
this.assertCredentialGeneration(generation);
|
|
1026
1056
|
this.accessToken = void 0;
|
|
1027
1057
|
this.refreshToken = void 0;
|
|
1028
1058
|
this.hasRefreshCookie = false;
|
|
1029
1059
|
throw err;
|
|
1030
1060
|
}
|
|
1061
|
+
this.assertCredentialGeneration(generation);
|
|
1062
|
+
return this.persistTokenResponse(tokens);
|
|
1031
1063
|
}
|
|
1032
1064
|
// ────────────────────────────────────────────────────────────────────────
|
|
1033
1065
|
// Internal: fetch wrapper that maps non-2xx → WitniumchainApiError
|