@feelflow/ffid-sdk 5.12.0 → 5.13.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-AOJDV3UO.cjs → chunk-JFFRO2Q5.cjs} +221 -9
- package/dist/{chunk-KB2JG64Z.js → chunk-RATTQIKM.js} +218 -10
- 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-5IprSUVR.d.ts → ffid-client-BG0Qr86U.d.ts} +59 -29
- package/dist/{ffid-client-Dx4oc4Cw.d.cts → ffid-client-C3K3sAqq.d.cts} +59 -29
- package/dist/{index-DqsWKU16.d.cts → index-C6dnexXf.d.cts} +13 -0
- package/dist/{index-DqsWKU16.d.ts → index-C6dnexXf.d.ts} +13 -0
- package/dist/index.cjs +53 -37
- package/dist/index.d.cts +98 -4
- package/dist/index.d.ts +98 -4
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +67 -3
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +67 -3
- package/dist/server/test/index.d.cts +1 -1
- package/dist/server/test/index.d.ts +1 -1
- package/dist/webhooks/index.cjs +5 -2
- package/dist/webhooks/index.js +5 -2
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-
|
|
2
|
-
export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, 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, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-
|
|
1
|
+
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-C6dnexXf.cjs';
|
|
2
|
+
export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, 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, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-C6dnexXf.cjs';
|
|
3
3
|
export { A as ALL_DENIED_EXCEPT_NECESSARY, i as CONSENT_COOKIE_NAME, j as CONSENT_DISMISSAL_TIMESTAMP_KEY, l as COOKIE_VERSION, D as DEFAULT_CONSENT_ERROR_MESSAGES, o as FFIDAnalyticsProvider, p as FFIDAnalyticsProviderProps, c as FFIDConsentCategories, r as FFIDConsentCategoryCode, e as FFIDConsentCategoryMetadata, w as FFIDConsentError, x as FFIDConsentErrorCode, y as FFIDConsentMergeStrategy, B as FFIDConsentMergeWarning, E as FFIDConsentMergeWarningEvent, F as FFIDConsentResult, I as FFIDConsentSource, a as FFIDConsentState, d as FFIDConsentSyncResult, M as FFIDCookieBanner, N as FFIDCookieBannerClassNames, O as FFIDCookieBannerProps, Q as FFIDCookieLink, R as FFIDCookieLinkProps, f as FFIDCookiePolicy, T as FFIDCookieSettings, U as FFIDCookieSettingsClassNames, V as FFIDCookieSettingsProps, _ as FFID_CONSENT_ERROR_CODES, ae as UseFFIDConsentPreferencesReturn, af as UseFFIDConsentReturn, ag as clearConsentDismissalTimestamp, aj as decodeConsentCookie, al as encodeConsentCookie, an as readConsentCookie, ao as readConsentDismissalTimestamp, aq as useFFIDConsent, ar as useFFIDConsentPreferences, as as writeConsentCookie, at as writeConsentDismissalTimestamp } from './FFIDCookieLink-D1WwE_ZO.cjs';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
import { ReactNode, ComponentType, FC } from 'react';
|
|
@@ -122,6 +122,35 @@ declare function storeCodeVerifier(verifier: string, logger?: PKCELogger): boole
|
|
|
122
122
|
*/
|
|
123
123
|
declare function retrieveCodeVerifier(logger?: PKCELogger): string | null;
|
|
124
124
|
|
|
125
|
+
/** Logger interface matching FFIDLogger for optional warning output */
|
|
126
|
+
interface StateLogger {
|
|
127
|
+
warn: (...args: unknown[]) => void;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Store the OAuth `state` for later retrieval.
|
|
131
|
+
*
|
|
132
|
+
* Writes to both sessionStorage (primary) and localStorage (fallback for iOS
|
|
133
|
+
* WebKit sessionStorage eviction during external OAuth bounces). Returns true
|
|
134
|
+
* if at least one write succeeded.
|
|
135
|
+
*
|
|
136
|
+
* @param state - The OAuth state value to store
|
|
137
|
+
* @param logger - Optional logger for warning on storage failure
|
|
138
|
+
* @returns true if stored in at least one storage, false otherwise
|
|
139
|
+
*/
|
|
140
|
+
declare function storeState(state: string, logger?: StateLogger): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Retrieve and remove the OAuth `state`.
|
|
143
|
+
*
|
|
144
|
+
* Reads from sessionStorage first, falls back to localStorage (with 5-minute TTL).
|
|
145
|
+
* Removes from all storages after retrieval (one-time use). Returns null if no
|
|
146
|
+
* state is stored, the fallback is stale (>5 min), or storage is unavailable.
|
|
147
|
+
*
|
|
148
|
+
* @param logger - Optional logger for warning on storage failure
|
|
149
|
+
*/
|
|
150
|
+
declare function retrieveState(logger?: StateLogger): string | null;
|
|
151
|
+
|
|
152
|
+
declare function cleanupStateStorage(logger?: StateLogger): void;
|
|
153
|
+
|
|
125
154
|
/**
|
|
126
155
|
* Billing checkout / portal session types.
|
|
127
156
|
*
|
|
@@ -716,6 +745,25 @@ interface ContractWizardSubscriptionOptions {
|
|
|
716
745
|
organizationId?: string;
|
|
717
746
|
}
|
|
718
747
|
|
|
748
|
+
/** OAuth token operations - exchangeCodeForTokens / refreshAccessToken / signOutToken */
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Optional OAuth `state` validation for {@link exchangeCodeForTokens}.
|
|
752
|
+
*
|
|
753
|
+
* If a `state` is supplied on EITHER side — `expectedState` (the value persisted
|
|
754
|
+
* at `redirectToAuthorize`) or `actualState` (the value returned on the callback
|
|
755
|
+
* URL) — both must be present and equal before any token exchange. A mismatch
|
|
756
|
+
* OR an omitted counterpart fails closed (no exchange) to defend against CSRF
|
|
757
|
+
* (RFC 6749 §10.12 / #3841). Validation is skipped only when BOTH are omitted
|
|
758
|
+
* (backward compatible — callers that don't opt in are unaffected).
|
|
759
|
+
*/
|
|
760
|
+
interface ExchangeCodeForTokensOptions {
|
|
761
|
+
/** Stored state from `redirectToAuthorize` (e.g. `retrieveState()`) */
|
|
762
|
+
expectedState?: string;
|
|
763
|
+
/** State returned on the OAuth callback URL */
|
|
764
|
+
actualState?: string;
|
|
765
|
+
}
|
|
766
|
+
|
|
719
767
|
/** Redirect and URL generation - redirectToLogin / redirectToAuthorize / redirectToLogout / getLoginUrl / getSignupUrl / getLogoutUrl */
|
|
720
768
|
|
|
721
769
|
/**
|
|
@@ -755,7 +803,7 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
755
803
|
getLogoutUrl: (postLogoutRedirectUri?: string) => string;
|
|
756
804
|
getSignupUrl: (redirectUrl?: string) => string;
|
|
757
805
|
createError: (code: string, message: string) => FFIDError;
|
|
758
|
-
exchangeCodeForTokens: (code: string, codeVerifier?: string) => Promise<FFIDApiResponse<void>>;
|
|
806
|
+
exchangeCodeForTokens: (code: string, codeVerifier?: string, opts?: ExchangeCodeForTokensOptions) => Promise<FFIDApiResponse<void>>;
|
|
759
807
|
refreshAccessToken: () => Promise<FFIDApiResponse<void>>;
|
|
760
808
|
checkSubscription: (params: {
|
|
761
809
|
userId?: string;
|
|
@@ -857,6 +905,52 @@ declare class FFIDSDKError extends Error {
|
|
|
857
905
|
constructor(code: string, message: string);
|
|
858
906
|
}
|
|
859
907
|
|
|
908
|
+
/**
|
|
909
|
+
* OAuth redirect callback handler
|
|
910
|
+
*
|
|
911
|
+
* `handleRedirectCallback` is the convenience counterpart to
|
|
912
|
+
* `redirectToAuthorize`: it reads `code` + `state` from the callback URL,
|
|
913
|
+
* validates the OAuth `state` against the value persisted at authorize time
|
|
914
|
+
* (CSRF protection, RFC 6749 §10.12), retrieves the PKCE verifier, exchanges
|
|
915
|
+
* the code for tokens, and cleans the params out of the URL on success.
|
|
916
|
+
*/
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Minimal client surface required by {@link handleRedirectCallback}.
|
|
920
|
+
* A full {@link FFIDClient} satisfies this structurally.
|
|
921
|
+
*/
|
|
922
|
+
type HandleRedirectCallbackClient = Pick<FFIDClient, 'exchangeCodeForTokens' | 'createError' | 'logger'>;
|
|
923
|
+
/** Options for {@link handleRedirectCallback} */
|
|
924
|
+
interface HandleRedirectCallbackOptions {
|
|
925
|
+
/**
|
|
926
|
+
* Callback URL (or query string) to read `code` / `state` from. Accepts an
|
|
927
|
+
* absolute URL, a relative URL, or a bare query string. Defaults to
|
|
928
|
+
* `window.location.search` in the browser.
|
|
929
|
+
*/
|
|
930
|
+
url?: string;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Complete an OAuth authorization-code redirect.
|
|
934
|
+
*
|
|
935
|
+
* Behavior:
|
|
936
|
+
* 1. Reads `code` + `state` from `options.url ?? window.location.search`.
|
|
937
|
+
* 2. CSRF guard: if a `state` exists on EITHER side (a stored state from
|
|
938
|
+
* authorize OR a `state` on the callback URL), the two MUST match — mismatch,
|
|
939
|
+
* a missing stored state, or an **omitted** callback `state` all **fail closed**
|
|
940
|
+
* (returns an error, performs no exchange). Validation is skipped ONLY when
|
|
941
|
+
* neither side has any state (a genuine no-state flow). Omitting the callback
|
|
942
|
+
* `state` does NOT bypass the check (#3841).
|
|
943
|
+
* 3. Retrieves the PKCE verifier and exchanges the code for tokens.
|
|
944
|
+
* 4. On success, removes `code` + `state` from the browser URL.
|
|
945
|
+
*
|
|
946
|
+
* SSR-safe: when there is no `window` and no `options.url`, no exchange is
|
|
947
|
+
* attempted and an error result is returned.
|
|
948
|
+
*
|
|
949
|
+
* @param client - FFID client (or any object exposing exchangeCodeForTokens / createError / logger)
|
|
950
|
+
* @param options - Optional callback URL override
|
|
951
|
+
*/
|
|
952
|
+
declare function handleRedirectCallback(client: HandleRedirectCallbackClient, options?: HandleRedirectCallbackOptions): Promise<FFIDApiResponse<void>>;
|
|
953
|
+
|
|
860
954
|
/**
|
|
861
955
|
* Redirect URI normalization (SDK copy)
|
|
862
956
|
*
|
|
@@ -1565,4 +1659,4 @@ declare function createInquiryMethods(deps: InquiryMethodsDeps): {
|
|
|
1565
1659
|
};
|
|
1566
1660
|
type FFIDInquiryClient = ReturnType<typeof createInquiryMethods>;
|
|
1567
1661
|
|
|
1568
|
-
export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
|
|
1662
|
+
export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type ExchangeCodeForTokensOptions, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type HandleRedirectCallbackClient, type HandleRedirectCallbackOptions, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, cleanupStateStorage as clearState, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, handleRedirectCallback, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, retrieveState, storeCodeVerifier, storeState, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-
|
|
2
|
-
export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, 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, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-
|
|
1
|
+
import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-C6dnexXf.js';
|
|
2
|
+
export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, 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, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-C6dnexXf.js';
|
|
3
3
|
export { A as ALL_DENIED_EXCEPT_NECESSARY, i as CONSENT_COOKIE_NAME, j as CONSENT_DISMISSAL_TIMESTAMP_KEY, l as COOKIE_VERSION, D as DEFAULT_CONSENT_ERROR_MESSAGES, o as FFIDAnalyticsProvider, p as FFIDAnalyticsProviderProps, c as FFIDConsentCategories, r as FFIDConsentCategoryCode, e as FFIDConsentCategoryMetadata, w as FFIDConsentError, x as FFIDConsentErrorCode, y as FFIDConsentMergeStrategy, B as FFIDConsentMergeWarning, E as FFIDConsentMergeWarningEvent, F as FFIDConsentResult, I as FFIDConsentSource, a as FFIDConsentState, d as FFIDConsentSyncResult, M as FFIDCookieBanner, N as FFIDCookieBannerClassNames, O as FFIDCookieBannerProps, Q as FFIDCookieLink, R as FFIDCookieLinkProps, f as FFIDCookiePolicy, T as FFIDCookieSettings, U as FFIDCookieSettingsClassNames, V as FFIDCookieSettingsProps, _ as FFID_CONSENT_ERROR_CODES, ae as UseFFIDConsentPreferencesReturn, af as UseFFIDConsentReturn, ag as clearConsentDismissalTimestamp, aj as decodeConsentCookie, al as encodeConsentCookie, an as readConsentCookie, ao as readConsentDismissalTimestamp, aq as useFFIDConsent, ar as useFFIDConsentPreferences, as as writeConsentCookie, at as writeConsentDismissalTimestamp } from './FFIDCookieLink-D1WwE_ZO.js';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
5
|
import { ReactNode, ComponentType, FC } from 'react';
|
|
@@ -122,6 +122,35 @@ declare function storeCodeVerifier(verifier: string, logger?: PKCELogger): boole
|
|
|
122
122
|
*/
|
|
123
123
|
declare function retrieveCodeVerifier(logger?: PKCELogger): string | null;
|
|
124
124
|
|
|
125
|
+
/** Logger interface matching FFIDLogger for optional warning output */
|
|
126
|
+
interface StateLogger {
|
|
127
|
+
warn: (...args: unknown[]) => void;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Store the OAuth `state` for later retrieval.
|
|
131
|
+
*
|
|
132
|
+
* Writes to both sessionStorage (primary) and localStorage (fallback for iOS
|
|
133
|
+
* WebKit sessionStorage eviction during external OAuth bounces). Returns true
|
|
134
|
+
* if at least one write succeeded.
|
|
135
|
+
*
|
|
136
|
+
* @param state - The OAuth state value to store
|
|
137
|
+
* @param logger - Optional logger for warning on storage failure
|
|
138
|
+
* @returns true if stored in at least one storage, false otherwise
|
|
139
|
+
*/
|
|
140
|
+
declare function storeState(state: string, logger?: StateLogger): boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Retrieve and remove the OAuth `state`.
|
|
143
|
+
*
|
|
144
|
+
* Reads from sessionStorage first, falls back to localStorage (with 5-minute TTL).
|
|
145
|
+
* Removes from all storages after retrieval (one-time use). Returns null if no
|
|
146
|
+
* state is stored, the fallback is stale (>5 min), or storage is unavailable.
|
|
147
|
+
*
|
|
148
|
+
* @param logger - Optional logger for warning on storage failure
|
|
149
|
+
*/
|
|
150
|
+
declare function retrieveState(logger?: StateLogger): string | null;
|
|
151
|
+
|
|
152
|
+
declare function cleanupStateStorage(logger?: StateLogger): void;
|
|
153
|
+
|
|
125
154
|
/**
|
|
126
155
|
* Billing checkout / portal session types.
|
|
127
156
|
*
|
|
@@ -716,6 +745,25 @@ interface ContractWizardSubscriptionOptions {
|
|
|
716
745
|
organizationId?: string;
|
|
717
746
|
}
|
|
718
747
|
|
|
748
|
+
/** OAuth token operations - exchangeCodeForTokens / refreshAccessToken / signOutToken */
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Optional OAuth `state` validation for {@link exchangeCodeForTokens}.
|
|
752
|
+
*
|
|
753
|
+
* If a `state` is supplied on EITHER side — `expectedState` (the value persisted
|
|
754
|
+
* at `redirectToAuthorize`) or `actualState` (the value returned on the callback
|
|
755
|
+
* URL) — both must be present and equal before any token exchange. A mismatch
|
|
756
|
+
* OR an omitted counterpart fails closed (no exchange) to defend against CSRF
|
|
757
|
+
* (RFC 6749 §10.12 / #3841). Validation is skipped only when BOTH are omitted
|
|
758
|
+
* (backward compatible — callers that don't opt in are unaffected).
|
|
759
|
+
*/
|
|
760
|
+
interface ExchangeCodeForTokensOptions {
|
|
761
|
+
/** Stored state from `redirectToAuthorize` (e.g. `retrieveState()`) */
|
|
762
|
+
expectedState?: string;
|
|
763
|
+
/** State returned on the OAuth callback URL */
|
|
764
|
+
actualState?: string;
|
|
765
|
+
}
|
|
766
|
+
|
|
719
767
|
/** Redirect and URL generation - redirectToLogin / redirectToAuthorize / redirectToLogout / getLoginUrl / getSignupUrl / getLogoutUrl */
|
|
720
768
|
|
|
721
769
|
/**
|
|
@@ -755,7 +803,7 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
755
803
|
getLogoutUrl: (postLogoutRedirectUri?: string) => string;
|
|
756
804
|
getSignupUrl: (redirectUrl?: string) => string;
|
|
757
805
|
createError: (code: string, message: string) => FFIDError;
|
|
758
|
-
exchangeCodeForTokens: (code: string, codeVerifier?: string) => Promise<FFIDApiResponse<void>>;
|
|
806
|
+
exchangeCodeForTokens: (code: string, codeVerifier?: string, opts?: ExchangeCodeForTokensOptions) => Promise<FFIDApiResponse<void>>;
|
|
759
807
|
refreshAccessToken: () => Promise<FFIDApiResponse<void>>;
|
|
760
808
|
checkSubscription: (params: {
|
|
761
809
|
userId?: string;
|
|
@@ -857,6 +905,52 @@ declare class FFIDSDKError extends Error {
|
|
|
857
905
|
constructor(code: string, message: string);
|
|
858
906
|
}
|
|
859
907
|
|
|
908
|
+
/**
|
|
909
|
+
* OAuth redirect callback handler
|
|
910
|
+
*
|
|
911
|
+
* `handleRedirectCallback` is the convenience counterpart to
|
|
912
|
+
* `redirectToAuthorize`: it reads `code` + `state` from the callback URL,
|
|
913
|
+
* validates the OAuth `state` against the value persisted at authorize time
|
|
914
|
+
* (CSRF protection, RFC 6749 §10.12), retrieves the PKCE verifier, exchanges
|
|
915
|
+
* the code for tokens, and cleans the params out of the URL on success.
|
|
916
|
+
*/
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Minimal client surface required by {@link handleRedirectCallback}.
|
|
920
|
+
* A full {@link FFIDClient} satisfies this structurally.
|
|
921
|
+
*/
|
|
922
|
+
type HandleRedirectCallbackClient = Pick<FFIDClient, 'exchangeCodeForTokens' | 'createError' | 'logger'>;
|
|
923
|
+
/** Options for {@link handleRedirectCallback} */
|
|
924
|
+
interface HandleRedirectCallbackOptions {
|
|
925
|
+
/**
|
|
926
|
+
* Callback URL (or query string) to read `code` / `state` from. Accepts an
|
|
927
|
+
* absolute URL, a relative URL, or a bare query string. Defaults to
|
|
928
|
+
* `window.location.search` in the browser.
|
|
929
|
+
*/
|
|
930
|
+
url?: string;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Complete an OAuth authorization-code redirect.
|
|
934
|
+
*
|
|
935
|
+
* Behavior:
|
|
936
|
+
* 1. Reads `code` + `state` from `options.url ?? window.location.search`.
|
|
937
|
+
* 2. CSRF guard: if a `state` exists on EITHER side (a stored state from
|
|
938
|
+
* authorize OR a `state` on the callback URL), the two MUST match — mismatch,
|
|
939
|
+
* a missing stored state, or an **omitted** callback `state` all **fail closed**
|
|
940
|
+
* (returns an error, performs no exchange). Validation is skipped ONLY when
|
|
941
|
+
* neither side has any state (a genuine no-state flow). Omitting the callback
|
|
942
|
+
* `state` does NOT bypass the check (#3841).
|
|
943
|
+
* 3. Retrieves the PKCE verifier and exchanges the code for tokens.
|
|
944
|
+
* 4. On success, removes `code` + `state` from the browser URL.
|
|
945
|
+
*
|
|
946
|
+
* SSR-safe: when there is no `window` and no `options.url`, no exchange is
|
|
947
|
+
* attempted and an error result is returned.
|
|
948
|
+
*
|
|
949
|
+
* @param client - FFID client (or any object exposing exchangeCodeForTokens / createError / logger)
|
|
950
|
+
* @param options - Optional callback URL override
|
|
951
|
+
*/
|
|
952
|
+
declare function handleRedirectCallback(client: HandleRedirectCallbackClient, options?: HandleRedirectCallbackOptions): Promise<FFIDApiResponse<void>>;
|
|
953
|
+
|
|
860
954
|
/**
|
|
861
955
|
* Redirect URI normalization (SDK copy)
|
|
862
956
|
*
|
|
@@ -1565,4 +1659,4 @@ declare function createInquiryMethods(deps: InquiryMethodsDeps): {
|
|
|
1565
1659
|
};
|
|
1566
1660
|
type FFIDInquiryClient = ReturnType<typeof createInquiryMethods>;
|
|
1567
1661
|
|
|
1568
|
-
export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
|
|
1662
|
+
export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type ExchangeCodeForTokensOptions, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type HandleRedirectCallbackClient, type HandleRedirectCallbackOptions, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, cleanupStateStorage as clearState, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, handleRedirectCallback, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, retrieveState, storeCodeVerifier, storeState, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useFFIDContext, useSubscription } from './chunk-
|
|
2
|
-
export { ACCESS_GRANTING_EFFECTIVE_STATUSES, BLOCKING_EFFECTIVE_STATUSES, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EFFECTIVE_SUBSCRIPTION_STATUSES, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, hasAccessFromUserinfo, isBlockedFromUserinfo, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-
|
|
1
|
+
import { useFFIDContext, useSubscription } from './chunk-RATTQIKM.js';
|
|
2
|
+
export { ACCESS_GRANTING_EFFECTIVE_STATUSES, BLOCKING_EFFECTIVE_STATUSES, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EFFECTIVE_SUBSCRIPTION_STATUSES, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, cleanupStateStorage as clearState, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, handleRedirectCallback, hasAccessFromUserinfo, isBlockedFromUserinfo, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, retrieveState, storeCodeVerifier, storeState, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-RATTQIKM.js';
|
|
3
3
|
export { ALL_DENIED_EXCEPT_NECESSARY, CONSENT_COOKIE_NAME, CONSENT_DISMISSAL_TIMESTAMP_KEY, COOKIE_VERSION, DEFAULT_CONSENT_ERROR_MESSAGES, FFIDAnalyticsProvider, FFIDConsentError, FFIDCookieBanner, FFIDCookieLink, FFIDCookieSettings, FFID_CONSENT_ERROR_CODES, clearConsentDismissalTimestamp, decodeConsentCookie, encodeConsentCookie, readConsentCookie, readConsentDismissalTimestamp, useFFIDConsent, useFFIDConsentPreferences, writeConsentCookie, writeConsentDismissalTimestamp } from './chunk-M4N2PUX6.js';
|
|
4
4
|
import { useEffect, useRef } from 'react';
|
|
5
5
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
package/dist/server/index.cjs
CHANGED
|
@@ -119,6 +119,9 @@ function normalizeUserinfo(raw) {
|
|
|
119
119
|
return {
|
|
120
120
|
sub: raw.sub,
|
|
121
121
|
email: raw.email,
|
|
122
|
+
// #3791: undefined → undefined を保つ(false に丸めない)。古い FFID は wire に
|
|
123
|
+
// 含めないため、consumer は undefined を「未確認」ではなく「不明」として扱える。
|
|
124
|
+
emailVerified: raw.email_verified,
|
|
122
125
|
name: raw.name,
|
|
123
126
|
picture: raw.picture,
|
|
124
127
|
companyName: raw.company_name ?? null,
|
|
@@ -374,6 +377,9 @@ function createVerifyAccessToken(deps) {
|
|
|
374
377
|
const base = {
|
|
375
378
|
sub: introspectResponse.sub,
|
|
376
379
|
email: introspectResponse.email ?? null,
|
|
380
|
+
// #3791: preserve undefined (do NOT coerce to false) so introspect-strategy
|
|
381
|
+
// callers can distinguish "verified" / "not verified" / "older server".
|
|
382
|
+
email_verified: introspectResponse.email_verified,
|
|
377
383
|
name: introspectResponse.name ?? null,
|
|
378
384
|
picture: introspectResponse.picture ?? null,
|
|
379
385
|
company_name: introspectResponse.company_name ?? null,
|
|
@@ -929,7 +935,7 @@ function createProfileMethods(deps) {
|
|
|
929
935
|
}
|
|
930
936
|
|
|
931
937
|
// src/client/version-check.ts
|
|
932
|
-
var SDK_VERSION = "5.
|
|
938
|
+
var SDK_VERSION = "5.13.0";
|
|
933
939
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
934
940
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
935
941
|
function sdkHeaders() {
|
|
@@ -1001,9 +1007,20 @@ function createOAuthTokenMethods(deps) {
|
|
|
1001
1007
|
logger,
|
|
1002
1008
|
errorCodes
|
|
1003
1009
|
} = deps;
|
|
1004
|
-
async function exchangeCodeForTokens(code, codeVerifier) {
|
|
1010
|
+
async function exchangeCodeForTokens(code, codeVerifier, opts) {
|
|
1005
1011
|
const url = `${baseUrl}${OAUTH_TOKEN_ENDPOINT}`;
|
|
1006
1012
|
logger.debug("Exchanging code for tokens:", url);
|
|
1013
|
+
if (opts?.expectedState !== void 0 || opts?.actualState !== void 0) {
|
|
1014
|
+
if (opts?.expectedState !== opts?.actualState) {
|
|
1015
|
+
logger.error("Token exchange aborted: OAuth state mismatch or omitted (possible CSRF)");
|
|
1016
|
+
return {
|
|
1017
|
+
error: {
|
|
1018
|
+
code: errorCodes.STATE_MISMATCH_ERROR,
|
|
1019
|
+
message: "OAuth state \u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002CSRF \u306E\u53EF\u80FD\u6027\u304C\u3042\u308B\u305F\u3081\u8A8D\u8A3C\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1007
1024
|
const effectiveRedirectUri = resolvedRedirectUri ?? (typeof window !== "undefined" ? window.location.origin + window.location.pathname : null);
|
|
1008
1025
|
if (!effectiveRedirectUri) {
|
|
1009
1026
|
logger.error("redirectUri is required for token exchange in SSR environments. Set config.redirectUri explicitly.");
|
|
@@ -1448,6 +1465,46 @@ function base64UrlEncode(buffer) {
|
|
|
1448
1465
|
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1449
1466
|
}
|
|
1450
1467
|
|
|
1468
|
+
// src/auth/state.ts
|
|
1469
|
+
var STATE_STORAGE_KEY = "ffid_oauth_state";
|
|
1470
|
+
var STATE_FALLBACK_STORAGE_KEY = "ffid_oauth_state_fb";
|
|
1471
|
+
var STATE_FALLBACK_TIMESTAMP_KEY = "ffid_oauth_state_fb_ts";
|
|
1472
|
+
function storeState(state, logger) {
|
|
1473
|
+
if (typeof window === "undefined") {
|
|
1474
|
+
logger?.warn("storeState: storage is not available in SSR context");
|
|
1475
|
+
return false;
|
|
1476
|
+
}
|
|
1477
|
+
let sessionStored = false;
|
|
1478
|
+
try {
|
|
1479
|
+
window.sessionStorage.setItem(STATE_STORAGE_KEY, state);
|
|
1480
|
+
sessionStored = true;
|
|
1481
|
+
} catch (error) {
|
|
1482
|
+
logger?.warn("storeState: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1483
|
+
}
|
|
1484
|
+
let localStored = false;
|
|
1485
|
+
try {
|
|
1486
|
+
window.localStorage.setItem(STATE_FALLBACK_STORAGE_KEY, state);
|
|
1487
|
+
window.localStorage.setItem(STATE_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
|
|
1488
|
+
localStored = true;
|
|
1489
|
+
} catch (error) {
|
|
1490
|
+
logger?.warn("storeState: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1491
|
+
}
|
|
1492
|
+
return sessionStored || localStored;
|
|
1493
|
+
}
|
|
1494
|
+
function cleanupStateStorage(logger) {
|
|
1495
|
+
try {
|
|
1496
|
+
window.sessionStorage.removeItem(STATE_STORAGE_KEY);
|
|
1497
|
+
} catch (error) {
|
|
1498
|
+
logger?.warn("retrieveState: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1499
|
+
}
|
|
1500
|
+
try {
|
|
1501
|
+
window.localStorage.removeItem(STATE_FALLBACK_STORAGE_KEY);
|
|
1502
|
+
window.localStorage.removeItem(STATE_FALLBACK_TIMESTAMP_KEY);
|
|
1503
|
+
} catch (error) {
|
|
1504
|
+
logger?.warn("retrieveState: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1451
1508
|
// src/client/redirect.ts
|
|
1452
1509
|
var OAUTH_AUTHORIZE_ENDPOINT = "/api/v1/oauth/authorize";
|
|
1453
1510
|
var AUTH_LOGOUT_ENDPOINT = "/api/v1/auth/logout";
|
|
@@ -1579,6 +1636,7 @@ function createRedirectMethods(deps) {
|
|
|
1579
1636
|
const recentCount = getRecentRedirectCount(authorizeKey, now, logger);
|
|
1580
1637
|
if (recentCount >= REDIRECT_LOOP_THRESHOLD) {
|
|
1581
1638
|
cleanupVerifierStorage(logger);
|
|
1639
|
+
cleanupStateStorage(logger);
|
|
1582
1640
|
logger.warn("[FFID SDK] redirect loop detected \u2014 \u81EA\u52D5\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u505C\u6B62\u3057\u307E\u3057\u305F", {
|
|
1583
1641
|
authorizeKey,
|
|
1584
1642
|
recentCount,
|
|
@@ -1602,6 +1660,11 @@ function createRedirectMethods(deps) {
|
|
|
1602
1660
|
return { success: false, error: errorMessage };
|
|
1603
1661
|
}
|
|
1604
1662
|
const state = generateRandomState();
|
|
1663
|
+
if (!storeState(state, logger)) {
|
|
1664
|
+
logger.error(
|
|
1665
|
+
"redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u3067\u306E CSRF \u691C\u8A3C\u304C\u5931\u6557\u3057\u307E\u3059"
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1605
1668
|
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
1606
1669
|
const params = new URLSearchParams({
|
|
1607
1670
|
response_type: "code",
|
|
@@ -2316,7 +2379,8 @@ var FFID_ERROR_CODES = {
|
|
|
2316
2379
|
TOKEN_EXCHANGE_ERROR: "TOKEN_EXCHANGE_ERROR",
|
|
2317
2380
|
TOKEN_REFRESH_ERROR: "TOKEN_REFRESH_ERROR",
|
|
2318
2381
|
NO_TOKENS: "NO_TOKENS",
|
|
2319
|
-
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
2382
|
+
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR",
|
|
2383
|
+
STATE_MISMATCH_ERROR: "STATE_MISMATCH_ERROR"
|
|
2320
2384
|
};
|
|
2321
2385
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
2322
2386
|
var DEFAULT_ALLOW_GRACE = true;
|
package/dist/server/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-
|
|
2
|
-
export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-
|
|
1
|
+
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-C3K3sAqq.cjs';
|
|
2
|
+
export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-C3K3sAqq.cjs';
|
|
3
3
|
export { D as DEFAULT_API_BASE_URL, a as DEFAULT_OAUTH_SCOPES } from '../constants-D61jqRIO.cjs';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import '../types-BeVl-z12.cjs';
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-
|
|
2
|
-
export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-
|
|
1
|
+
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-BG0Qr86U.js';
|
|
2
|
+
export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-BG0Qr86U.js';
|
|
3
3
|
export { D as DEFAULT_API_BASE_URL, a as DEFAULT_OAUTH_SCOPES } from '../constants-D61jqRIO.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import '../types-BeVl-z12.js';
|
package/dist/server/index.js
CHANGED
|
@@ -118,6 +118,9 @@ function normalizeUserinfo(raw) {
|
|
|
118
118
|
return {
|
|
119
119
|
sub: raw.sub,
|
|
120
120
|
email: raw.email,
|
|
121
|
+
// #3791: undefined → undefined を保つ(false に丸めない)。古い FFID は wire に
|
|
122
|
+
// 含めないため、consumer は undefined を「未確認」ではなく「不明」として扱える。
|
|
123
|
+
emailVerified: raw.email_verified,
|
|
121
124
|
name: raw.name,
|
|
122
125
|
picture: raw.picture,
|
|
123
126
|
companyName: raw.company_name ?? null,
|
|
@@ -373,6 +376,9 @@ function createVerifyAccessToken(deps) {
|
|
|
373
376
|
const base = {
|
|
374
377
|
sub: introspectResponse.sub,
|
|
375
378
|
email: introspectResponse.email ?? null,
|
|
379
|
+
// #3791: preserve undefined (do NOT coerce to false) so introspect-strategy
|
|
380
|
+
// callers can distinguish "verified" / "not verified" / "older server".
|
|
381
|
+
email_verified: introspectResponse.email_verified,
|
|
376
382
|
name: introspectResponse.name ?? null,
|
|
377
383
|
picture: introspectResponse.picture ?? null,
|
|
378
384
|
company_name: introspectResponse.company_name ?? null,
|
|
@@ -928,7 +934,7 @@ function createProfileMethods(deps) {
|
|
|
928
934
|
}
|
|
929
935
|
|
|
930
936
|
// src/client/version-check.ts
|
|
931
|
-
var SDK_VERSION = "5.
|
|
937
|
+
var SDK_VERSION = "5.13.0";
|
|
932
938
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
933
939
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
934
940
|
function sdkHeaders() {
|
|
@@ -1000,9 +1006,20 @@ function createOAuthTokenMethods(deps) {
|
|
|
1000
1006
|
logger,
|
|
1001
1007
|
errorCodes
|
|
1002
1008
|
} = deps;
|
|
1003
|
-
async function exchangeCodeForTokens(code, codeVerifier) {
|
|
1009
|
+
async function exchangeCodeForTokens(code, codeVerifier, opts) {
|
|
1004
1010
|
const url = `${baseUrl}${OAUTH_TOKEN_ENDPOINT}`;
|
|
1005
1011
|
logger.debug("Exchanging code for tokens:", url);
|
|
1012
|
+
if (opts?.expectedState !== void 0 || opts?.actualState !== void 0) {
|
|
1013
|
+
if (opts?.expectedState !== opts?.actualState) {
|
|
1014
|
+
logger.error("Token exchange aborted: OAuth state mismatch or omitted (possible CSRF)");
|
|
1015
|
+
return {
|
|
1016
|
+
error: {
|
|
1017
|
+
code: errorCodes.STATE_MISMATCH_ERROR,
|
|
1018
|
+
message: "OAuth state \u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002CSRF \u306E\u53EF\u80FD\u6027\u304C\u3042\u308B\u305F\u3081\u8A8D\u8A3C\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1006
1023
|
const effectiveRedirectUri = resolvedRedirectUri ?? (typeof window !== "undefined" ? window.location.origin + window.location.pathname : null);
|
|
1007
1024
|
if (!effectiveRedirectUri) {
|
|
1008
1025
|
logger.error("redirectUri is required for token exchange in SSR environments. Set config.redirectUri explicitly.");
|
|
@@ -1447,6 +1464,46 @@ function base64UrlEncode(buffer) {
|
|
|
1447
1464
|
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1448
1465
|
}
|
|
1449
1466
|
|
|
1467
|
+
// src/auth/state.ts
|
|
1468
|
+
var STATE_STORAGE_KEY = "ffid_oauth_state";
|
|
1469
|
+
var STATE_FALLBACK_STORAGE_KEY = "ffid_oauth_state_fb";
|
|
1470
|
+
var STATE_FALLBACK_TIMESTAMP_KEY = "ffid_oauth_state_fb_ts";
|
|
1471
|
+
function storeState(state, logger) {
|
|
1472
|
+
if (typeof window === "undefined") {
|
|
1473
|
+
logger?.warn("storeState: storage is not available in SSR context");
|
|
1474
|
+
return false;
|
|
1475
|
+
}
|
|
1476
|
+
let sessionStored = false;
|
|
1477
|
+
try {
|
|
1478
|
+
window.sessionStorage.setItem(STATE_STORAGE_KEY, state);
|
|
1479
|
+
sessionStored = true;
|
|
1480
|
+
} catch (error) {
|
|
1481
|
+
logger?.warn("storeState: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1482
|
+
}
|
|
1483
|
+
let localStored = false;
|
|
1484
|
+
try {
|
|
1485
|
+
window.localStorage.setItem(STATE_FALLBACK_STORAGE_KEY, state);
|
|
1486
|
+
window.localStorage.setItem(STATE_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
|
|
1487
|
+
localStored = true;
|
|
1488
|
+
} catch (error) {
|
|
1489
|
+
logger?.warn("storeState: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1490
|
+
}
|
|
1491
|
+
return sessionStored || localStored;
|
|
1492
|
+
}
|
|
1493
|
+
function cleanupStateStorage(logger) {
|
|
1494
|
+
try {
|
|
1495
|
+
window.sessionStorage.removeItem(STATE_STORAGE_KEY);
|
|
1496
|
+
} catch (error) {
|
|
1497
|
+
logger?.warn("retrieveState: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1498
|
+
}
|
|
1499
|
+
try {
|
|
1500
|
+
window.localStorage.removeItem(STATE_FALLBACK_STORAGE_KEY);
|
|
1501
|
+
window.localStorage.removeItem(STATE_FALLBACK_TIMESTAMP_KEY);
|
|
1502
|
+
} catch (error) {
|
|
1503
|
+
logger?.warn("retrieveState: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1450
1507
|
// src/client/redirect.ts
|
|
1451
1508
|
var OAUTH_AUTHORIZE_ENDPOINT = "/api/v1/oauth/authorize";
|
|
1452
1509
|
var AUTH_LOGOUT_ENDPOINT = "/api/v1/auth/logout";
|
|
@@ -1578,6 +1635,7 @@ function createRedirectMethods(deps) {
|
|
|
1578
1635
|
const recentCount = getRecentRedirectCount(authorizeKey, now, logger);
|
|
1579
1636
|
if (recentCount >= REDIRECT_LOOP_THRESHOLD) {
|
|
1580
1637
|
cleanupVerifierStorage(logger);
|
|
1638
|
+
cleanupStateStorage(logger);
|
|
1581
1639
|
logger.warn("[FFID SDK] redirect loop detected \u2014 \u81EA\u52D5\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u505C\u6B62\u3057\u307E\u3057\u305F", {
|
|
1582
1640
|
authorizeKey,
|
|
1583
1641
|
recentCount,
|
|
@@ -1601,6 +1659,11 @@ function createRedirectMethods(deps) {
|
|
|
1601
1659
|
return { success: false, error: errorMessage };
|
|
1602
1660
|
}
|
|
1603
1661
|
const state = generateRandomState();
|
|
1662
|
+
if (!storeState(state, logger)) {
|
|
1663
|
+
logger.error(
|
|
1664
|
+
"redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u3067\u306E CSRF \u691C\u8A3C\u304C\u5931\u6557\u3057\u307E\u3059"
|
|
1665
|
+
);
|
|
1666
|
+
}
|
|
1604
1667
|
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
1605
1668
|
const params = new URLSearchParams({
|
|
1606
1669
|
response_type: "code",
|
|
@@ -2315,7 +2378,8 @@ var FFID_ERROR_CODES = {
|
|
|
2315
2378
|
TOKEN_EXCHANGE_ERROR: "TOKEN_EXCHANGE_ERROR",
|
|
2316
2379
|
TOKEN_REFRESH_ERROR: "TOKEN_REFRESH_ERROR",
|
|
2317
2380
|
NO_TOKENS: "NO_TOKENS",
|
|
2318
|
-
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
2381
|
+
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR",
|
|
2382
|
+
STATE_MISMATCH_ERROR: "STATE_MISMATCH_ERROR"
|
|
2319
2383
|
};
|
|
2320
2384
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
2321
2385
|
var DEFAULT_ALLOW_GRACE = true;
|