@feelflow/ffid-sdk 1.11.0 → 1.14.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/{chunk-WZZP7SQB.cjs → chunk-TMUFELR5.cjs} +377 -30
- package/dist/{chunk-GW23IWNE.js → chunk-WJI7D5C7.js} +377 -30
- package/dist/components/index.cjs +7 -7
- 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/{index-DMgtXEt5.d.cts → index-DU-lFo9B.d.cts} +13 -1
- package/dist/{index-DMgtXEt5.d.ts → index-DU-lFo9B.d.ts} +13 -1
- package/dist/index.cjs +22 -22
- package/dist/index.d.cts +65 -7
- package/dist/index.d.ts +65 -7
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +374 -28
- package/dist/server/index.d.cts +64 -2
- package/dist/server/index.d.ts +64 -2
- package/dist/server/index.js +374 -28
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -432,7 +432,7 @@ function createBillingMethods(deps) {
|
|
|
432
432
|
}
|
|
433
433
|
|
|
434
434
|
// src/client/version-check.ts
|
|
435
|
-
var SDK_VERSION = "1.
|
|
435
|
+
var SDK_VERSION = "1.14.0";
|
|
436
436
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
437
437
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
438
438
|
function sdkHeaders() {
|
|
@@ -478,6 +478,22 @@ npm install @feelflow/ffid-sdk@latest \u3067\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8
|
|
|
478
478
|
var OAUTH_TOKEN_ENDPOINT = "/api/v1/oauth/token";
|
|
479
479
|
var OAUTH_REVOKE_ENDPOINT = "/api/v1/oauth/revoke";
|
|
480
480
|
var MS_PER_SECOND = 1e3;
|
|
481
|
+
function validateTokenResponse(tokenResponse) {
|
|
482
|
+
const invalid = [];
|
|
483
|
+
if (!tokenResponse.access_token) {
|
|
484
|
+
invalid.push("access_token");
|
|
485
|
+
}
|
|
486
|
+
if (!tokenResponse.refresh_token) {
|
|
487
|
+
invalid.push("refresh_token");
|
|
488
|
+
}
|
|
489
|
+
if (typeof tokenResponse.expires_in !== "number" || tokenResponse.expires_in <= 0) {
|
|
490
|
+
invalid.push("expires_in");
|
|
491
|
+
}
|
|
492
|
+
if (invalid.length > 0) {
|
|
493
|
+
return `\u30C8\u30FC\u30AF\u30F3\u30EC\u30B9\u30DD\u30F3\u30B9\u306B\u4E0D\u6B63\u306A\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u3042\u308A\u307E\u3059: ${invalid.join(", ")}`;
|
|
494
|
+
}
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
481
497
|
function createOAuthTokenMethods(deps) {
|
|
482
498
|
const {
|
|
483
499
|
baseUrl,
|
|
@@ -547,6 +563,16 @@ function createOAuthTokenMethods(deps) {
|
|
|
547
563
|
}
|
|
548
564
|
};
|
|
549
565
|
}
|
|
566
|
+
const validationError = validateTokenResponse(tokenResponse);
|
|
567
|
+
if (validationError) {
|
|
568
|
+
logger.error("Token exchange validation failed:", validationError);
|
|
569
|
+
return {
|
|
570
|
+
error: {
|
|
571
|
+
code: errorCodes.TOKEN_EXCHANGE_ERROR,
|
|
572
|
+
message: validationError
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
550
576
|
tokenStore.setTokens({
|
|
551
577
|
accessToken: tokenResponse.access_token,
|
|
552
578
|
refreshToken: tokenResponse.refresh_token,
|
|
@@ -615,6 +641,16 @@ function createOAuthTokenMethods(deps) {
|
|
|
615
641
|
}
|
|
616
642
|
};
|
|
617
643
|
}
|
|
644
|
+
const validationError = validateTokenResponse(tokenResponse);
|
|
645
|
+
if (validationError) {
|
|
646
|
+
logger.error("Token refresh validation failed:", validationError);
|
|
647
|
+
return {
|
|
648
|
+
error: {
|
|
649
|
+
code: errorCodes.TOKEN_REFRESH_ERROR,
|
|
650
|
+
message: validationError
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
}
|
|
618
654
|
tokenStore.setTokens({
|
|
619
655
|
accessToken: tokenResponse.access_token,
|
|
620
656
|
refreshToken: tokenResponse.refresh_token,
|
|
@@ -868,11 +904,17 @@ async function generateCodeChallenge(verifier) {
|
|
|
868
904
|
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
869
905
|
return base64UrlEncode(digest);
|
|
870
906
|
}
|
|
871
|
-
function storeCodeVerifier(verifier) {
|
|
907
|
+
function storeCodeVerifier(verifier, logger) {
|
|
872
908
|
try {
|
|
873
|
-
if (typeof window === "undefined")
|
|
909
|
+
if (typeof window === "undefined") {
|
|
910
|
+
logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
|
|
911
|
+
return false;
|
|
912
|
+
}
|
|
874
913
|
window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
|
|
875
|
-
|
|
914
|
+
return true;
|
|
915
|
+
} catch (error) {
|
|
916
|
+
logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
917
|
+
return false;
|
|
876
918
|
}
|
|
877
919
|
}
|
|
878
920
|
function base64UrlEncode(buffer) {
|
|
@@ -886,6 +928,7 @@ function base64UrlEncode(buffer) {
|
|
|
886
928
|
|
|
887
929
|
// src/client/redirect.ts
|
|
888
930
|
var OAUTH_AUTHORIZE_ENDPOINT = "/api/v1/oauth/authorize";
|
|
931
|
+
var AUTH_LOGOUT_ENDPOINT = "/api/v1/auth/logout";
|
|
889
932
|
var STATE_RANDOM_BYTES = 16;
|
|
890
933
|
var HEX_BASE2 = 16;
|
|
891
934
|
function generateRandomState() {
|
|
@@ -904,32 +947,34 @@ function createRedirectMethods(deps) {
|
|
|
904
947
|
} = deps;
|
|
905
948
|
async function redirectToAuthorize() {
|
|
906
949
|
const verifier = generateCodeVerifier();
|
|
907
|
-
storeCodeVerifier(verifier);
|
|
950
|
+
storeCodeVerifier(verifier, logger);
|
|
951
|
+
let challenge;
|
|
908
952
|
try {
|
|
909
|
-
|
|
910
|
-
const state = generateRandomState();
|
|
911
|
-
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
912
|
-
const params = new URLSearchParams({
|
|
913
|
-
response_type: "code",
|
|
914
|
-
client_id: clientId,
|
|
915
|
-
redirect_uri: redirectUri,
|
|
916
|
-
state,
|
|
917
|
-
code_challenge: challenge,
|
|
918
|
-
code_challenge_method: "S256"
|
|
919
|
-
});
|
|
920
|
-
const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
|
|
921
|
-
logger.debug("Redirecting to authorize:", authorizeUrl);
|
|
922
|
-
window.location.href = authorizeUrl;
|
|
923
|
-
return true;
|
|
953
|
+
challenge = await generateCodeChallenge(verifier);
|
|
924
954
|
} catch (error) {
|
|
955
|
+
const errorMessage = error instanceof Error ? error.message : "PKCE \u30B3\u30FC\u30C9\u30C1\u30E3\u30EC\u30F3\u30B8\u306E\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F";
|
|
925
956
|
logger.error("PKCE \u30B3\u30FC\u30C9\u30C1\u30E3\u30EC\u30F3\u30B8\u306E\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
926
|
-
return false;
|
|
957
|
+
return { success: false, error: errorMessage };
|
|
927
958
|
}
|
|
959
|
+
const state = generateRandomState();
|
|
960
|
+
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
961
|
+
const params = new URLSearchParams({
|
|
962
|
+
response_type: "code",
|
|
963
|
+
client_id: clientId,
|
|
964
|
+
redirect_uri: redirectUri,
|
|
965
|
+
state,
|
|
966
|
+
code_challenge: challenge,
|
|
967
|
+
code_challenge_method: "S256"
|
|
968
|
+
});
|
|
969
|
+
const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
|
|
970
|
+
logger.debug("Redirecting to authorize:", authorizeUrl);
|
|
971
|
+
window.location.href = authorizeUrl;
|
|
972
|
+
return { success: true };
|
|
928
973
|
}
|
|
929
974
|
async function redirectToLogin() {
|
|
930
975
|
if (typeof window === "undefined") {
|
|
931
|
-
logger.
|
|
932
|
-
return false;
|
|
976
|
+
logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
|
|
977
|
+
return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
|
|
933
978
|
}
|
|
934
979
|
if (authMode === "token") {
|
|
935
980
|
return redirectToAuthorize();
|
|
@@ -938,17 +983,289 @@ function createRedirectMethods(deps) {
|
|
|
938
983
|
const loginUrl = `${baseUrl}/login?redirect=${encodeURIComponent(currentUrl)}&service=${encodeURIComponent(serviceCode)}`;
|
|
939
984
|
logger.debug("Redirecting to login:", loginUrl);
|
|
940
985
|
window.location.href = loginUrl;
|
|
941
|
-
return true;
|
|
986
|
+
return { success: true };
|
|
942
987
|
}
|
|
943
988
|
function getLoginUrl(redirectUrl) {
|
|
944
|
-
|
|
989
|
+
let redirect;
|
|
990
|
+
if (redirectUrl != null) {
|
|
991
|
+
redirect = redirectUrl;
|
|
992
|
+
} else if (typeof window !== "undefined") {
|
|
993
|
+
redirect = window.location.href;
|
|
994
|
+
} else {
|
|
995
|
+
logger.warn("getLoginUrl: SSR \u74B0\u5883\u3067 redirectUrl \u304C\u672A\u6307\u5B9A\u306E\u305F\u3081\u7A7A\u6587\u5B57\u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3057\u307E\u3059");
|
|
996
|
+
redirect = "";
|
|
997
|
+
}
|
|
945
998
|
return `${baseUrl}/login?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
|
|
946
999
|
}
|
|
947
1000
|
function getSignupUrl(redirectUrl) {
|
|
948
|
-
|
|
1001
|
+
let redirect;
|
|
1002
|
+
if (redirectUrl != null) {
|
|
1003
|
+
redirect = redirectUrl;
|
|
1004
|
+
} else if (typeof window !== "undefined") {
|
|
1005
|
+
redirect = window.location.href;
|
|
1006
|
+
} else {
|
|
1007
|
+
logger.warn("getSignupUrl: SSR \u74B0\u5883\u3067 redirectUrl \u304C\u672A\u6307\u5B9A\u306E\u305F\u3081\u7A7A\u6587\u5B57\u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3057\u307E\u3059");
|
|
1008
|
+
redirect = "";
|
|
1009
|
+
}
|
|
949
1010
|
return `${baseUrl}/signup?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
|
|
950
1011
|
}
|
|
951
|
-
|
|
1012
|
+
function getLogoutUrl(postLogoutRedirectUri) {
|
|
1013
|
+
const url = new URL(`${baseUrl}${AUTH_LOGOUT_ENDPOINT}`);
|
|
1014
|
+
url.searchParams.set("client_id", clientId);
|
|
1015
|
+
if (postLogoutRedirectUri != null) {
|
|
1016
|
+
url.searchParams.set("post_logout_redirect_uri", postLogoutRedirectUri);
|
|
1017
|
+
}
|
|
1018
|
+
return url.toString();
|
|
1019
|
+
}
|
|
1020
|
+
function redirectToLogout(postLogoutRedirectUri) {
|
|
1021
|
+
if (typeof window === "undefined") {
|
|
1022
|
+
logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
|
|
1023
|
+
return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
|
|
1024
|
+
}
|
|
1025
|
+
const logoutUrl = getLogoutUrl(postLogoutRedirectUri);
|
|
1026
|
+
logger.debug("Redirecting to logout:", logoutUrl);
|
|
1027
|
+
window.location.href = logoutUrl;
|
|
1028
|
+
return { success: true };
|
|
1029
|
+
}
|
|
1030
|
+
return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout };
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// src/client/password-reset.ts
|
|
1034
|
+
var RESET_PASSWORD_BASE = "/api/v1/auth/reset-password";
|
|
1035
|
+
function isBlank(value) {
|
|
1036
|
+
return !value || !value.trim();
|
|
1037
|
+
}
|
|
1038
|
+
function createPasswordResetMethods(deps) {
|
|
1039
|
+
const { baseUrl, logger, createError, fetchWithAuth, errorCodes } = deps;
|
|
1040
|
+
async function fetchPublic(endpoint, options = {}) {
|
|
1041
|
+
const url = `${baseUrl}${endpoint}`;
|
|
1042
|
+
logger.debug("Fetching (public):", url);
|
|
1043
|
+
let response;
|
|
1044
|
+
try {
|
|
1045
|
+
response = await fetch(url, {
|
|
1046
|
+
...options,
|
|
1047
|
+
credentials: "include",
|
|
1048
|
+
headers: {
|
|
1049
|
+
"Content-Type": "application/json",
|
|
1050
|
+
...sdkHeaders(),
|
|
1051
|
+
...options.headers
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
} catch (error) {
|
|
1055
|
+
logger.error("Network error:", error);
|
|
1056
|
+
return {
|
|
1057
|
+
error: {
|
|
1058
|
+
code: errorCodes.NETWORK_ERROR,
|
|
1059
|
+
message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
let raw;
|
|
1064
|
+
try {
|
|
1065
|
+
raw = await response.json();
|
|
1066
|
+
} catch (parseError) {
|
|
1067
|
+
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
1068
|
+
return {
|
|
1069
|
+
error: {
|
|
1070
|
+
code: errorCodes.PARSE_ERROR,
|
|
1071
|
+
message: `\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u4E0D\u6B63\u306A\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F (status: ${response.status})`
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
logger.debug("Response (public):", response.status, raw);
|
|
1076
|
+
checkVersionHeader(response, logger);
|
|
1077
|
+
if (!response.ok) {
|
|
1078
|
+
return {
|
|
1079
|
+
error: raw.error ?? {
|
|
1080
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1081
|
+
message: "\u30D1\u30B9\u30EF\u30FC\u30C9\u30EA\u30BB\u30C3\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
if (raw.data === void 0) {
|
|
1086
|
+
return {
|
|
1087
|
+
error: {
|
|
1088
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1089
|
+
message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
return { data: raw.data };
|
|
1094
|
+
}
|
|
1095
|
+
async function requestPasswordReset(email) {
|
|
1096
|
+
if (isBlank(email)) {
|
|
1097
|
+
return {
|
|
1098
|
+
error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
return fetchPublic(
|
|
1102
|
+
RESET_PASSWORD_BASE,
|
|
1103
|
+
{
|
|
1104
|
+
method: "POST",
|
|
1105
|
+
body: JSON.stringify({ email })
|
|
1106
|
+
}
|
|
1107
|
+
);
|
|
1108
|
+
}
|
|
1109
|
+
async function verifyPasswordResetToken(accessToken) {
|
|
1110
|
+
if (isBlank(accessToken)) {
|
|
1111
|
+
return {
|
|
1112
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
const query = new URLSearchParams({
|
|
1116
|
+
access_token: accessToken,
|
|
1117
|
+
type: "recovery"
|
|
1118
|
+
});
|
|
1119
|
+
return fetchPublic(
|
|
1120
|
+
`${RESET_PASSWORD_BASE}/verify?${query.toString()}`
|
|
1121
|
+
);
|
|
1122
|
+
}
|
|
1123
|
+
async function establishResetSession(accessToken, refreshToken) {
|
|
1124
|
+
if (isBlank(accessToken)) {
|
|
1125
|
+
return {
|
|
1126
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
if (isBlank(refreshToken)) {
|
|
1130
|
+
return {
|
|
1131
|
+
error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
return fetchPublic(
|
|
1135
|
+
`${RESET_PASSWORD_BASE}/session`,
|
|
1136
|
+
{
|
|
1137
|
+
method: "POST",
|
|
1138
|
+
body: JSON.stringify({ accessToken, refreshToken })
|
|
1139
|
+
}
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
async function confirmPasswordReset(password) {
|
|
1143
|
+
if (isBlank(password)) {
|
|
1144
|
+
return {
|
|
1145
|
+
error: createError("VALIDATION_ERROR", "\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
return fetchWithAuth(
|
|
1149
|
+
`${RESET_PASSWORD_BASE}/confirm`,
|
|
1150
|
+
{
|
|
1151
|
+
method: "POST",
|
|
1152
|
+
body: JSON.stringify({ password })
|
|
1153
|
+
}
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
return {
|
|
1157
|
+
requestPasswordReset,
|
|
1158
|
+
verifyPasswordResetToken,
|
|
1159
|
+
establishResetSession,
|
|
1160
|
+
confirmPasswordReset
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// src/client/otp.ts
|
|
1165
|
+
var OTP_BASE = "/api/v1/auth/otp";
|
|
1166
|
+
function isBlank2(value) {
|
|
1167
|
+
return !value || !value.trim();
|
|
1168
|
+
}
|
|
1169
|
+
function createOtpMethods(deps) {
|
|
1170
|
+
const { baseUrl, logger, createError, errorCodes } = deps;
|
|
1171
|
+
async function fetchPublic(endpoint, options = {}) {
|
|
1172
|
+
const url = `${baseUrl}${endpoint}`;
|
|
1173
|
+
logger.debug("Fetching (public):", url);
|
|
1174
|
+
let response;
|
|
1175
|
+
try {
|
|
1176
|
+
response = await fetch(url, {
|
|
1177
|
+
...options,
|
|
1178
|
+
credentials: "include",
|
|
1179
|
+
headers: {
|
|
1180
|
+
"Content-Type": "application/json",
|
|
1181
|
+
...sdkHeaders(),
|
|
1182
|
+
...options.headers
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
} catch (error) {
|
|
1186
|
+
logger.error("Network error:", error);
|
|
1187
|
+
return {
|
|
1188
|
+
error: {
|
|
1189
|
+
code: errorCodes.NETWORK_ERROR,
|
|
1190
|
+
message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
let raw;
|
|
1195
|
+
try {
|
|
1196
|
+
raw = await response.json();
|
|
1197
|
+
} catch (parseError) {
|
|
1198
|
+
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
1199
|
+
return {
|
|
1200
|
+
error: {
|
|
1201
|
+
code: errorCodes.PARSE_ERROR,
|
|
1202
|
+
message: `\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u4E0D\u6B63\u306A\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F (status: ${response.status})`
|
|
1203
|
+
}
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
logger.debug("Response (public):", response.status, raw);
|
|
1207
|
+
checkVersionHeader(response, logger);
|
|
1208
|
+
if (!response.ok) {
|
|
1209
|
+
return {
|
|
1210
|
+
error: raw.error ?? {
|
|
1211
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1212
|
+
message: "OTP\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
if (raw.data === void 0) {
|
|
1217
|
+
return {
|
|
1218
|
+
error: {
|
|
1219
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1220
|
+
message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
return { data: raw.data };
|
|
1225
|
+
}
|
|
1226
|
+
async function sendOtp(email, options) {
|
|
1227
|
+
if (isBlank2(email)) {
|
|
1228
|
+
return {
|
|
1229
|
+
error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
return fetchPublic(
|
|
1233
|
+
`${OTP_BASE}/send`,
|
|
1234
|
+
{
|
|
1235
|
+
method: "POST",
|
|
1236
|
+
body: JSON.stringify({
|
|
1237
|
+
email,
|
|
1238
|
+
...options?.redirectUrl ? { redirectUrl: options.redirectUrl } : {}
|
|
1239
|
+
})
|
|
1240
|
+
}
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
async function verifyOtp(params) {
|
|
1244
|
+
if (isBlank2(params.accessToken)) {
|
|
1245
|
+
return {
|
|
1246
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
if (isBlank2(params.refreshToken)) {
|
|
1250
|
+
return {
|
|
1251
|
+
error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
return fetchPublic(
|
|
1255
|
+
`${OTP_BASE}/verify`,
|
|
1256
|
+
{
|
|
1257
|
+
method: "POST",
|
|
1258
|
+
body: JSON.stringify({
|
|
1259
|
+
accessToken: params.accessToken,
|
|
1260
|
+
refreshToken: params.refreshToken
|
|
1261
|
+
})
|
|
1262
|
+
}
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
return {
|
|
1266
|
+
sendOtp,
|
|
1267
|
+
verifyOtp
|
|
1268
|
+
};
|
|
952
1269
|
}
|
|
953
1270
|
|
|
954
1271
|
// src/client/ffid-client.ts
|
|
@@ -1083,6 +1400,9 @@ function createFFIDClient(config) {
|
|
|
1083
1400
|
}
|
|
1084
1401
|
};
|
|
1085
1402
|
}
|
|
1403
|
+
} else {
|
|
1404
|
+
logger.warn("Token refresh failed, returning refresh error:", refreshResult.error);
|
|
1405
|
+
return { error: refreshResult.error };
|
|
1086
1406
|
}
|
|
1087
1407
|
}
|
|
1088
1408
|
let raw;
|
|
@@ -1133,7 +1453,7 @@ function createFFIDClient(config) {
|
|
|
1133
1453
|
}
|
|
1134
1454
|
return signOutCookie();
|
|
1135
1455
|
}
|
|
1136
|
-
const { redirectToLogin, getLoginUrl, getSignupUrl } = createRedirectMethods({
|
|
1456
|
+
const { redirectToLogin, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
|
|
1137
1457
|
authMode,
|
|
1138
1458
|
baseUrl,
|
|
1139
1459
|
clientId,
|
|
@@ -1160,6 +1480,24 @@ function createFFIDClient(config) {
|
|
|
1160
1480
|
fetchWithAuth,
|
|
1161
1481
|
createError
|
|
1162
1482
|
});
|
|
1483
|
+
const {
|
|
1484
|
+
requestPasswordReset,
|
|
1485
|
+
verifyPasswordResetToken,
|
|
1486
|
+
establishResetSession,
|
|
1487
|
+
confirmPasswordReset
|
|
1488
|
+
} = createPasswordResetMethods({
|
|
1489
|
+
baseUrl,
|
|
1490
|
+
logger,
|
|
1491
|
+
createError,
|
|
1492
|
+
fetchWithAuth,
|
|
1493
|
+
errorCodes: FFID_ERROR_CODES
|
|
1494
|
+
});
|
|
1495
|
+
const { sendOtp, verifyOtp } = createOtpMethods({
|
|
1496
|
+
baseUrl,
|
|
1497
|
+
logger,
|
|
1498
|
+
createError,
|
|
1499
|
+
errorCodes: FFID_ERROR_CODES
|
|
1500
|
+
});
|
|
1163
1501
|
const verifyAccessToken = createVerifyAccessToken({
|
|
1164
1502
|
authMode,
|
|
1165
1503
|
baseUrl,
|
|
@@ -1176,7 +1514,9 @@ function createFFIDClient(config) {
|
|
|
1176
1514
|
getSession,
|
|
1177
1515
|
signOut,
|
|
1178
1516
|
redirectToLogin,
|
|
1517
|
+
redirectToLogout,
|
|
1179
1518
|
getLoginUrl,
|
|
1519
|
+
getLogoutUrl,
|
|
1180
1520
|
getSignupUrl,
|
|
1181
1521
|
createError,
|
|
1182
1522
|
exchangeCodeForTokens,
|
|
@@ -1185,6 +1525,12 @@ function createFFIDClient(config) {
|
|
|
1185
1525
|
createCheckoutSession,
|
|
1186
1526
|
createPortalSession,
|
|
1187
1527
|
verifyAccessToken,
|
|
1528
|
+
requestPasswordReset,
|
|
1529
|
+
verifyPasswordResetToken,
|
|
1530
|
+
establishResetSession,
|
|
1531
|
+
confirmPasswordReset,
|
|
1532
|
+
sendOtp,
|
|
1533
|
+
verifyOtp,
|
|
1188
1534
|
/** Token store (token mode only) */
|
|
1189
1535
|
tokenStore,
|
|
1190
1536
|
/** Resolved auth mode */
|