@djangocfg/api 2.1.455 → 2.1.457
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/auth.cjs +1611 -2148
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +37 -82
- package/dist/auth.d.ts +37 -82
- package/dist/auth.mjs +1581 -2118
- package/dist/auth.mjs.map +1 -1
- package/dist/chunk-2G67QRNU.mjs +2096 -0
- package/dist/chunk-2G67QRNU.mjs.map +1 -0
- package/dist/chunk-32SRQGAC.mjs +2109 -0
- package/dist/chunk-32SRQGAC.mjs.map +1 -0
- package/dist/chunk-4BPRCONN.mjs +2098 -0
- package/dist/chunk-4BPRCONN.mjs.map +1 -0
- package/dist/chunk-5UZ2Z323.mjs +2021 -0
- package/dist/chunk-5UZ2Z323.mjs.map +1 -0
- package/dist/chunk-7KFTJXNM.mjs +2097 -0
- package/dist/chunk-7KFTJXNM.mjs.map +1 -0
- package/dist/chunk-BK4K5CVT.mjs +2019 -0
- package/dist/chunk-BK4K5CVT.mjs.map +1 -0
- package/dist/chunk-JLPJZ6WB.mjs +2020 -0
- package/dist/chunk-JLPJZ6WB.mjs.map +1 -0
- package/dist/chunk-TVU6PYJH.mjs +2032 -0
- package/dist/chunk-TVU6PYJH.mjs.map +1 -0
- package/dist/clients.cjs +292 -47
- package/dist/clients.cjs.map +1 -1
- package/dist/clients.d.cts +23 -0
- package/dist/clients.d.ts +23 -0
- package/dist/clients.mjs +292 -47
- package/dist/clients.mjs.map +1 -1
- package/dist/hooks.cjs +200 -32
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.mjs +200 -32
- package/dist/hooks.mjs.map +1 -1
- package/dist/index.cjs +292 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -4
- package/dist/index.d.ts +81 -4
- package/dist/index.mjs +292 -47
- package/dist/index.mjs.map +1 -1
- package/dist/sdk.gen-2SQOPTWJ.mjs +26 -0
- package/dist/sdk.gen-2SQOPTWJ.mjs.map +1 -0
- package/dist/sdk.gen-HSGK4C5S.mjs +26 -0
- package/dist/sdk.gen-HSGK4C5S.mjs.map +1 -0
- package/dist/sdk.gen-NUK2VGHO.mjs +25 -0
- package/dist/sdk.gen-NUK2VGHO.mjs.map +1 -0
- package/dist/sdk.gen-O4KAQUZB.mjs +26 -0
- package/dist/sdk.gen-O4KAQUZB.mjs.map +1 -0
- package/dist/sdk.gen-PPAVSBNT.mjs +26 -0
- package/dist/sdk.gen-PPAVSBNT.mjs.map +1 -0
- package/dist/sdk.gen-XLHLOCJ2.mjs +25 -0
- package/dist/sdk.gen-XLHLOCJ2.mjs.map +1 -0
- package/dist/sdk.gen-ZOE6NQAL.mjs +26 -0
- package/dist/sdk.gen-ZOE6NQAL.mjs.map +1 -0
- package/dist/sdk.gen-ZT7LGJVO.mjs +26 -0
- package/dist/sdk.gen-ZT7LGJVO.mjs.map +1 -0
- package/package.json +2 -2
- package/src/_api/generated/_cfg_accounts/hooks/index.ts +1 -0
- package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsTokenBlacklistCreate.ts +28 -0
- package/src/_api/generated/_cfg_accounts/openapi.json +99 -0
- package/src/_api/generated/_cfg_accounts/schemas/TokenBlacklistRequest.ts +11 -0
- package/src/_api/generated/_cfg_accounts/schemas/index.ts +1 -0
- package/src/_api/generated/_cfg_centrifugo/openapi.json +9 -0
- package/src/_api/generated/_cfg_totp/openapi.json +33 -0
- package/src/_api/generated/helpers/auth.ts +288 -31
- package/src/_api/generated/openapi.json +129 -0
- package/src/_api/generated/sdk.gen.ts +94 -16
- package/src/_api/generated/types.gen.ts +18 -0
- package/src/auth/__tests__/guard.test.ts +0 -31
- package/src/auth/constants.ts +6 -0
- package/src/auth/context/AccountsContext.tsx +14 -24
- package/src/auth/context/AuthContext.tsx +263 -607
- package/src/auth/context/types.ts +13 -0
- package/src/auth/hooks/index.ts +8 -5
- package/src/auth/hooks/useAuthRedirect.ts +17 -0
- package/src/auth/hooks/useGithubAuth.ts +3 -3
- package/src/auth/hooks/useSession.ts +22 -0
- package/src/auth/hooks/useTwoFactor.ts +8 -6
- package/src/auth/middlewares/index.ts +5 -6
- package/src/auth/utils/guard.ts +0 -22
- package/src/auth/utils/index.ts +0 -2
- package/src/_api/generated/_cfg_accounts/events.ts +0 -198
- package/src/_api/generated/_cfg_centrifugo/events.ts +0 -198
- package/src/_api/generated/_cfg_totp/events.ts +0 -198
- package/src/auth/__tests__/jwt.test.ts +0 -119
- package/src/auth/__tests__/sessionBootstrap.test.ts +0 -111
- package/src/auth/__tests__/useTokenRefresh.dom.test.tsx +0 -167
- package/src/auth/hooks/useAuthGuard.ts +0 -35
- package/src/auth/hooks/useTokenRefresh.ts +0 -131
- package/src/auth/refreshHandler.ts +0 -79
- package/src/auth/utils/jwt.ts +0 -66
package/dist/clients.d.cts
CHANGED
|
@@ -978,6 +978,9 @@ type SetupResponse = {
|
|
|
978
978
|
*/
|
|
979
979
|
expires_in: number;
|
|
980
980
|
};
|
|
981
|
+
type TokenBlacklistRequest = {
|
|
982
|
+
refresh: string;
|
|
983
|
+
};
|
|
981
984
|
type TokenRefresh = {
|
|
982
985
|
readonly access: string;
|
|
983
986
|
refresh: string;
|
|
@@ -1525,6 +1528,18 @@ type CfgAccountsProfileUpdateUpdateErrors = {
|
|
|
1525
1528
|
type CfgAccountsProfileUpdateUpdateResponses = {
|
|
1526
1529
|
200: User;
|
|
1527
1530
|
};
|
|
1531
|
+
type CfgAccountsTokenBlacklistCreateData = {
|
|
1532
|
+
body: TokenBlacklistRequest;
|
|
1533
|
+
path?: never;
|
|
1534
|
+
query?: never;
|
|
1535
|
+
url: '/cfg/accounts/token/blacklist/';
|
|
1536
|
+
};
|
|
1537
|
+
type CfgAccountsTokenBlacklistCreateResponses = {
|
|
1538
|
+
/**
|
|
1539
|
+
* No response body
|
|
1540
|
+
*/
|
|
1541
|
+
200: unknown;
|
|
1542
|
+
};
|
|
1528
1543
|
type CfgAccountsTokenRefreshCreateData = {
|
|
1529
1544
|
body: TokenRefreshRequest;
|
|
1530
1545
|
path?: never;
|
|
@@ -1823,6 +1838,14 @@ declare class CfgAccountsProfile {
|
|
|
1823
1838
|
static cfgAccountsProfileUpdateUpdate<ThrowOnError extends boolean = false>(options?: Options<CfgAccountsProfileUpdateUpdateData, ThrowOnError>): RequestResult<CfgAccountsProfileUpdateUpdateResponses, CfgAccountsProfileUpdateUpdateErrors, ThrowOnError>;
|
|
1824
1839
|
}
|
|
1825
1840
|
declare class CfgAccountsAuth {
|
|
1841
|
+
/**
|
|
1842
|
+
* Revoke a refresh token (logout).
|
|
1843
|
+
*
|
|
1844
|
+
* Blacklists the posted refresh token so it can never mint another access
|
|
1845
|
+
* token. Called best-effort by the client's logout — without it, "logout"
|
|
1846
|
+
* is purely client-side and a stolen refresh token survives until expiry.
|
|
1847
|
+
*/
|
|
1848
|
+
static cfgAccountsTokenBlacklistCreate<ThrowOnError extends boolean = false>(options: Options<CfgAccountsTokenBlacklistCreateData, ThrowOnError>): RequestResult<CfgAccountsTokenBlacklistCreateResponses, unknown, ThrowOnError>;
|
|
1826
1849
|
/**
|
|
1827
1850
|
* Refresh JWT token.
|
|
1828
1851
|
*
|
package/dist/clients.d.ts
CHANGED
|
@@ -978,6 +978,9 @@ type SetupResponse = {
|
|
|
978
978
|
*/
|
|
979
979
|
expires_in: number;
|
|
980
980
|
};
|
|
981
|
+
type TokenBlacklistRequest = {
|
|
982
|
+
refresh: string;
|
|
983
|
+
};
|
|
981
984
|
type TokenRefresh = {
|
|
982
985
|
readonly access: string;
|
|
983
986
|
refresh: string;
|
|
@@ -1525,6 +1528,18 @@ type CfgAccountsProfileUpdateUpdateErrors = {
|
|
|
1525
1528
|
type CfgAccountsProfileUpdateUpdateResponses = {
|
|
1526
1529
|
200: User;
|
|
1527
1530
|
};
|
|
1531
|
+
type CfgAccountsTokenBlacklistCreateData = {
|
|
1532
|
+
body: TokenBlacklistRequest;
|
|
1533
|
+
path?: never;
|
|
1534
|
+
query?: never;
|
|
1535
|
+
url: '/cfg/accounts/token/blacklist/';
|
|
1536
|
+
};
|
|
1537
|
+
type CfgAccountsTokenBlacklistCreateResponses = {
|
|
1538
|
+
/**
|
|
1539
|
+
* No response body
|
|
1540
|
+
*/
|
|
1541
|
+
200: unknown;
|
|
1542
|
+
};
|
|
1528
1543
|
type CfgAccountsTokenRefreshCreateData = {
|
|
1529
1544
|
body: TokenRefreshRequest;
|
|
1530
1545
|
path?: never;
|
|
@@ -1823,6 +1838,14 @@ declare class CfgAccountsProfile {
|
|
|
1823
1838
|
static cfgAccountsProfileUpdateUpdate<ThrowOnError extends boolean = false>(options?: Options<CfgAccountsProfileUpdateUpdateData, ThrowOnError>): RequestResult<CfgAccountsProfileUpdateUpdateResponses, CfgAccountsProfileUpdateUpdateErrors, ThrowOnError>;
|
|
1824
1839
|
}
|
|
1825
1840
|
declare class CfgAccountsAuth {
|
|
1841
|
+
/**
|
|
1842
|
+
* Revoke a refresh token (logout).
|
|
1843
|
+
*
|
|
1844
|
+
* Blacklists the posted refresh token so it can never mint another access
|
|
1845
|
+
* token. Called best-effort by the client's logout — without it, "logout"
|
|
1846
|
+
* is purely client-side and a stolen refresh token survives until expiry.
|
|
1847
|
+
*/
|
|
1848
|
+
static cfgAccountsTokenBlacklistCreate<ThrowOnError extends boolean = false>(options: Options<CfgAccountsTokenBlacklistCreateData, ThrowOnError>): RequestResult<CfgAccountsTokenBlacklistCreateResponses, unknown, ThrowOnError>;
|
|
1826
1849
|
/**
|
|
1827
1850
|
* Refresh JWT token.
|
|
1828
1851
|
*
|
package/dist/clients.mjs
CHANGED
|
@@ -169,6 +169,89 @@ var _onUnauthorized = null;
|
|
|
169
169
|
var _refreshHandler = null;
|
|
170
170
|
var _refreshInflight = null;
|
|
171
171
|
var RETRY_MARKER = "X-Auth-Retry";
|
|
172
|
+
function jwtExpMs(token) {
|
|
173
|
+
try {
|
|
174
|
+
const payload = token.split(".")[1];
|
|
175
|
+
if (!payload) return null;
|
|
176
|
+
const json = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
177
|
+
return typeof json.exp === "number" ? json.exp * 1e3 : null;
|
|
178
|
+
} catch {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
__name(jwtExpMs, "jwtExpMs");
|
|
183
|
+
function computeSnapshot() {
|
|
184
|
+
const access = _storage.get(ACCESS_KEY);
|
|
185
|
+
const refresh = _storage.get(REFRESH_KEY);
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
const accessExp = access ? jwtExpMs(access) : null;
|
|
188
|
+
const accessAlive = access !== null && (accessExp === null || accessExp > now);
|
|
189
|
+
const refreshExp = refresh ? jwtExpMs(refresh) : null;
|
|
190
|
+
const refreshAlive = refresh !== null && (refreshExp === null || refreshExp > now);
|
|
191
|
+
return {
|
|
192
|
+
status: accessAlive || refreshAlive ? "authenticated" : "anonymous",
|
|
193
|
+
accessExpiresAt: accessExp
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
__name(computeSnapshot, "computeSnapshot");
|
|
197
|
+
var SERVER_SNAPSHOT = { status: "anonymous", accessExpiresAt: null };
|
|
198
|
+
var SESSION_SYNC_EVENT = `cfg-auth:changed:${ACCESS_KEY}`;
|
|
199
|
+
var _snapshot = computeSnapshot();
|
|
200
|
+
var _sessionListeners = /* @__PURE__ */ new Set();
|
|
201
|
+
var _expiryTimer = null;
|
|
202
|
+
var _storageListenerInstalled = false;
|
|
203
|
+
function scheduleExpiryFlip() {
|
|
204
|
+
if (!isBrowser) return;
|
|
205
|
+
if (_expiryTimer !== null) {
|
|
206
|
+
clearTimeout(_expiryTimer);
|
|
207
|
+
_expiryTimer = null;
|
|
208
|
+
}
|
|
209
|
+
if (_sessionListeners.size === 0) return;
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
const exps = [];
|
|
212
|
+
const access = _storage.get(ACCESS_KEY);
|
|
213
|
+
const refresh = _storage.get(REFRESH_KEY);
|
|
214
|
+
const accessExp = access ? jwtExpMs(access) : null;
|
|
215
|
+
const refreshExp = refresh ? jwtExpMs(refresh) : null;
|
|
216
|
+
if (accessExp !== null && accessExp > now) exps.push(accessExp);
|
|
217
|
+
if (refreshExp !== null && refreshExp > now) exps.push(refreshExp);
|
|
218
|
+
if (!exps.length) return;
|
|
219
|
+
const delay = Math.min(Math.min(...exps) - now + 250, 2147483647);
|
|
220
|
+
_expiryTimer = setTimeout(notifySessionChanged, delay);
|
|
221
|
+
}
|
|
222
|
+
__name(scheduleExpiryFlip, "scheduleExpiryFlip");
|
|
223
|
+
function notifySessionChanged() {
|
|
224
|
+
const next = computeSnapshot();
|
|
225
|
+
const changed = next.status !== _snapshot.status || next.accessExpiresAt !== _snapshot.accessExpiresAt;
|
|
226
|
+
if (changed) _snapshot = next;
|
|
227
|
+
scheduleExpiryFlip();
|
|
228
|
+
if (!changed) return;
|
|
229
|
+
for (const listener of Array.from(_sessionListeners)) {
|
|
230
|
+
try {
|
|
231
|
+
listener();
|
|
232
|
+
} catch {
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (isBrowser) {
|
|
236
|
+
try {
|
|
237
|
+
window.dispatchEvent(new Event(SESSION_SYNC_EVENT));
|
|
238
|
+
} catch {
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
__name(notifySessionChanged, "notifySessionChanged");
|
|
243
|
+
function ensureStorageSync() {
|
|
244
|
+
if (!isBrowser || _storageListenerInstalled) return;
|
|
245
|
+
_storageListenerInstalled = true;
|
|
246
|
+
window.addEventListener("storage", (e) => {
|
|
247
|
+
if (e.key === null || e.key === ACCESS_KEY || e.key === REFRESH_KEY) {
|
|
248
|
+
notifySessionChanged();
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
window.addEventListener(SESSION_SYNC_EVENT, () => notifySessionChanged());
|
|
252
|
+
}
|
|
253
|
+
__name(ensureStorageSync, "ensureStorageSync");
|
|
254
|
+
var _sessionExpiredHandlers = /* @__PURE__ */ new Set();
|
|
172
255
|
var _client = null;
|
|
173
256
|
function pushClientConfig() {
|
|
174
257
|
if (!_client) return;
|
|
@@ -186,6 +269,7 @@ var auth = {
|
|
|
186
269
|
setStorageMode(mode) {
|
|
187
270
|
_storageMode = mode;
|
|
188
271
|
_storage = mode === "cookie" ? cookieBackend : localStorageBackend;
|
|
272
|
+
notifySessionChanged();
|
|
189
273
|
},
|
|
190
274
|
// ── Bearer token ──────────────────────────────────────────────────
|
|
191
275
|
getToken() {
|
|
@@ -193,19 +277,79 @@ var auth = {
|
|
|
193
277
|
},
|
|
194
278
|
setToken(token) {
|
|
195
279
|
_storage.set(ACCESS_KEY, token);
|
|
280
|
+
notifySessionChanged();
|
|
196
281
|
},
|
|
197
282
|
getRefreshToken() {
|
|
198
283
|
return _storage.get(REFRESH_KEY);
|
|
199
284
|
},
|
|
200
285
|
setRefreshToken(token) {
|
|
201
286
|
_storage.set(REFRESH_KEY, token);
|
|
287
|
+
notifySessionChanged();
|
|
202
288
|
},
|
|
203
289
|
clearTokens() {
|
|
204
290
|
_storage.set(ACCESS_KEY, null);
|
|
205
291
|
_storage.set(REFRESH_KEY, null);
|
|
292
|
+
notifySessionChanged();
|
|
206
293
|
},
|
|
294
|
+
/** Session-aware: token PRESENT and not past its `exp` (or a live refresh
|
|
295
|
+
* token exists that can mint one). Prefer `getSnapshot().status` in React. */
|
|
207
296
|
isAuthenticated() {
|
|
208
|
-
return
|
|
297
|
+
return computeSnapshot().status === "authenticated";
|
|
298
|
+
},
|
|
299
|
+
// ── Session (the ONE write path for login/logout flows) ──────────
|
|
300
|
+
/**
|
|
301
|
+
* Persist a token pair atomically. Every login flow (OTP verify, 2FA,
|
|
302
|
+
* OAuth callback) and the refresh handler should end here — do NOT
|
|
303
|
+
* scatter `setToken`/`setRefreshToken` pairs through app code.
|
|
304
|
+
* `refresh: undefined` keeps the current refresh token (access-only
|
|
305
|
+
* rotation); `refresh: null` explicitly drops it.
|
|
306
|
+
*/
|
|
307
|
+
setSession(tokens) {
|
|
308
|
+
_storage.set(ACCESS_KEY, tokens.access);
|
|
309
|
+
if (tokens.refresh !== void 0) _storage.set(REFRESH_KEY, tokens.refresh);
|
|
310
|
+
notifySessionChanged();
|
|
311
|
+
},
|
|
312
|
+
clearSession() {
|
|
313
|
+
auth.clearTokens();
|
|
314
|
+
},
|
|
315
|
+
// ── Reactive snapshot (for useSyncExternalStore) ──────────────────
|
|
316
|
+
/**
|
|
317
|
+
* @example React:
|
|
318
|
+
* const session = useSyncExternalStore(
|
|
319
|
+
* auth.subscribe, auth.getSnapshot, auth.getServerSnapshot,
|
|
320
|
+
* );
|
|
321
|
+
* const isAuthenticated = session.status === 'authenticated';
|
|
322
|
+
*/
|
|
323
|
+
getSnapshot() {
|
|
324
|
+
return _snapshot;
|
|
325
|
+
},
|
|
326
|
+
getServerSnapshot() {
|
|
327
|
+
return SERVER_SNAPSHOT;
|
|
328
|
+
},
|
|
329
|
+
subscribe(listener) {
|
|
330
|
+
ensureStorageSync();
|
|
331
|
+
_sessionListeners.add(listener);
|
|
332
|
+
notifySessionChanged();
|
|
333
|
+
return () => {
|
|
334
|
+
_sessionListeners.delete(listener);
|
|
335
|
+
if (_sessionListeners.size === 0 && _expiryTimer !== null) {
|
|
336
|
+
clearTimeout(_expiryTimer);
|
|
337
|
+
_expiryTimer = null;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
},
|
|
341
|
+
/**
|
|
342
|
+
* Fired on TERMINAL 401 — after the refresh+retry path is exhausted.
|
|
343
|
+
* The store has already cleared the session before calling back, so
|
|
344
|
+
* handlers only need to route to login (no clear-then-redirect
|
|
345
|
+
* ordering to get wrong). Returns an unsubscribe function; multiple
|
|
346
|
+
* handlers compose (unlike the legacy single-slot `onUnauthorized`).
|
|
347
|
+
*/
|
|
348
|
+
onSessionExpired(cb) {
|
|
349
|
+
_sessionExpiredHandlers.add(cb);
|
|
350
|
+
return () => {
|
|
351
|
+
_sessionExpiredHandlers.delete(cb);
|
|
352
|
+
};
|
|
209
353
|
},
|
|
210
354
|
// ── API key ───────────────────────────────────────────────────────
|
|
211
355
|
getApiKey() {
|
|
@@ -287,15 +431,22 @@ var auth = {
|
|
|
287
431
|
async function tryRefresh() {
|
|
288
432
|
if (_refreshInflight) return _refreshInflight;
|
|
289
433
|
if (!_refreshHandler) return null;
|
|
290
|
-
const
|
|
291
|
-
|
|
434
|
+
const runRefresh = /* @__PURE__ */ __name(async () => {
|
|
435
|
+
const refresh = auth.getRefreshToken();
|
|
436
|
+
if (!refresh) return null;
|
|
437
|
+
const result = await _refreshHandler(refresh);
|
|
438
|
+
if (!result?.access) return null;
|
|
439
|
+
auth.setToken(result.access);
|
|
440
|
+
if (result.refresh) auth.setRefreshToken(result.refresh);
|
|
441
|
+
return result.access;
|
|
442
|
+
}, "runRefresh");
|
|
292
443
|
_refreshInflight = (async () => {
|
|
293
444
|
try {
|
|
294
|
-
const
|
|
295
|
-
if (
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return
|
|
445
|
+
const locks = typeof navigator !== "undefined" ? navigator.locks : void 0;
|
|
446
|
+
if (locks?.request) {
|
|
447
|
+
return await locks.request(`${REFRESH_KEY}:refresh`, runRefresh);
|
|
448
|
+
}
|
|
449
|
+
return await runRefresh();
|
|
299
450
|
} catch {
|
|
300
451
|
return null;
|
|
301
452
|
} finally {
|
|
@@ -305,6 +456,22 @@ async function tryRefresh() {
|
|
|
305
456
|
return _refreshInflight;
|
|
306
457
|
}
|
|
307
458
|
__name(tryRefresh, "tryRefresh");
|
|
459
|
+
function expireSession(response) {
|
|
460
|
+
auth.clearTokens();
|
|
461
|
+
for (const cb of Array.from(_sessionExpiredHandlers)) {
|
|
462
|
+
try {
|
|
463
|
+
cb(response);
|
|
464
|
+
} catch {
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (_onUnauthorized) {
|
|
468
|
+
try {
|
|
469
|
+
_onUnauthorized(response);
|
|
470
|
+
} catch {
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
__name(expireSession, "expireSession");
|
|
308
475
|
function dpopEnabled() {
|
|
309
476
|
try {
|
|
310
477
|
return typeof process !== "undefined" && process.env?.NEXT_PUBLIC_DPOP_ENABLED === "true";
|
|
@@ -434,22 +601,12 @@ function installAuthOnClient(client2) {
|
|
|
434
601
|
client2.interceptors.response.use(async (response, request) => {
|
|
435
602
|
if (response.status !== 401) return response;
|
|
436
603
|
if (request.headers.get(RETRY_MARKER)) {
|
|
437
|
-
|
|
438
|
-
try {
|
|
439
|
-
_onUnauthorized(response);
|
|
440
|
-
} catch {
|
|
441
|
-
}
|
|
442
|
-
}
|
|
604
|
+
expireSession(response);
|
|
443
605
|
return response;
|
|
444
606
|
}
|
|
445
607
|
const newToken = await tryRefresh();
|
|
446
608
|
if (!newToken) {
|
|
447
|
-
|
|
448
|
-
try {
|
|
449
|
-
_onUnauthorized(response);
|
|
450
|
-
} catch {
|
|
451
|
-
}
|
|
452
|
-
}
|
|
609
|
+
expireSession(response);
|
|
453
610
|
return response;
|
|
454
611
|
}
|
|
455
612
|
const retry = request.clone();
|
|
@@ -461,25 +618,36 @@ function installAuthOnClient(client2) {
|
|
|
461
618
|
}
|
|
462
619
|
try {
|
|
463
620
|
const retried = await fetch(retry);
|
|
464
|
-
if (retried.status === 401
|
|
465
|
-
try {
|
|
466
|
-
_onUnauthorized(retried);
|
|
467
|
-
} catch {
|
|
468
|
-
}
|
|
469
|
-
}
|
|
621
|
+
if (retried.status === 401) expireSession(retried);
|
|
470
622
|
return retried;
|
|
471
623
|
} catch {
|
|
472
|
-
if (_onUnauthorized) {
|
|
473
|
-
try {
|
|
474
|
-
_onUnauthorized(response);
|
|
475
|
-
} catch {
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
624
|
return response;
|
|
479
625
|
}
|
|
480
626
|
});
|
|
481
627
|
}
|
|
482
628
|
__name(installAuthOnClient, "installAuthOnClient");
|
|
629
|
+
var REFRESH_ENDPOINT = "/cfg/accounts/token/refresh/";
|
|
630
|
+
auth.setRefreshHandler(async (refresh) => {
|
|
631
|
+
try {
|
|
632
|
+
const url = `${auth.getBaseUrl()}${REFRESH_ENDPOINT}`;
|
|
633
|
+
const headers = { "Content-Type": "application/json" };
|
|
634
|
+
if (dpopEnabled() && typeof window !== "undefined") {
|
|
635
|
+
const proof = await _makeDpopProof("POST", url);
|
|
636
|
+
if (proof) headers["DPoP"] = proof;
|
|
637
|
+
}
|
|
638
|
+
const res = await fetch(url, {
|
|
639
|
+
method: "POST",
|
|
640
|
+
headers,
|
|
641
|
+
credentials: auth.getWithCredentials() ? "include" : "same-origin",
|
|
642
|
+
body: JSON.stringify({ refresh })
|
|
643
|
+
});
|
|
644
|
+
if (!res.ok) return null;
|
|
645
|
+
const data = await res.json();
|
|
646
|
+
return data?.access ? { access: data.access, refresh: data.refresh ?? refresh } : null;
|
|
647
|
+
} catch {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
});
|
|
483
651
|
|
|
484
652
|
// src/_api/generated/helpers/logger.ts
|
|
485
653
|
import { createConsola } from "consola";
|
|
@@ -1504,7 +1672,11 @@ var CfgAccountsOauth = class {
|
|
|
1504
1672
|
*/
|
|
1505
1673
|
static cfgAccountsOauthConnectionsList(options) {
|
|
1506
1674
|
return (options?.client ?? client).get({
|
|
1507
|
-
security: [
|
|
1675
|
+
security: [
|
|
1676
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
1677
|
+
{ scheme: "bearer", type: "http" },
|
|
1678
|
+
{ name: "Authorization", type: "apiKey" }
|
|
1679
|
+
],
|
|
1508
1680
|
url: "/cfg/accounts/oauth/connections/",
|
|
1509
1681
|
...options
|
|
1510
1682
|
});
|
|
@@ -1516,7 +1688,11 @@ var CfgAccountsOauth = class {
|
|
|
1516
1688
|
*/
|
|
1517
1689
|
static cfgAccountsOauthDisconnectCreate(options) {
|
|
1518
1690
|
return (options.client ?? client).post({
|
|
1519
|
-
security: [
|
|
1691
|
+
security: [
|
|
1692
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
1693
|
+
{ scheme: "bearer", type: "http" },
|
|
1694
|
+
{ name: "Authorization", type: "apiKey" }
|
|
1695
|
+
],
|
|
1520
1696
|
url: "/cfg/accounts/oauth/disconnect/",
|
|
1521
1697
|
...options,
|
|
1522
1698
|
headers: {
|
|
@@ -1573,7 +1749,11 @@ var CfgAccounts = class {
|
|
|
1573
1749
|
*/
|
|
1574
1750
|
static cfgAccountsOtpRequestCreate(options) {
|
|
1575
1751
|
return (options.client ?? client).post({
|
|
1576
|
-
security: [
|
|
1752
|
+
security: [
|
|
1753
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
1754
|
+
{ scheme: "bearer", type: "http" },
|
|
1755
|
+
{ name: "Authorization", type: "apiKey" }
|
|
1756
|
+
],
|
|
1577
1757
|
url: "/cfg/accounts/otp/request/",
|
|
1578
1758
|
...options,
|
|
1579
1759
|
headers: {
|
|
@@ -1594,7 +1774,11 @@ var CfgAccounts = class {
|
|
|
1594
1774
|
*/
|
|
1595
1775
|
static cfgAccountsOtpVerifyCreate(options) {
|
|
1596
1776
|
return (options.client ?? client).post({
|
|
1597
|
-
security: [
|
|
1777
|
+
security: [
|
|
1778
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
1779
|
+
{ scheme: "bearer", type: "http" },
|
|
1780
|
+
{ name: "Authorization", type: "apiKey" }
|
|
1781
|
+
],
|
|
1598
1782
|
url: "/cfg/accounts/otp/verify/",
|
|
1599
1783
|
...options,
|
|
1600
1784
|
headers: {
|
|
@@ -1632,7 +1816,11 @@ var CfgAccountsProfile = class {
|
|
|
1632
1816
|
static cfgAccountsProfileAvatarCreate(options) {
|
|
1633
1817
|
return (options?.client ?? client).post({
|
|
1634
1818
|
...formDataBodySerializer,
|
|
1635
|
-
security: [
|
|
1819
|
+
security: [
|
|
1820
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
1821
|
+
{ scheme: "bearer", type: "http" },
|
|
1822
|
+
{ name: "Authorization", type: "apiKey" }
|
|
1823
|
+
],
|
|
1636
1824
|
url: "/cfg/accounts/profile/avatar/",
|
|
1637
1825
|
...options,
|
|
1638
1826
|
headers: {
|
|
@@ -1752,6 +1940,23 @@ var CfgAccountsAuth = class {
|
|
|
1752
1940
|
static {
|
|
1753
1941
|
__name(this, "CfgAccountsAuth");
|
|
1754
1942
|
}
|
|
1943
|
+
/**
|
|
1944
|
+
* Revoke a refresh token (logout).
|
|
1945
|
+
*
|
|
1946
|
+
* Blacklists the posted refresh token so it can never mint another access
|
|
1947
|
+
* token. Called best-effort by the client's logout — without it, "logout"
|
|
1948
|
+
* is purely client-side and a stolen refresh token survives until expiry.
|
|
1949
|
+
*/
|
|
1950
|
+
static cfgAccountsTokenBlacklistCreate(options) {
|
|
1951
|
+
return (options.client ?? client).post({
|
|
1952
|
+
url: "/cfg/accounts/token/blacklist/",
|
|
1953
|
+
...options,
|
|
1954
|
+
headers: {
|
|
1955
|
+
"Content-Type": "application/json",
|
|
1956
|
+
...options.headers
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1755
1960
|
/**
|
|
1756
1961
|
* Refresh JWT token.
|
|
1757
1962
|
*
|
|
@@ -1783,7 +1988,11 @@ var CfgCentrifugo = class {
|
|
|
1783
1988
|
*/
|
|
1784
1989
|
static cfgCentrifugoAuthTokenRetrieve(options) {
|
|
1785
1990
|
return (options?.client ?? client).get({
|
|
1786
|
-
security: [
|
|
1991
|
+
security: [
|
|
1992
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
1993
|
+
{ scheme: "bearer", type: "http" },
|
|
1994
|
+
{ name: "Authorization", type: "apiKey" }
|
|
1995
|
+
],
|
|
1787
1996
|
url: "/cfg/centrifugo/auth/token/",
|
|
1788
1997
|
...options
|
|
1789
1998
|
});
|
|
@@ -1798,7 +2007,11 @@ var CfgTotpBackupCodes = class {
|
|
|
1798
2007
|
*/
|
|
1799
2008
|
static cfgTotpBackupCodesRetrieve(options) {
|
|
1800
2009
|
return (options?.client ?? client).get({
|
|
1801
|
-
security: [
|
|
2010
|
+
security: [
|
|
2011
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2012
|
+
{ scheme: "bearer", type: "http" },
|
|
2013
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2014
|
+
],
|
|
1802
2015
|
url: "/cfg/totp/backup-codes/",
|
|
1803
2016
|
...options
|
|
1804
2017
|
});
|
|
@@ -1811,7 +2024,11 @@ var CfgTotpBackupCodes = class {
|
|
|
1811
2024
|
*/
|
|
1812
2025
|
static cfgTotpBackupCodesRegenerateCreate(options) {
|
|
1813
2026
|
return (options.client ?? client).post({
|
|
1814
|
-
security: [
|
|
2027
|
+
security: [
|
|
2028
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2029
|
+
{ scheme: "bearer", type: "http" },
|
|
2030
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2031
|
+
],
|
|
1815
2032
|
url: "/cfg/totp/backup-codes/regenerate/",
|
|
1816
2033
|
...options,
|
|
1817
2034
|
headers: {
|
|
@@ -1830,7 +2047,11 @@ var CfgTotp = class {
|
|
|
1830
2047
|
*/
|
|
1831
2048
|
static cfgTotpDevicesRetrieve(options) {
|
|
1832
2049
|
return (options?.client ?? client).get({
|
|
1833
|
-
security: [
|
|
2050
|
+
security: [
|
|
2051
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2052
|
+
{ scheme: "bearer", type: "http" },
|
|
2053
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2054
|
+
],
|
|
1834
2055
|
url: "/cfg/totp/devices/",
|
|
1835
2056
|
...options
|
|
1836
2057
|
});
|
|
@@ -1842,7 +2063,11 @@ var CfgTotp = class {
|
|
|
1842
2063
|
*/
|
|
1843
2064
|
static cfgTotpDevicesDestroy(options) {
|
|
1844
2065
|
return (options.client ?? client).delete({
|
|
1845
|
-
security: [
|
|
2066
|
+
security: [
|
|
2067
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2068
|
+
{ scheme: "bearer", type: "http" },
|
|
2069
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2070
|
+
],
|
|
1846
2071
|
url: "/cfg/totp/devices/{id}/",
|
|
1847
2072
|
...options
|
|
1848
2073
|
});
|
|
@@ -1854,7 +2079,11 @@ var CfgTotp = class {
|
|
|
1854
2079
|
*/
|
|
1855
2080
|
static cfgTotpDisableCreate(options) {
|
|
1856
2081
|
return (options.client ?? client).post({
|
|
1857
|
-
security: [
|
|
2082
|
+
security: [
|
|
2083
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2084
|
+
{ scheme: "bearer", type: "http" },
|
|
2085
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2086
|
+
],
|
|
1858
2087
|
url: "/cfg/totp/disable/",
|
|
1859
2088
|
...options,
|
|
1860
2089
|
headers: {
|
|
@@ -1875,7 +2104,11 @@ var CfgTotpSetup = class {
|
|
|
1875
2104
|
*/
|
|
1876
2105
|
static cfgTotpSetupCreate(options) {
|
|
1877
2106
|
return (options?.client ?? client).post({
|
|
1878
|
-
security: [
|
|
2107
|
+
security: [
|
|
2108
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2109
|
+
{ scheme: "bearer", type: "http" },
|
|
2110
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2111
|
+
],
|
|
1879
2112
|
url: "/cfg/totp/setup/",
|
|
1880
2113
|
...options,
|
|
1881
2114
|
headers: {
|
|
@@ -1891,7 +2124,11 @@ var CfgTotpSetup = class {
|
|
|
1891
2124
|
*/
|
|
1892
2125
|
static cfgTotpSetupConfirmCreate(options) {
|
|
1893
2126
|
return (options.client ?? client).post({
|
|
1894
|
-
security: [
|
|
2127
|
+
security: [
|
|
2128
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2129
|
+
{ scheme: "bearer", type: "http" },
|
|
2130
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2131
|
+
],
|
|
1895
2132
|
url: "/cfg/totp/setup/confirm/",
|
|
1896
2133
|
...options,
|
|
1897
2134
|
headers: {
|
|
@@ -1912,7 +2149,11 @@ var CfgTotpVerify = class {
|
|
|
1912
2149
|
*/
|
|
1913
2150
|
static cfgTotpVerifyCreate(options) {
|
|
1914
2151
|
return (options.client ?? client).post({
|
|
1915
|
-
security: [
|
|
2152
|
+
security: [
|
|
2153
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2154
|
+
{ scheme: "bearer", type: "http" },
|
|
2155
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2156
|
+
],
|
|
1916
2157
|
url: "/cfg/totp/verify/",
|
|
1917
2158
|
...options,
|
|
1918
2159
|
headers: {
|
|
@@ -1928,7 +2169,11 @@ var CfgTotpVerify = class {
|
|
|
1928
2169
|
*/
|
|
1929
2170
|
static cfgTotpVerifyBackupCreate(options) {
|
|
1930
2171
|
return (options.client ?? client).post({
|
|
1931
|
-
security: [
|
|
2172
|
+
security: [
|
|
2173
|
+
{ name: "X-API-Key", type: "apiKey" },
|
|
2174
|
+
{ scheme: "bearer", type: "http" },
|
|
2175
|
+
{ name: "Authorization", type: "apiKey" }
|
|
2176
|
+
],
|
|
1932
2177
|
url: "/cfg/totp/verify/backup/",
|
|
1933
2178
|
...options,
|
|
1934
2179
|
headers: {
|