@feelflow/ffid-sdk 5.19.0 → 5.21.0
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/agency/index.cjs +4 -2
- package/dist/agency/index.js +4 -2
- package/dist/announcements/index.cjs +2 -1
- package/dist/announcements/index.js +2 -1
- package/dist/{chunk-TW2FXASO.cjs → chunk-RDQ4R3XC.cjs} +96 -49
- package/dist/{chunk-D3PZ6SZB.js → chunk-U57ZDFEN.js} +96 -49
- package/dist/components/index.cjs +8 -8
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{ffid-client-BuDM5tmq.d.cts → ffid-client-BQPhm-XL.d.cts} +54 -8
- package/dist/{ffid-client-D0x8TBS5.d.ts → ffid-client-Bx8y4SwC.d.ts} +54 -8
- package/dist/{index-Bkul-fRw.d.cts → index--wRiPlpi.d.cts} +54 -8
- package/dist/{index-Bkul-fRw.d.ts → index--wRiPlpi.d.ts} +54 -8
- package/dist/index.cjs +42 -42
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/legal/index.cjs +2 -1
- package/dist/legal/index.js +2 -1
- package/dist/server/index.cjs +94 -48
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +94 -48
- package/dist/server/test/index.d.cts +1 -1
- package/dist/server/test/index.d.ts +1 -1
- package/dist/webhooks/index.cjs +2 -2
- package/dist/webhooks/index.js +2 -2
- package/package.json +1 -1
package/dist/agency/index.cjs
CHANGED
|
@@ -16,8 +16,10 @@ var noopLogger = {
|
|
|
16
16
|
},
|
|
17
17
|
info: () => {
|
|
18
18
|
},
|
|
19
|
-
warn: (
|
|
20
|
-
|
|
19
|
+
warn: () => {
|
|
20
|
+
},
|
|
21
|
+
error: () => {
|
|
22
|
+
}
|
|
21
23
|
};
|
|
22
24
|
var consoleLogger = {
|
|
23
25
|
debug: (...args) => console.debug(SDK_LOG_PREFIX, ...args),
|
package/dist/agency/index.js
CHANGED
|
@@ -15,8 +15,10 @@ var noopLogger = {
|
|
|
15
15
|
},
|
|
16
16
|
info: () => {
|
|
17
17
|
},
|
|
18
|
-
warn: (
|
|
19
|
-
|
|
18
|
+
warn: () => {
|
|
19
|
+
},
|
|
20
|
+
error: () => {
|
|
21
|
+
}
|
|
20
22
|
};
|
|
21
23
|
var consoleLogger = {
|
|
22
24
|
debug: (...args) => console.debug(SDK_LOG_PREFIX, ...args),
|
|
@@ -266,10 +266,12 @@ var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
|
|
|
266
266
|
var CACHE_KEY_PREFIX = "ffid:introspect:";
|
|
267
267
|
var HEX_BASE = 16;
|
|
268
268
|
var HEX_BYTE_WIDTH = 2;
|
|
269
|
-
var TOKEN_LOG_PREFIX_LENGTH = 8;
|
|
270
269
|
function createVerifyAccessToken(deps) {
|
|
271
270
|
const { authMode, baseUrl, serviceCode, serviceApiKey, verifyStrategy, logger, createError, errorCodes, cache, timeout } = deps;
|
|
272
271
|
let jwtVerify2 = null;
|
|
272
|
+
let cacheReadFailureEscalated = false;
|
|
273
|
+
let cacheWriteFailureEscalated = false;
|
|
274
|
+
let missingSubtleCryptoLogged = false;
|
|
273
275
|
function getJwtVerifier() {
|
|
274
276
|
if (!jwtVerify2) {
|
|
275
277
|
jwtVerify2 = createJwtVerifier({
|
|
@@ -329,8 +331,9 @@ function createVerifyAccessToken(deps) {
|
|
|
329
331
|
}
|
|
330
332
|
const url = `${baseUrl}${OAUTH_INTROSPECT_ENDPOINT}`;
|
|
331
333
|
logger.debug("Verifying access token:", url);
|
|
332
|
-
const cacheKey = cache ? await buildCacheKey(accessToken, cacheKeySuffix) :
|
|
333
|
-
|
|
334
|
+
const cacheKey = cache ? await buildCacheKey(accessToken, cacheKeySuffix) : null;
|
|
335
|
+
let verificationCacheDegraded = cache !== void 0 && cacheKey === null;
|
|
336
|
+
if (cache && cacheKey !== null) {
|
|
334
337
|
try {
|
|
335
338
|
const cached = await cache.adapter.get(cacheKey);
|
|
336
339
|
if (cached && typeof cached === "object" && "sub" in cached) {
|
|
@@ -338,7 +341,16 @@ function createVerifyAccessToken(deps) {
|
|
|
338
341
|
return { data: cached };
|
|
339
342
|
}
|
|
340
343
|
} catch (cacheError) {
|
|
341
|
-
|
|
344
|
+
verificationCacheDegraded = true;
|
|
345
|
+
if (!cacheReadFailureEscalated) {
|
|
346
|
+
cacheReadFailureEscalated = true;
|
|
347
|
+
logger.error(
|
|
348
|
+
"Cache read failed \u2014 falling back to API call. Redis \u7B49\u306E cache adapter \u969C\u5BB3\u6642\u306F\u5168 verification \u304C introspect \u306B degrade \u3057\u307E\u3059\uFF08\u3053\u306E error \u306F instance \u3054\u3068\u306B\u521D\u56DE\u306E\u307F\u3001\u4EE5\u964D\u306F warn\uFF09:",
|
|
349
|
+
cacheError
|
|
350
|
+
);
|
|
351
|
+
} else {
|
|
352
|
+
logger.warn("Cache read failed, falling back to API call:", cacheError);
|
|
353
|
+
}
|
|
342
354
|
}
|
|
343
355
|
}
|
|
344
356
|
const fetchOptions = {
|
|
@@ -433,31 +445,40 @@ function createVerifyAccessToken(deps) {
|
|
|
433
445
|
}
|
|
434
446
|
} : base;
|
|
435
447
|
const userinfo = normalizeUserinfo(raw);
|
|
436
|
-
if (cache) {
|
|
448
|
+
if (cache && cacheKey !== null) {
|
|
437
449
|
try {
|
|
438
450
|
await cache.adapter.set(cacheKey, userinfo, cache.ttl);
|
|
439
451
|
} catch (cacheError) {
|
|
440
|
-
|
|
452
|
+
verificationCacheDegraded = true;
|
|
453
|
+
if (!cacheWriteFailureEscalated) {
|
|
454
|
+
cacheWriteFailureEscalated = true;
|
|
455
|
+
logger.error(
|
|
456
|
+
"Cache write failed \u2014 result still returned. cache adapter \u969C\u5BB3\u6642\u306F introspect \u7D50\u679C\u304C\u30AD\u30E3\u30C3\u30B7\u30E5\u3055\u308C\u305A\u5168 verification \u304C API \u547C\u3073\u51FA\u3057\u306B degrade \u3057\u307E\u3059\uFF08\u3053\u306E error \u306F instance \u3054\u3068\u306B\u521D\u56DE\u306E\u307F\u3001\u4EE5\u964D\u306F warn\uFF09:",
|
|
457
|
+
cacheError
|
|
458
|
+
);
|
|
459
|
+
} else {
|
|
460
|
+
logger.warn("Cache write failed (result still returned):", cacheError);
|
|
461
|
+
}
|
|
441
462
|
}
|
|
442
463
|
}
|
|
443
|
-
return { data: userinfo };
|
|
464
|
+
return verificationCacheDegraded ? { data: userinfo, meta: { verificationCacheDegraded: true } } : { data: userinfo };
|
|
444
465
|
}
|
|
445
466
|
async function buildCacheKey(token, suffix) {
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
467
|
+
if (typeof globalThis.crypto?.subtle?.digest !== "function") {
|
|
468
|
+
if (!missingSubtleCryptoLogged) {
|
|
469
|
+
missingSubtleCryptoLogged = true;
|
|
470
|
+
logger.error(
|
|
471
|
+
"crypto.subtle \u304C\u5229\u7528\u3067\u304D\u306A\u3044\u305F\u3081 introspect \u7D50\u679C\u306E\u30AD\u30E3\u30C3\u30B7\u30E5\u3092\u7121\u52B9\u5316\u3057\u307E\u3057\u305F\uFF08\u30CF\u30C3\u30B7\u30E5\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u30C8\u30FC\u30AF\u30F3\u3092 cache key \u306B\u4F7F\u308F\u306A\u3044\u305F\u3081\u306E\u63AA\u7F6E #4119\uFF09\u3002\u5168 verification \u304C API \u547C\u3073\u51FA\u3057\u306B\u306A\u308A\u307E\u3059"
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
const encoder = new TextEncoder();
|
|
477
|
+
const data = encoder.encode(token);
|
|
478
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
479
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
480
|
+
const hashHex = hashArray.map((b) => b.toString(HEX_BASE).padStart(HEX_BYTE_WIDTH, "0")).join("");
|
|
481
|
+
const key = CACHE_KEY_PREFIX + hashHex;
|
|
461
482
|
return suffix ? `${key}:${suffix}` : key;
|
|
462
483
|
}
|
|
463
484
|
return verifyAccessToken;
|
|
@@ -1206,7 +1227,7 @@ function createNonContractMethods(deps) {
|
|
|
1206
1227
|
}
|
|
1207
1228
|
|
|
1208
1229
|
// src/client/version-check.ts
|
|
1209
|
-
var SDK_VERSION = "5.
|
|
1230
|
+
var SDK_VERSION = "5.21.0";
|
|
1210
1231
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
1211
1232
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
1212
1233
|
function sdkHeaders() {
|
|
@@ -1448,33 +1469,48 @@ function createOAuthTokenMethods(deps) {
|
|
|
1448
1469
|
async function signOutToken() {
|
|
1449
1470
|
const tokens = tokenStore.getTokens();
|
|
1450
1471
|
tokenStore.clearTokens();
|
|
1472
|
+
const allRevoked = {
|
|
1473
|
+
revoked: true,
|
|
1474
|
+
accessTokenRevoked: true,
|
|
1475
|
+
refreshTokenRevoked: true
|
|
1476
|
+
};
|
|
1451
1477
|
if (!tokens) {
|
|
1452
1478
|
logger.debug("No tokens to revoke");
|
|
1453
|
-
return { data:
|
|
1479
|
+
return { data: allRevoked };
|
|
1454
1480
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
);
|
|
1481
|
+
async function revokeOAuthToken(token, tokenTypeHint) {
|
|
1482
|
+
const url = `${baseUrl}${OAUTH_REVOKE_ENDPOINT}`;
|
|
1483
|
+
try {
|
|
1484
|
+
const response = await fetch(url, {
|
|
1485
|
+
method: "POST",
|
|
1486
|
+
credentials: "omit",
|
|
1487
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded", ...sdkHeaders() },
|
|
1488
|
+
body: new URLSearchParams({
|
|
1489
|
+
token,
|
|
1490
|
+
client_id: clientId,
|
|
1491
|
+
token_type_hint: tokenTypeHint
|
|
1492
|
+
}).toString()
|
|
1493
|
+
});
|
|
1494
|
+
return response.ok;
|
|
1495
|
+
} catch {
|
|
1496
|
+
return false;
|
|
1472
1497
|
}
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1498
|
+
}
|
|
1499
|
+
logger.debug("Revoking tokens:", `${baseUrl}${OAUTH_REVOKE_ENDPOINT}`);
|
|
1500
|
+
const accessTokenRevoked = await revokeOAuthToken(tokens.accessToken, "access_token");
|
|
1501
|
+
if (!accessTokenRevoked) {
|
|
1502
|
+
logger.warn("\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306E\u7121\u52B9\u5316\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u30B5\u30FC\u30D0\u30FC\u3067\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
1503
|
+
}
|
|
1504
|
+
const refreshTokenRevoked = tokens.refreshToken ? await revokeOAuthToken(tokens.refreshToken, "refresh_token") : true;
|
|
1505
|
+
if (tokens.refreshToken && !refreshTokenRevoked) {
|
|
1506
|
+
logger.warn("\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306E\u7121\u52B9\u5316\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u30B5\u30FC\u30D0\u30FC\u3067\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
1507
|
+
}
|
|
1508
|
+
const revoked = accessTokenRevoked && refreshTokenRevoked;
|
|
1509
|
+
if (!revoked) {
|
|
1510
|
+
logger.warn("\u30C8\u30FC\u30AF\u30F3\u7121\u52B9\u5316\u304C\u4E00\u90E8\u307E\u305F\u306F\u5168\u90E8\u5931\u6557\u3057\u307E\u3057\u305F\uFF08\u30ED\u30FC\u30AB\u30EB\u30C8\u30FC\u30AF\u30F3\u306F\u30AF\u30EA\u30A2\u6E08\u307F\uFF09");
|
|
1475
1511
|
}
|
|
1476
1512
|
logger.debug("Token sign-out completed");
|
|
1477
|
-
return { data:
|
|
1513
|
+
return { data: { revoked, accessTokenRevoked, refreshTokenRevoked } };
|
|
1478
1514
|
}
|
|
1479
1515
|
return { exchangeCodeForTokens, refreshAccessToken, signOutToken };
|
|
1480
1516
|
}
|
|
@@ -1638,7 +1674,7 @@ function createSessionMethods(deps) {
|
|
|
1638
1674
|
}
|
|
1639
1675
|
if (response.status === NO_CONTENT_STATUS) {
|
|
1640
1676
|
logger.debug("Response: 204 No Content");
|
|
1641
|
-
return { data:
|
|
1677
|
+
return { data: { revoked: true } };
|
|
1642
1678
|
}
|
|
1643
1679
|
if (!response.ok) {
|
|
1644
1680
|
try {
|
|
@@ -1665,7 +1701,7 @@ function createSessionMethods(deps) {
|
|
|
1665
1701
|
}
|
|
1666
1702
|
}
|
|
1667
1703
|
logger.debug("Response:", response.status);
|
|
1668
|
-
return { data:
|
|
1704
|
+
return { data: { revoked: true } };
|
|
1669
1705
|
}
|
|
1670
1706
|
return { getSession, signOutCookie };
|
|
1671
1707
|
}
|
|
@@ -1883,6 +1919,9 @@ var REDIRECT_LOOP_WINDOW_MS = 6e4;
|
|
|
1883
1919
|
var REDIRECT_LOOP_THRESHOLD = 3;
|
|
1884
1920
|
var storageReadFailureLogged = false;
|
|
1885
1921
|
var storageWriteFailureLogged = false;
|
|
1922
|
+
function isLoopDetectionDegraded() {
|
|
1923
|
+
return storageReadFailureLogged || storageWriteFailureLogged;
|
|
1924
|
+
}
|
|
1886
1925
|
function logStorageReadFailure(logger, err) {
|
|
1887
1926
|
if (storageReadFailureLogged) return;
|
|
1888
1927
|
storageReadFailureLogged = true;
|
|
@@ -2027,9 +2066,16 @@ function createRedirectMethods(deps) {
|
|
|
2027
2066
|
}
|
|
2028
2067
|
const state = generateRandomState();
|
|
2029
2068
|
if (!storeState(state, logger)) {
|
|
2069
|
+
cleanupVerifierStorage(logger);
|
|
2070
|
+
cleanupStateStorage(logger);
|
|
2030
2071
|
logger.error(
|
|
2031
|
-
"redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\
|
|
2072
|
+
"redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u8A8D\u53EF\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
|
|
2032
2073
|
);
|
|
2074
|
+
return {
|
|
2075
|
+
success: false,
|
|
2076
|
+
code: "state_persistence_failed",
|
|
2077
|
+
error: "OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u8A8D\u53EF\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
|
|
2078
|
+
};
|
|
2033
2079
|
}
|
|
2034
2080
|
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
2035
2081
|
const params = new URLSearchParams({
|
|
@@ -2064,7 +2110,7 @@ function createRedirectMethods(deps) {
|
|
|
2064
2110
|
rollbackLastRedirectAttempt(authorizeKey, logger);
|
|
2065
2111
|
throw err;
|
|
2066
2112
|
}
|
|
2067
|
-
return { success: true };
|
|
2113
|
+
return isLoopDetectionDegraded() ? { success: true, loopDetectionDisabled: true } : { success: true };
|
|
2068
2114
|
}
|
|
2069
2115
|
async function redirectToLogin(options) {
|
|
2070
2116
|
if (typeof window === "undefined") {
|
|
@@ -4331,7 +4377,8 @@ var quietLogger = {
|
|
|
4331
4377
|
},
|
|
4332
4378
|
warn: () => {
|
|
4333
4379
|
},
|
|
4334
|
-
error: (
|
|
4380
|
+
error: () => {
|
|
4381
|
+
}
|
|
4335
4382
|
};
|
|
4336
4383
|
var consoleLogger2 = {
|
|
4337
4384
|
debug: (...args) => console.debug(SDK_LOG_PREFIX2, ...args),
|
|
@@ -264,10 +264,12 @@ var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
|
|
|
264
264
|
var CACHE_KEY_PREFIX = "ffid:introspect:";
|
|
265
265
|
var HEX_BASE = 16;
|
|
266
266
|
var HEX_BYTE_WIDTH = 2;
|
|
267
|
-
var TOKEN_LOG_PREFIX_LENGTH = 8;
|
|
268
267
|
function createVerifyAccessToken(deps) {
|
|
269
268
|
const { authMode, baseUrl, serviceCode, serviceApiKey, verifyStrategy, logger, createError, errorCodes, cache, timeout } = deps;
|
|
270
269
|
let jwtVerify2 = null;
|
|
270
|
+
let cacheReadFailureEscalated = false;
|
|
271
|
+
let cacheWriteFailureEscalated = false;
|
|
272
|
+
let missingSubtleCryptoLogged = false;
|
|
271
273
|
function getJwtVerifier() {
|
|
272
274
|
if (!jwtVerify2) {
|
|
273
275
|
jwtVerify2 = createJwtVerifier({
|
|
@@ -327,8 +329,9 @@ function createVerifyAccessToken(deps) {
|
|
|
327
329
|
}
|
|
328
330
|
const url = `${baseUrl}${OAUTH_INTROSPECT_ENDPOINT}`;
|
|
329
331
|
logger.debug("Verifying access token:", url);
|
|
330
|
-
const cacheKey = cache ? await buildCacheKey(accessToken, cacheKeySuffix) :
|
|
331
|
-
|
|
332
|
+
const cacheKey = cache ? await buildCacheKey(accessToken, cacheKeySuffix) : null;
|
|
333
|
+
let verificationCacheDegraded = cache !== void 0 && cacheKey === null;
|
|
334
|
+
if (cache && cacheKey !== null) {
|
|
332
335
|
try {
|
|
333
336
|
const cached = await cache.adapter.get(cacheKey);
|
|
334
337
|
if (cached && typeof cached === "object" && "sub" in cached) {
|
|
@@ -336,7 +339,16 @@ function createVerifyAccessToken(deps) {
|
|
|
336
339
|
return { data: cached };
|
|
337
340
|
}
|
|
338
341
|
} catch (cacheError) {
|
|
339
|
-
|
|
342
|
+
verificationCacheDegraded = true;
|
|
343
|
+
if (!cacheReadFailureEscalated) {
|
|
344
|
+
cacheReadFailureEscalated = true;
|
|
345
|
+
logger.error(
|
|
346
|
+
"Cache read failed \u2014 falling back to API call. Redis \u7B49\u306E cache adapter \u969C\u5BB3\u6642\u306F\u5168 verification \u304C introspect \u306B degrade \u3057\u307E\u3059\uFF08\u3053\u306E error \u306F instance \u3054\u3068\u306B\u521D\u56DE\u306E\u307F\u3001\u4EE5\u964D\u306F warn\uFF09:",
|
|
347
|
+
cacheError
|
|
348
|
+
);
|
|
349
|
+
} else {
|
|
350
|
+
logger.warn("Cache read failed, falling back to API call:", cacheError);
|
|
351
|
+
}
|
|
340
352
|
}
|
|
341
353
|
}
|
|
342
354
|
const fetchOptions = {
|
|
@@ -431,31 +443,40 @@ function createVerifyAccessToken(deps) {
|
|
|
431
443
|
}
|
|
432
444
|
} : base;
|
|
433
445
|
const userinfo = normalizeUserinfo(raw);
|
|
434
|
-
if (cache) {
|
|
446
|
+
if (cache && cacheKey !== null) {
|
|
435
447
|
try {
|
|
436
448
|
await cache.adapter.set(cacheKey, userinfo, cache.ttl);
|
|
437
449
|
} catch (cacheError) {
|
|
438
|
-
|
|
450
|
+
verificationCacheDegraded = true;
|
|
451
|
+
if (!cacheWriteFailureEscalated) {
|
|
452
|
+
cacheWriteFailureEscalated = true;
|
|
453
|
+
logger.error(
|
|
454
|
+
"Cache write failed \u2014 result still returned. cache adapter \u969C\u5BB3\u6642\u306F introspect \u7D50\u679C\u304C\u30AD\u30E3\u30C3\u30B7\u30E5\u3055\u308C\u305A\u5168 verification \u304C API \u547C\u3073\u51FA\u3057\u306B degrade \u3057\u307E\u3059\uFF08\u3053\u306E error \u306F instance \u3054\u3068\u306B\u521D\u56DE\u306E\u307F\u3001\u4EE5\u964D\u306F warn\uFF09:",
|
|
455
|
+
cacheError
|
|
456
|
+
);
|
|
457
|
+
} else {
|
|
458
|
+
logger.warn("Cache write failed (result still returned):", cacheError);
|
|
459
|
+
}
|
|
439
460
|
}
|
|
440
461
|
}
|
|
441
|
-
return { data: userinfo };
|
|
462
|
+
return verificationCacheDegraded ? { data: userinfo, meta: { verificationCacheDegraded: true } } : { data: userinfo };
|
|
442
463
|
}
|
|
443
464
|
async function buildCacheKey(token, suffix) {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
465
|
+
if (typeof globalThis.crypto?.subtle?.digest !== "function") {
|
|
466
|
+
if (!missingSubtleCryptoLogged) {
|
|
467
|
+
missingSubtleCryptoLogged = true;
|
|
468
|
+
logger.error(
|
|
469
|
+
"crypto.subtle \u304C\u5229\u7528\u3067\u304D\u306A\u3044\u305F\u3081 introspect \u7D50\u679C\u306E\u30AD\u30E3\u30C3\u30B7\u30E5\u3092\u7121\u52B9\u5316\u3057\u307E\u3057\u305F\uFF08\u30CF\u30C3\u30B7\u30E5\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u30C8\u30FC\u30AF\u30F3\u3092 cache key \u306B\u4F7F\u308F\u306A\u3044\u305F\u3081\u306E\u63AA\u7F6E #4119\uFF09\u3002\u5168 verification \u304C API \u547C\u3073\u51FA\u3057\u306B\u306A\u308A\u307E\u3059"
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
const encoder = new TextEncoder();
|
|
475
|
+
const data = encoder.encode(token);
|
|
476
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
477
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
478
|
+
const hashHex = hashArray.map((b) => b.toString(HEX_BASE).padStart(HEX_BYTE_WIDTH, "0")).join("");
|
|
479
|
+
const key = CACHE_KEY_PREFIX + hashHex;
|
|
459
480
|
return suffix ? `${key}:${suffix}` : key;
|
|
460
481
|
}
|
|
461
482
|
return verifyAccessToken;
|
|
@@ -1204,7 +1225,7 @@ function createNonContractMethods(deps) {
|
|
|
1204
1225
|
}
|
|
1205
1226
|
|
|
1206
1227
|
// src/client/version-check.ts
|
|
1207
|
-
var SDK_VERSION = "5.
|
|
1228
|
+
var SDK_VERSION = "5.21.0";
|
|
1208
1229
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
1209
1230
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
1210
1231
|
function sdkHeaders() {
|
|
@@ -1446,33 +1467,48 @@ function createOAuthTokenMethods(deps) {
|
|
|
1446
1467
|
async function signOutToken() {
|
|
1447
1468
|
const tokens = tokenStore.getTokens();
|
|
1448
1469
|
tokenStore.clearTokens();
|
|
1470
|
+
const allRevoked = {
|
|
1471
|
+
revoked: true,
|
|
1472
|
+
accessTokenRevoked: true,
|
|
1473
|
+
refreshTokenRevoked: true
|
|
1474
|
+
};
|
|
1449
1475
|
if (!tokens) {
|
|
1450
1476
|
logger.debug("No tokens to revoke");
|
|
1451
|
-
return { data:
|
|
1477
|
+
return { data: allRevoked };
|
|
1452
1478
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
);
|
|
1479
|
+
async function revokeOAuthToken(token, tokenTypeHint) {
|
|
1480
|
+
const url = `${baseUrl}${OAUTH_REVOKE_ENDPOINT}`;
|
|
1481
|
+
try {
|
|
1482
|
+
const response = await fetch(url, {
|
|
1483
|
+
method: "POST",
|
|
1484
|
+
credentials: "omit",
|
|
1485
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded", ...sdkHeaders() },
|
|
1486
|
+
body: new URLSearchParams({
|
|
1487
|
+
token,
|
|
1488
|
+
client_id: clientId,
|
|
1489
|
+
token_type_hint: tokenTypeHint
|
|
1490
|
+
}).toString()
|
|
1491
|
+
});
|
|
1492
|
+
return response.ok;
|
|
1493
|
+
} catch {
|
|
1494
|
+
return false;
|
|
1470
1495
|
}
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1496
|
+
}
|
|
1497
|
+
logger.debug("Revoking tokens:", `${baseUrl}${OAUTH_REVOKE_ENDPOINT}`);
|
|
1498
|
+
const accessTokenRevoked = await revokeOAuthToken(tokens.accessToken, "access_token");
|
|
1499
|
+
if (!accessTokenRevoked) {
|
|
1500
|
+
logger.warn("\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306E\u7121\u52B9\u5316\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u30B5\u30FC\u30D0\u30FC\u3067\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
1501
|
+
}
|
|
1502
|
+
const refreshTokenRevoked = tokens.refreshToken ? await revokeOAuthToken(tokens.refreshToken, "refresh_token") : true;
|
|
1503
|
+
if (tokens.refreshToken && !refreshTokenRevoked) {
|
|
1504
|
+
logger.warn("\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306E\u7121\u52B9\u5316\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u30B5\u30FC\u30D0\u30FC\u3067\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
1505
|
+
}
|
|
1506
|
+
const revoked = accessTokenRevoked && refreshTokenRevoked;
|
|
1507
|
+
if (!revoked) {
|
|
1508
|
+
logger.warn("\u30C8\u30FC\u30AF\u30F3\u7121\u52B9\u5316\u304C\u4E00\u90E8\u307E\u305F\u306F\u5168\u90E8\u5931\u6557\u3057\u307E\u3057\u305F\uFF08\u30ED\u30FC\u30AB\u30EB\u30C8\u30FC\u30AF\u30F3\u306F\u30AF\u30EA\u30A2\u6E08\u307F\uFF09");
|
|
1473
1509
|
}
|
|
1474
1510
|
logger.debug("Token sign-out completed");
|
|
1475
|
-
return { data:
|
|
1511
|
+
return { data: { revoked, accessTokenRevoked, refreshTokenRevoked } };
|
|
1476
1512
|
}
|
|
1477
1513
|
return { exchangeCodeForTokens, refreshAccessToken, signOutToken };
|
|
1478
1514
|
}
|
|
@@ -1636,7 +1672,7 @@ function createSessionMethods(deps) {
|
|
|
1636
1672
|
}
|
|
1637
1673
|
if (response.status === NO_CONTENT_STATUS) {
|
|
1638
1674
|
logger.debug("Response: 204 No Content");
|
|
1639
|
-
return { data:
|
|
1675
|
+
return { data: { revoked: true } };
|
|
1640
1676
|
}
|
|
1641
1677
|
if (!response.ok) {
|
|
1642
1678
|
try {
|
|
@@ -1663,7 +1699,7 @@ function createSessionMethods(deps) {
|
|
|
1663
1699
|
}
|
|
1664
1700
|
}
|
|
1665
1701
|
logger.debug("Response:", response.status);
|
|
1666
|
-
return { data:
|
|
1702
|
+
return { data: { revoked: true } };
|
|
1667
1703
|
}
|
|
1668
1704
|
return { getSession, signOutCookie };
|
|
1669
1705
|
}
|
|
@@ -1881,6 +1917,9 @@ var REDIRECT_LOOP_WINDOW_MS = 6e4;
|
|
|
1881
1917
|
var REDIRECT_LOOP_THRESHOLD = 3;
|
|
1882
1918
|
var storageReadFailureLogged = false;
|
|
1883
1919
|
var storageWriteFailureLogged = false;
|
|
1920
|
+
function isLoopDetectionDegraded() {
|
|
1921
|
+
return storageReadFailureLogged || storageWriteFailureLogged;
|
|
1922
|
+
}
|
|
1884
1923
|
function logStorageReadFailure(logger, err) {
|
|
1885
1924
|
if (storageReadFailureLogged) return;
|
|
1886
1925
|
storageReadFailureLogged = true;
|
|
@@ -2025,9 +2064,16 @@ function createRedirectMethods(deps) {
|
|
|
2025
2064
|
}
|
|
2026
2065
|
const state = generateRandomState();
|
|
2027
2066
|
if (!storeState(state, logger)) {
|
|
2067
|
+
cleanupVerifierStorage(logger);
|
|
2068
|
+
cleanupStateStorage(logger);
|
|
2028
2069
|
logger.error(
|
|
2029
|
-
"redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\
|
|
2070
|
+
"redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u8A8D\u53EF\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
|
|
2030
2071
|
);
|
|
2072
|
+
return {
|
|
2073
|
+
success: false,
|
|
2074
|
+
code: "state_persistence_failed",
|
|
2075
|
+
error: "OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u8A8D\u53EF\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
|
|
2076
|
+
};
|
|
2031
2077
|
}
|
|
2032
2078
|
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
2033
2079
|
const params = new URLSearchParams({
|
|
@@ -2062,7 +2108,7 @@ function createRedirectMethods(deps) {
|
|
|
2062
2108
|
rollbackLastRedirectAttempt(authorizeKey, logger);
|
|
2063
2109
|
throw err;
|
|
2064
2110
|
}
|
|
2065
|
-
return { success: true };
|
|
2111
|
+
return isLoopDetectionDegraded() ? { success: true, loopDetectionDisabled: true } : { success: true };
|
|
2066
2112
|
}
|
|
2067
2113
|
async function redirectToLogin(options) {
|
|
2068
2114
|
if (typeof window === "undefined") {
|
|
@@ -4329,7 +4375,8 @@ var quietLogger = {
|
|
|
4329
4375
|
},
|
|
4330
4376
|
warn: () => {
|
|
4331
4377
|
},
|
|
4332
|
-
error: (
|
|
4378
|
+
error: () => {
|
|
4379
|
+
}
|
|
4333
4380
|
};
|
|
4334
4381
|
var consoleLogger2 = {
|
|
4335
4382
|
debug: (...args) => console.debug(SDK_LOG_PREFIX2, ...args),
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkRDQ4R3XC_cjs = require('../chunk-RDQ4R3XC.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, "FFIDAnnouncementBadge", {
|
|
8
8
|
enumerable: true,
|
|
9
|
-
get: function () { return
|
|
9
|
+
get: function () { return chunkRDQ4R3XC_cjs.FFIDAnnouncementBadge; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "FFIDAnnouncementList", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkRDQ4R3XC_cjs.FFIDAnnouncementList; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "FFIDInquiryForm", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkRDQ4R3XC_cjs.FFIDInquiryForm; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "FFIDLoginButton", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunkRDQ4R3XC_cjs.FFIDLoginButton; }
|
|
22
22
|
});
|
|
23
23
|
Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
|
|
24
24
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
25
|
+
get: function () { return chunkRDQ4R3XC_cjs.FFIDOrganizationSwitcher; }
|
|
26
26
|
});
|
|
27
27
|
Object.defineProperty(exports, "FFIDSubscriptionBadge", {
|
|
28
28
|
enumerable: true,
|
|
29
|
-
get: function () { return
|
|
29
|
+
get: function () { return chunkRDQ4R3XC_cjs.FFIDSubscriptionBadge; }
|
|
30
30
|
});
|
|
31
31
|
Object.defineProperty(exports, "FFIDUserMenu", {
|
|
32
32
|
enumerable: true,
|
|
33
|
-
get: function () { return
|
|
33
|
+
get: function () { return chunkRDQ4R3XC_cjs.FFIDUserMenu; }
|
|
34
34
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { H as FFIDAnnouncementBadge, ai as FFIDAnnouncementBadgeClassNames, aj as FFIDAnnouncementBadgeProps, I as FFIDAnnouncementList, ak as FFIDAnnouncementListClassNames, al as FFIDAnnouncementListProps, S as FFIDInquiryForm, T as FFIDInquiryFormCategoryItem, U as FFIDInquiryFormClassNames, V as FFIDInquiryFormLegalLayout, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a1 as FFIDLoginButton, am as FFIDLoginButtonProps, a4 as FFIDOrganizationSwitcher, an as FFIDOrganizationSwitcherClassNames, ao as FFIDOrganizationSwitcherProps, a9 as FFIDSubscriptionBadge, ap as FFIDSubscriptionBadgeClassNames, aq as FFIDSubscriptionBadgeProps, ab as FFIDUserMenu, ar as FFIDUserMenuClassNames, as as FFIDUserMenuProps } from '../index--wRiPlpi.cjs';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { H as FFIDAnnouncementBadge, ai as FFIDAnnouncementBadgeClassNames, aj as FFIDAnnouncementBadgeProps, I as FFIDAnnouncementList, ak as FFIDAnnouncementListClassNames, al as FFIDAnnouncementListProps, S as FFIDInquiryForm, T as FFIDInquiryFormCategoryItem, U as FFIDInquiryFormClassNames, V as FFIDInquiryFormLegalLayout, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a1 as FFIDLoginButton, am as FFIDLoginButtonProps, a4 as FFIDOrganizationSwitcher, an as FFIDOrganizationSwitcherClassNames, ao as FFIDOrganizationSwitcherProps, a9 as FFIDSubscriptionBadge, ap as FFIDSubscriptionBadgeClassNames, aq as FFIDSubscriptionBadgeProps, ab as FFIDUserMenu, ar as FFIDUserMenuClassNames, as as FFIDUserMenuProps } from '../index--wRiPlpi.js';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import 'react';
|
package/dist/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-
|
|
1
|
+
export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-U57ZDFEN.js';
|