@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.d.mts
CHANGED
|
@@ -12050,6 +12050,7 @@ declare class WitniumchainClient {
|
|
|
12050
12050
|
private refreshInFlight;
|
|
12051
12051
|
private accessTokenFromSession;
|
|
12052
12052
|
private sessionExchangeInFlight;
|
|
12053
|
+
private credentialGeneration;
|
|
12053
12054
|
/** Subscriptions / billing helpers. See {@link Subscriptions}. */
|
|
12054
12055
|
readonly subscriptions: Subscriptions;
|
|
12055
12056
|
/** Delegated-key namespace including the one-call {@link DelegatedKeys.provision} flow. */
|
|
@@ -12161,8 +12162,9 @@ declare class WitniumchainClient {
|
|
|
12161
12162
|
enrollTotp(): Promise<TotpEnrollResponse>;
|
|
12162
12163
|
/**
|
|
12163
12164
|
* Confirming bumps the user's security epoch server-side, which ends every
|
|
12164
|
-
* session-minted access token
|
|
12165
|
-
* call mints a fresh
|
|
12165
|
+
* session-minted access token and OAuth artifact of the user. Cached and
|
|
12166
|
+
* in-flight tokens are dropped so the next bearer call mints a fresh one
|
|
12167
|
+
* from the (surviving) session.
|
|
12166
12168
|
*/
|
|
12167
12169
|
confirmTotp(body: TotpConfirmRequest): Promise<TotpConfirmResponse>;
|
|
12168
12170
|
/** Step-up: 403 `mfa_step_up_failed` on a wrong proof, 429 `mfa_rate_limited`. */
|
|
@@ -12280,6 +12282,12 @@ declare class WitniumchainClient {
|
|
|
12280
12282
|
* valid session.
|
|
12281
12283
|
*/
|
|
12282
12284
|
exchangeSessionForToken(): Promise<OAuthTokenSnapshot>;
|
|
12285
|
+
private assertCredentialGeneration;
|
|
12286
|
+
/**
|
|
12287
|
+
* Forget every cached credential and orphan in-flight mints/refreshes, so
|
|
12288
|
+
* none of them can store a token afterwards.
|
|
12289
|
+
*/
|
|
12290
|
+
private invalidateCredentials;
|
|
12283
12291
|
/**
|
|
12284
12292
|
* Best-effort transparent mint for the `BearerJWT` path: if no access token
|
|
12285
12293
|
* is cached, try the session exchange (single-flight). Swallows failure so
|
package/dist/index.d.ts
CHANGED
|
@@ -12050,6 +12050,7 @@ declare class WitniumchainClient {
|
|
|
12050
12050
|
private refreshInFlight;
|
|
12051
12051
|
private accessTokenFromSession;
|
|
12052
12052
|
private sessionExchangeInFlight;
|
|
12053
|
+
private credentialGeneration;
|
|
12053
12054
|
/** Subscriptions / billing helpers. See {@link Subscriptions}. */
|
|
12054
12055
|
readonly subscriptions: Subscriptions;
|
|
12055
12056
|
/** Delegated-key namespace including the one-call {@link DelegatedKeys.provision} flow. */
|
|
@@ -12161,8 +12162,9 @@ declare class WitniumchainClient {
|
|
|
12161
12162
|
enrollTotp(): Promise<TotpEnrollResponse>;
|
|
12162
12163
|
/**
|
|
12163
12164
|
* Confirming bumps the user's security epoch server-side, which ends every
|
|
12164
|
-
* session-minted access token
|
|
12165
|
-
* call mints a fresh
|
|
12165
|
+
* session-minted access token and OAuth artifact of the user. Cached and
|
|
12166
|
+
* in-flight tokens are dropped so the next bearer call mints a fresh one
|
|
12167
|
+
* from the (surviving) session.
|
|
12166
12168
|
*/
|
|
12167
12169
|
confirmTotp(body: TotpConfirmRequest): Promise<TotpConfirmResponse>;
|
|
12168
12170
|
/** Step-up: 403 `mfa_step_up_failed` on a wrong proof, 429 `mfa_rate_limited`. */
|
|
@@ -12280,6 +12282,12 @@ declare class WitniumchainClient {
|
|
|
12280
12282
|
* valid session.
|
|
12281
12283
|
*/
|
|
12282
12284
|
exchangeSessionForToken(): Promise<OAuthTokenSnapshot>;
|
|
12285
|
+
private assertCredentialGeneration;
|
|
12286
|
+
/**
|
|
12287
|
+
* Forget every cached credential and orphan in-flight mints/refreshes, so
|
|
12288
|
+
* none of them can store a token afterwards.
|
|
12289
|
+
*/
|
|
12290
|
+
private invalidateCredentials;
|
|
12283
12291
|
/**
|
|
12284
12292
|
* Best-effort transparent mint for the `BearerJWT` path: if no access token
|
|
12285
12293
|
* is cached, try the session exchange (single-flight). Swallows failure so
|
package/dist/index.js
CHANGED
|
@@ -121,6 +121,11 @@ var WitniumchainClient = class {
|
|
|
121
121
|
// first BearerJWT call (and any concurrent fan-out) awaits one in-flight
|
|
122
122
|
// mint rather than minting N tokens.
|
|
123
123
|
sessionExchangeInFlight;
|
|
124
|
+
// Bumped whenever the cached credentials stop being valid (sign-out, the
|
|
125
|
+
// TOTP-confirm epoch bump). A mint or refresh that started under an older
|
|
126
|
+
// generation must not store its result: it could be a previous user's
|
|
127
|
+
// token, or one the server has already ended.
|
|
128
|
+
credentialGeneration = 0;
|
|
124
129
|
/** Subscriptions / billing helpers. See {@link Subscriptions}. */
|
|
125
130
|
subscriptions;
|
|
126
131
|
/** Delegated-key namespace including the one-call {@link DelegatedKeys.provision} flow. */
|
|
@@ -502,18 +507,16 @@ var WitniumchainClient = class {
|
|
|
502
507
|
}
|
|
503
508
|
/**
|
|
504
509
|
* Confirming bumps the user's security epoch server-side, which ends every
|
|
505
|
-
* session-minted access token
|
|
506
|
-
* call mints a fresh
|
|
510
|
+
* session-minted access token and OAuth artifact of the user. Cached and
|
|
511
|
+
* in-flight tokens are dropped so the next bearer call mints a fresh one
|
|
512
|
+
* from the (surviving) session.
|
|
507
513
|
*/
|
|
508
514
|
async confirmTotp(body) {
|
|
509
515
|
const res = await this.req("POST", "/v1/account/mfa/totp/confirm", {
|
|
510
516
|
auth: "SessionCookie",
|
|
511
517
|
body
|
|
512
518
|
});
|
|
513
|
-
|
|
514
|
-
this.accessToken = void 0;
|
|
515
|
-
this.accessTokenFromSession = false;
|
|
516
|
-
}
|
|
519
|
+
this.invalidateCredentials();
|
|
517
520
|
return res;
|
|
518
521
|
}
|
|
519
522
|
/** Step-up: 403 `mfa_step_up_failed` on a wrong proof, 429 `mfa_rate_limited`. */
|
|
@@ -791,14 +794,16 @@ var WitniumchainClient = class {
|
|
|
791
794
|
*/
|
|
792
795
|
async refreshAccessToken() {
|
|
793
796
|
if (this.refreshInFlight) return this.refreshInFlight;
|
|
794
|
-
|
|
797
|
+
let flight = void 0;
|
|
798
|
+
flight = (async () => {
|
|
795
799
|
try {
|
|
796
800
|
return await this.refreshAccessTokenInternal();
|
|
797
801
|
} finally {
|
|
798
|
-
this.refreshInFlight = void 0;
|
|
802
|
+
if (this.refreshInFlight === flight) this.refreshInFlight = void 0;
|
|
799
803
|
}
|
|
800
804
|
})();
|
|
801
|
-
|
|
805
|
+
this.refreshInFlight = flight;
|
|
806
|
+
return flight;
|
|
802
807
|
}
|
|
803
808
|
/**
|
|
804
809
|
* Exchange the logged-in session (the `wac_session` cookie) for a short-lived
|
|
@@ -823,9 +828,12 @@ var WitniumchainClient = class {
|
|
|
823
828
|
*/
|
|
824
829
|
async exchangeSessionForToken() {
|
|
825
830
|
if (this.sessionExchangeInFlight) return this.sessionExchangeInFlight;
|
|
826
|
-
|
|
831
|
+
const generation = this.credentialGeneration;
|
|
832
|
+
let flight = void 0;
|
|
833
|
+
flight = (async () => {
|
|
827
834
|
try {
|
|
828
835
|
const res = await this.req("POST", "/v1/auth/access-token", { auth: "SessionCookie" });
|
|
836
|
+
this.assertCredentialGeneration(generation);
|
|
829
837
|
this.accessToken = res.accessToken;
|
|
830
838
|
this.accessTokenFromSession = true;
|
|
831
839
|
this.refreshToken = void 0;
|
|
@@ -835,10 +843,32 @@ var WitniumchainClient = class {
|
|
|
835
843
|
expiresAt: Math.floor(new Date(res.expiresAt).getTime() / 1e3)
|
|
836
844
|
};
|
|
837
845
|
} finally {
|
|
838
|
-
this.sessionExchangeInFlight = void 0;
|
|
846
|
+
if (this.sessionExchangeInFlight === flight) this.sessionExchangeInFlight = void 0;
|
|
839
847
|
}
|
|
840
848
|
})();
|
|
841
|
-
|
|
849
|
+
this.sessionExchangeInFlight = flight;
|
|
850
|
+
return flight;
|
|
851
|
+
}
|
|
852
|
+
assertCredentialGeneration(generation) {
|
|
853
|
+
if (generation !== this.credentialGeneration) {
|
|
854
|
+
throw new WitniumchainApiError({
|
|
855
|
+
status: 0,
|
|
856
|
+
message: "WitniumchainClient: the session changed (sign-out or MFA confirmation) while a token request was in flight; its token was discarded."
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Forget every cached credential and orphan in-flight mints/refreshes, so
|
|
862
|
+
* none of them can store a token afterwards.
|
|
863
|
+
*/
|
|
864
|
+
invalidateCredentials() {
|
|
865
|
+
this.credentialGeneration++;
|
|
866
|
+
this.accessToken = void 0;
|
|
867
|
+
this.accessTokenFromSession = false;
|
|
868
|
+
this.refreshToken = void 0;
|
|
869
|
+
this.hasRefreshCookie = false;
|
|
870
|
+
this.sessionExchangeInFlight = void 0;
|
|
871
|
+
this.refreshInFlight = void 0;
|
|
842
872
|
}
|
|
843
873
|
/**
|
|
844
874
|
* Best-effort transparent mint for the `BearerJWT` path: if no access token
|
|
@@ -850,7 +880,8 @@ var WitniumchainClient = class {
|
|
|
850
880
|
if (this.accessToken) return;
|
|
851
881
|
try {
|
|
852
882
|
await this.exchangeSessionForToken();
|
|
853
|
-
} catch {
|
|
883
|
+
} catch (err) {
|
|
884
|
+
if (!(err instanceof WitniumchainApiError && err.status === 401)) throw err;
|
|
854
885
|
}
|
|
855
886
|
}
|
|
856
887
|
/**
|
|
@@ -891,10 +922,7 @@ var WitniumchainClient = class {
|
|
|
891
922
|
* dropped — which it is, here.
|
|
892
923
|
*/
|
|
893
924
|
signOut() {
|
|
894
|
-
this.
|
|
895
|
-
this.accessTokenFromSession = false;
|
|
896
|
-
this.refreshToken = void 0;
|
|
897
|
-
this.hasRefreshCookie = false;
|
|
925
|
+
this.invalidateCredentials();
|
|
898
926
|
this.pendingLogins.clear();
|
|
899
927
|
}
|
|
900
928
|
// ────────────────────────────────────────────────────────────────────────
|
|
@@ -1014,6 +1042,7 @@ var WitniumchainClient = class {
|
|
|
1014
1042
|
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)."
|
|
1015
1043
|
});
|
|
1016
1044
|
}
|
|
1045
|
+
const generation = this.credentialGeneration;
|
|
1017
1046
|
const discovery = await this.fetchDiscovery();
|
|
1018
1047
|
const form = new URLSearchParams();
|
|
1019
1048
|
form.set("grant_type", "refresh_token");
|
|
@@ -1021,15 +1050,18 @@ var WitniumchainClient = class {
|
|
|
1021
1050
|
if (this.refreshToken) {
|
|
1022
1051
|
form.set("refresh_token", this.refreshToken);
|
|
1023
1052
|
}
|
|
1053
|
+
let tokens;
|
|
1024
1054
|
try {
|
|
1025
|
-
|
|
1026
|
-
return this.persistTokenResponse(tokens);
|
|
1055
|
+
tokens = await this.postTokenEndpoint(discovery.token_endpoint, form);
|
|
1027
1056
|
} catch (err) {
|
|
1057
|
+
this.assertCredentialGeneration(generation);
|
|
1028
1058
|
this.accessToken = void 0;
|
|
1029
1059
|
this.refreshToken = void 0;
|
|
1030
1060
|
this.hasRefreshCookie = false;
|
|
1031
1061
|
throw err;
|
|
1032
1062
|
}
|
|
1063
|
+
this.assertCredentialGeneration(generation);
|
|
1064
|
+
return this.persistTokenResponse(tokens);
|
|
1033
1065
|
}
|
|
1034
1066
|
// ────────────────────────────────────────────────────────────────────────
|
|
1035
1067
|
// Internal: fetch wrapper that maps non-2xx → WitniumchainApiError
|