@feelflow/ffid-sdk 1.4.0 → 1.5.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.
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('react');
4
+ var jose = require('jose');
4
5
  var jsxRuntime = require('react/jsx-runtime');
5
6
 
6
7
  // src/constants.ts
@@ -178,11 +179,79 @@ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
178
179
  }
179
180
  ];
180
181
  }
182
+ var JWKS_ENDPOINT = "/.well-known/jwks.json";
183
+ var JWT_ISSUER = "https://id.feelflow.co.jp";
184
+ var JWT_ALGORITHM = "ES256";
185
+ var JWT_CLOCK_TOLERANCE_SECONDS = 30;
186
+ function createJwtVerifier(deps) {
187
+ const { baseUrl, serviceCode, logger, createError, errorCodes } = deps;
188
+ const jwksUrl = new URL(JWKS_ENDPOINT, baseUrl);
189
+ const jwks = jose.createRemoteJWKSet(jwksUrl);
190
+ async function verifyJwt(accessToken) {
191
+ if (!accessToken || !accessToken.trim()) {
192
+ return {
193
+ error: createError(
194
+ errorCodes.TOKEN_VERIFICATION_ERROR,
195
+ "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093"
196
+ )
197
+ };
198
+ }
199
+ try {
200
+ const { payload } = await jose.jwtVerify(accessToken, jwks, {
201
+ algorithms: [JWT_ALGORITHM],
202
+ issuer: JWT_ISSUER,
203
+ audience: serviceCode,
204
+ clockTolerance: JWT_CLOCK_TOLERANCE_SECONDS
205
+ });
206
+ if (!payload.sub) {
207
+ logger.error("JWT payload missing sub claim");
208
+ return {
209
+ error: createError(
210
+ errorCodes.TOKEN_VERIFICATION_ERROR,
211
+ "JWT\u30DA\u30A4\u30ED\u30FC\u30C9\u306B\u30E6\u30FC\u30B6\u30FCID\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u305B\u3093"
212
+ )
213
+ };
214
+ }
215
+ const userInfo = {
216
+ sub: payload.sub,
217
+ email: null,
218
+ name: null,
219
+ picture: null,
220
+ organizationId: payload.org_id ?? null
221
+ // subscription is not available from JWT
222
+ };
223
+ return { data: userInfo };
224
+ } catch (error) {
225
+ const message = error instanceof Error ? error.message : "JWT\u691C\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F";
226
+ logger.error("JWT verification failed:", message);
227
+ return {
228
+ error: createError(
229
+ errorCodes.TOKEN_VERIFICATION_ERROR,
230
+ `JWT\u691C\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${message}`
231
+ )
232
+ };
233
+ }
234
+ }
235
+ return verifyJwt;
236
+ }
181
237
 
182
238
  // src/client/verify-access-token.ts
183
239
  var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
184
240
  function createVerifyAccessToken(deps) {
185
- const { authMode, baseUrl, serviceApiKey, logger, createError, errorCodes } = deps;
241
+ const { authMode, baseUrl, serviceCode, serviceApiKey, verifyStrategy, logger, createError, errorCodes } = deps;
242
+ let jwtVerify2 = null;
243
+ function getJwtVerifier() {
244
+ if (!jwtVerify2) {
245
+ jwtVerify2 = createJwtVerifier({
246
+ baseUrl,
247
+ serviceCode,
248
+ logger,
249
+ createError,
250
+ errorCodes: { TOKEN_VERIFICATION_ERROR: errorCodes.TOKEN_VERIFICATION_ERROR }
251
+ });
252
+ }
253
+ return jwtVerify2;
254
+ }
186
255
  async function verifyAccessToken(accessToken) {
187
256
  if (authMode !== "service-key") {
188
257
  return {
@@ -200,6 +269,12 @@ function createVerifyAccessToken(deps) {
200
269
  )
201
270
  };
202
271
  }
272
+ if (verifyStrategy === "jwt") {
273
+ return getJwtVerifier()(accessToken);
274
+ }
275
+ return verifyViaIntrospect(accessToken);
276
+ }
277
+ async function verifyViaIntrospect(accessToken) {
203
278
  if (!serviceApiKey) {
204
279
  return {
205
280
  error: createError(
@@ -336,6 +411,7 @@ function createFFIDClient(config) {
336
411
  const authMode = config.authMode ?? "cookie";
337
412
  const clientId = config.clientId ?? config.serviceCode;
338
413
  const serviceApiKey = config.serviceApiKey?.trim();
414
+ const verifyStrategy = config.verifyStrategy ?? "jwt";
339
415
  if (authMode === "service-key" && !serviceApiKey) {
340
416
  throw new Error("FFID Client: service-key \u30E2\u30FC\u30C9\u3067\u306F serviceApiKey \u304C\u5FC5\u9808\u3067\u3059");
341
417
  }
@@ -827,7 +903,9 @@ function createFFIDClient(config) {
827
903
  const verifyAccessToken = createVerifyAccessToken({
828
904
  authMode,
829
905
  baseUrl,
906
+ serviceCode: config.serviceCode,
830
907
  serviceApiKey,
908
+ verifyStrategy,
831
909
  logger,
832
910
  createError,
833
911
  errorCodes: FFID_ERROR_CODES
@@ -1,4 +1,5 @@
1
1
  import { createContext, useState, useRef, useEffect, useMemo, useCallback, useContext } from 'react';
2
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
2
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
4
 
4
5
  // src/constants.ts
@@ -176,11 +177,79 @@ function mapUserinfoSubscriptionToSession(userinfo, serviceCode) {
176
177
  }
177
178
  ];
178
179
  }
180
+ var JWKS_ENDPOINT = "/.well-known/jwks.json";
181
+ var JWT_ISSUER = "https://id.feelflow.co.jp";
182
+ var JWT_ALGORITHM = "ES256";
183
+ var JWT_CLOCK_TOLERANCE_SECONDS = 30;
184
+ function createJwtVerifier(deps) {
185
+ const { baseUrl, serviceCode, logger, createError, errorCodes } = deps;
186
+ const jwksUrl = new URL(JWKS_ENDPOINT, baseUrl);
187
+ const jwks = createRemoteJWKSet(jwksUrl);
188
+ async function verifyJwt(accessToken) {
189
+ if (!accessToken || !accessToken.trim()) {
190
+ return {
191
+ error: createError(
192
+ errorCodes.TOKEN_VERIFICATION_ERROR,
193
+ "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093"
194
+ )
195
+ };
196
+ }
197
+ try {
198
+ const { payload } = await jwtVerify(accessToken, jwks, {
199
+ algorithms: [JWT_ALGORITHM],
200
+ issuer: JWT_ISSUER,
201
+ audience: serviceCode,
202
+ clockTolerance: JWT_CLOCK_TOLERANCE_SECONDS
203
+ });
204
+ if (!payload.sub) {
205
+ logger.error("JWT payload missing sub claim");
206
+ return {
207
+ error: createError(
208
+ errorCodes.TOKEN_VERIFICATION_ERROR,
209
+ "JWT\u30DA\u30A4\u30ED\u30FC\u30C9\u306B\u30E6\u30FC\u30B6\u30FCID\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u305B\u3093"
210
+ )
211
+ };
212
+ }
213
+ const userInfo = {
214
+ sub: payload.sub,
215
+ email: null,
216
+ name: null,
217
+ picture: null,
218
+ organizationId: payload.org_id ?? null
219
+ // subscription is not available from JWT
220
+ };
221
+ return { data: userInfo };
222
+ } catch (error) {
223
+ const message = error instanceof Error ? error.message : "JWT\u691C\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F";
224
+ logger.error("JWT verification failed:", message);
225
+ return {
226
+ error: createError(
227
+ errorCodes.TOKEN_VERIFICATION_ERROR,
228
+ `JWT\u691C\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${message}`
229
+ )
230
+ };
231
+ }
232
+ }
233
+ return verifyJwt;
234
+ }
179
235
 
180
236
  // src/client/verify-access-token.ts
181
237
  var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
182
238
  function createVerifyAccessToken(deps) {
183
- const { authMode, baseUrl, serviceApiKey, logger, createError, errorCodes } = deps;
239
+ const { authMode, baseUrl, serviceCode, serviceApiKey, verifyStrategy, logger, createError, errorCodes } = deps;
240
+ let jwtVerify2 = null;
241
+ function getJwtVerifier() {
242
+ if (!jwtVerify2) {
243
+ jwtVerify2 = createJwtVerifier({
244
+ baseUrl,
245
+ serviceCode,
246
+ logger,
247
+ createError,
248
+ errorCodes: { TOKEN_VERIFICATION_ERROR: errorCodes.TOKEN_VERIFICATION_ERROR }
249
+ });
250
+ }
251
+ return jwtVerify2;
252
+ }
184
253
  async function verifyAccessToken(accessToken) {
185
254
  if (authMode !== "service-key") {
186
255
  return {
@@ -198,6 +267,12 @@ function createVerifyAccessToken(deps) {
198
267
  )
199
268
  };
200
269
  }
270
+ if (verifyStrategy === "jwt") {
271
+ return getJwtVerifier()(accessToken);
272
+ }
273
+ return verifyViaIntrospect(accessToken);
274
+ }
275
+ async function verifyViaIntrospect(accessToken) {
201
276
  if (!serviceApiKey) {
202
277
  return {
203
278
  error: createError(
@@ -334,6 +409,7 @@ function createFFIDClient(config) {
334
409
  const authMode = config.authMode ?? "cookie";
335
410
  const clientId = config.clientId ?? config.serviceCode;
336
411
  const serviceApiKey = config.serviceApiKey?.trim();
412
+ const verifyStrategy = config.verifyStrategy ?? "jwt";
337
413
  if (authMode === "service-key" && !serviceApiKey) {
338
414
  throw new Error("FFID Client: service-key \u30E2\u30FC\u30C9\u3067\u306F serviceApiKey \u304C\u5FC5\u9808\u3067\u3059");
339
415
  }
@@ -825,7 +901,9 @@ function createFFIDClient(config) {
825
901
  const verifyAccessToken = createVerifyAccessToken({
826
902
  authMode,
827
903
  baseUrl,
904
+ serviceCode: config.serviceCode,
828
905
  serviceApiKey,
906
+ verifyStrategy,
829
907
  logger,
830
908
  createError,
831
909
  errorCodes: FFID_ERROR_CODES
@@ -1,30 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var chunk5XOQIUEZ_cjs = require('../chunk-5XOQIUEZ.cjs');
3
+ var chunkUBQEG3CS_cjs = require('../chunk-UBQEG3CS.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunk5XOQIUEZ_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunk5XOQIUEZ_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDLoginButton", {
16
16
  enumerable: true,
17
- get: function () { return chunk5XOQIUEZ_cjs.FFIDLoginButton; }
17
+ get: function () { return chunkUBQEG3CS_cjs.FFIDLoginButton; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
20
20
  enumerable: true,
21
- get: function () { return chunk5XOQIUEZ_cjs.FFIDOrganizationSwitcher; }
21
+ get: function () { return chunkUBQEG3CS_cjs.FFIDOrganizationSwitcher; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
24
24
  enumerable: true,
25
- get: function () { return chunk5XOQIUEZ_cjs.FFIDSubscriptionBadge; }
25
+ get: function () { return chunkUBQEG3CS_cjs.FFIDSubscriptionBadge; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDUserMenu", {
28
28
  enumerable: true,
29
- get: function () { return chunk5XOQIUEZ_cjs.FFIDUserMenu; }
29
+ get: function () { return chunkUBQEG3CS_cjs.FFIDUserMenu; }
30
30
  });
@@ -1,3 +1,3 @@
1
- export { p as FFIDAnnouncementBadge, K as FFIDAnnouncementBadgeClassNames, M as FFIDAnnouncementBadgeProps, q as FFIDAnnouncementList, N as FFIDAnnouncementListClassNames, O as FFIDAnnouncementListProps, v as FFIDLoginButton, P as FFIDLoginButtonProps, z as FFIDOrganizationSwitcher, Q as FFIDOrganizationSwitcherClassNames, R as FFIDOrganizationSwitcherProps, D as FFIDSubscriptionBadge, S as FFIDSubscriptionBadgeClassNames, T as FFIDSubscriptionBadgeProps, H as FFIDUserMenu, V as FFIDUserMenuClassNames, W as FFIDUserMenuProps } from '../index-DHmt43kQ.cjs';
1
+ export { p as FFIDAnnouncementBadge, M as FFIDAnnouncementBadgeClassNames, N as FFIDAnnouncementBadgeProps, q as FFIDAnnouncementList, O as FFIDAnnouncementListClassNames, P as FFIDAnnouncementListProps, w as FFIDLoginButton, Q as FFIDLoginButtonProps, B as FFIDOrganizationSwitcher, R as FFIDOrganizationSwitcherClassNames, S as FFIDOrganizationSwitcherProps, E as FFIDSubscriptionBadge, T as FFIDSubscriptionBadgeClassNames, V as FFIDSubscriptionBadgeProps, I as FFIDUserMenu, W as FFIDUserMenuClassNames, X as FFIDUserMenuProps } from '../index-DEtyiwFZ.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { p as FFIDAnnouncementBadge, K as FFIDAnnouncementBadgeClassNames, M as FFIDAnnouncementBadgeProps, q as FFIDAnnouncementList, N as FFIDAnnouncementListClassNames, O as FFIDAnnouncementListProps, v as FFIDLoginButton, P as FFIDLoginButtonProps, z as FFIDOrganizationSwitcher, Q as FFIDOrganizationSwitcherClassNames, R as FFIDOrganizationSwitcherProps, D as FFIDSubscriptionBadge, S as FFIDSubscriptionBadgeClassNames, T as FFIDSubscriptionBadgeProps, H as FFIDUserMenu, V as FFIDUserMenuClassNames, W as FFIDUserMenuProps } from '../index-DHmt43kQ.js';
1
+ export { p as FFIDAnnouncementBadge, M as FFIDAnnouncementBadgeClassNames, N as FFIDAnnouncementBadgeProps, q as FFIDAnnouncementList, O as FFIDAnnouncementListClassNames, P as FFIDAnnouncementListProps, w as FFIDLoginButton, Q as FFIDLoginButtonProps, B as FFIDOrganizationSwitcher, R as FFIDOrganizationSwitcherClassNames, S as FFIDOrganizationSwitcherProps, E as FFIDSubscriptionBadge, T as FFIDSubscriptionBadgeClassNames, V as FFIDSubscriptionBadgeProps, I as FFIDUserMenu, W as FFIDUserMenuClassNames, X as FFIDUserMenuProps } from '../index-DEtyiwFZ.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-S2YL5Y4O.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-YJFOE2PP.js';
@@ -139,6 +139,42 @@ interface FFIDConfig {
139
139
  clientId?: string | undefined;
140
140
  /** Service API key for service-key mode (X-Service-Api-Key header) */
141
141
  serviceApiKey?: string | undefined;
142
+ /**
143
+ * Token verification strategy for service-key mode.
144
+ * - 'jwt': Local JWT verification via JWKS (default, lower latency)
145
+ * - 'introspect': Remote introspection via /api/v1/oauth/introspect
146
+ *
147
+ * JWT verification returns limited claims (no email/name/picture/subscription).
148
+ * Use 'introspect' if you need full user profile data.
149
+ */
150
+ verifyStrategy?: 'jwt' | 'introspect' | undefined;
151
+ }
152
+ /**
153
+ * FFID JWT claims structure (minimal payload).
154
+ *
155
+ * These are the claims available when using JWT local verification.
156
+ * email, name, picture, and subscription are NOT included in the JWT
157
+ * to minimize token size.
158
+ */
159
+ interface FFIDJwtClaims {
160
+ /** Subject: user UUID */
161
+ sub: string;
162
+ /** Issuer */
163
+ iss: string;
164
+ /** Audience: service code */
165
+ aud: string;
166
+ /** Expiration time (Unix timestamp) */
167
+ exp: number;
168
+ /** Issued at (Unix timestamp) */
169
+ iat: number;
170
+ /** JWT ID: token row UUID */
171
+ jti: string;
172
+ /** OAuth scope */
173
+ scope: string;
174
+ /** Organization UUID */
175
+ org_id: string | null;
176
+ /** Service UUID */
177
+ svc_id: string;
142
178
  }
143
179
  /**
144
180
  * FFID context value provided to consumers
@@ -647,4 +683,4 @@ interface FFIDAnnouncementListProps {
647
683
  */
648
684
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
649
685
 
650
- export { type AnnouncementListResponse as A, type FFIDSeatModel as B, type FFIDSubscription as C, FFIDSubscriptionBadge as D, type FFIDSubscriptionStatus as E, type FFIDConfig as F, type FFIDTokenIntrospectionResponse as G, FFIDUserMenu as H, type UseFFIDAnnouncementsReturn as I, useFFIDAnnouncements as J, type FFIDAnnouncementBadgeClassNames as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementBadgeProps as M, type FFIDAnnouncementListClassNames as N, type FFIDAnnouncementListProps as O, type FFIDLoginButtonProps as P, type FFIDOrganizationSwitcherClassNames as Q, type FFIDOrganizationSwitcherProps as R, type FFIDSubscriptionBadgeClassNames as S, type FFIDSubscriptionBadgeProps as T, type UseFFIDAnnouncementsOptions as U, type FFIDUserMenuClassNames as V, type FFIDUserMenuProps as W, type FFIDApiResponse as a, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDOAuthUserInfo as e, type FFIDLogger as f, type FFIDUser as g, type FFIDOrganization as h, type FFIDSubscriptionContextValue as i, type FFIDAnnouncementsClientConfig as j, type FFIDAnnouncementsApiResponse as k, type FFIDAnnouncementsLogger as l, type Announcement as m, type AnnouncementStatus as n, type AnnouncementType as o, FFIDAnnouncementBadge as p, FFIDAnnouncementList as q, type FFIDAnnouncementsError as r, type FFIDAnnouncementsErrorCode as s, type FFIDAnnouncementsServerResponse as t, type FFIDContextValue as u, FFIDLoginButton as v, type FFIDOAuthTokenResponse as w, type FFIDOAuthUserInfoMemberRole as x, type FFIDOAuthUserInfoSubscription as y, FFIDOrganizationSwitcher as z };
686
+ export { type AnnouncementListResponse as A, FFIDOrganizationSwitcher as B, type FFIDSeatModel as C, type FFIDSubscription as D, FFIDSubscriptionBadge as E, type FFIDConfig as F, type FFIDSubscriptionStatus as G, type FFIDTokenIntrospectionResponse as H, FFIDUserMenu as I, type UseFFIDAnnouncementsReturn as J, useFFIDAnnouncements as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementBadgeClassNames as M, type FFIDAnnouncementBadgeProps as N, type FFIDAnnouncementListClassNames as O, type FFIDAnnouncementListProps as P, type FFIDLoginButtonProps as Q, type FFIDOrganizationSwitcherClassNames as R, type FFIDOrganizationSwitcherProps as S, type FFIDSubscriptionBadgeClassNames as T, type UseFFIDAnnouncementsOptions as U, type FFIDSubscriptionBadgeProps as V, type FFIDUserMenuClassNames as W, type FFIDUserMenuProps as X, type FFIDApiResponse as a, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDOAuthUserInfo as e, type FFIDLogger as f, type FFIDUser as g, type FFIDOrganization as h, type FFIDSubscriptionContextValue as i, type FFIDAnnouncementsClientConfig as j, type FFIDAnnouncementsApiResponse as k, type FFIDAnnouncementsLogger as l, type Announcement as m, type AnnouncementStatus as n, type AnnouncementType as o, FFIDAnnouncementBadge as p, FFIDAnnouncementList as q, type FFIDAnnouncementsError as r, type FFIDAnnouncementsErrorCode as s, type FFIDAnnouncementsServerResponse as t, type FFIDContextValue as u, type FFIDJwtClaims as v, FFIDLoginButton as w, type FFIDOAuthTokenResponse as x, type FFIDOAuthUserInfoMemberRole as y, type FFIDOAuthUserInfoSubscription as z };
@@ -139,6 +139,42 @@ interface FFIDConfig {
139
139
  clientId?: string | undefined;
140
140
  /** Service API key for service-key mode (X-Service-Api-Key header) */
141
141
  serviceApiKey?: string | undefined;
142
+ /**
143
+ * Token verification strategy for service-key mode.
144
+ * - 'jwt': Local JWT verification via JWKS (default, lower latency)
145
+ * - 'introspect': Remote introspection via /api/v1/oauth/introspect
146
+ *
147
+ * JWT verification returns limited claims (no email/name/picture/subscription).
148
+ * Use 'introspect' if you need full user profile data.
149
+ */
150
+ verifyStrategy?: 'jwt' | 'introspect' | undefined;
151
+ }
152
+ /**
153
+ * FFID JWT claims structure (minimal payload).
154
+ *
155
+ * These are the claims available when using JWT local verification.
156
+ * email, name, picture, and subscription are NOT included in the JWT
157
+ * to minimize token size.
158
+ */
159
+ interface FFIDJwtClaims {
160
+ /** Subject: user UUID */
161
+ sub: string;
162
+ /** Issuer */
163
+ iss: string;
164
+ /** Audience: service code */
165
+ aud: string;
166
+ /** Expiration time (Unix timestamp) */
167
+ exp: number;
168
+ /** Issued at (Unix timestamp) */
169
+ iat: number;
170
+ /** JWT ID: token row UUID */
171
+ jti: string;
172
+ /** OAuth scope */
173
+ scope: string;
174
+ /** Organization UUID */
175
+ org_id: string | null;
176
+ /** Service UUID */
177
+ svc_id: string;
142
178
  }
143
179
  /**
144
180
  * FFID context value provided to consumers
@@ -647,4 +683,4 @@ interface FFIDAnnouncementListProps {
647
683
  */
648
684
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
649
685
 
650
- export { type AnnouncementListResponse as A, type FFIDSeatModel as B, type FFIDSubscription as C, FFIDSubscriptionBadge as D, type FFIDSubscriptionStatus as E, type FFIDConfig as F, type FFIDTokenIntrospectionResponse as G, FFIDUserMenu as H, type UseFFIDAnnouncementsReturn as I, useFFIDAnnouncements as J, type FFIDAnnouncementBadgeClassNames as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementBadgeProps as M, type FFIDAnnouncementListClassNames as N, type FFIDAnnouncementListProps as O, type FFIDLoginButtonProps as P, type FFIDOrganizationSwitcherClassNames as Q, type FFIDOrganizationSwitcherProps as R, type FFIDSubscriptionBadgeClassNames as S, type FFIDSubscriptionBadgeProps as T, type UseFFIDAnnouncementsOptions as U, type FFIDUserMenuClassNames as V, type FFIDUserMenuProps as W, type FFIDApiResponse as a, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDOAuthUserInfo as e, type FFIDLogger as f, type FFIDUser as g, type FFIDOrganization as h, type FFIDSubscriptionContextValue as i, type FFIDAnnouncementsClientConfig as j, type FFIDAnnouncementsApiResponse as k, type FFIDAnnouncementsLogger as l, type Announcement as m, type AnnouncementStatus as n, type AnnouncementType as o, FFIDAnnouncementBadge as p, FFIDAnnouncementList as q, type FFIDAnnouncementsError as r, type FFIDAnnouncementsErrorCode as s, type FFIDAnnouncementsServerResponse as t, type FFIDContextValue as u, FFIDLoginButton as v, type FFIDOAuthTokenResponse as w, type FFIDOAuthUserInfoMemberRole as x, type FFIDOAuthUserInfoSubscription as y, FFIDOrganizationSwitcher as z };
686
+ export { type AnnouncementListResponse as A, FFIDOrganizationSwitcher as B, type FFIDSeatModel as C, type FFIDSubscription as D, FFIDSubscriptionBadge as E, type FFIDConfig as F, type FFIDSubscriptionStatus as G, type FFIDTokenIntrospectionResponse as H, FFIDUserMenu as I, type UseFFIDAnnouncementsReturn as J, useFFIDAnnouncements as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementBadgeClassNames as M, type FFIDAnnouncementBadgeProps as N, type FFIDAnnouncementListClassNames as O, type FFIDAnnouncementListProps as P, type FFIDLoginButtonProps as Q, type FFIDOrganizationSwitcherClassNames as R, type FFIDOrganizationSwitcherProps as S, type FFIDSubscriptionBadgeClassNames as T, type UseFFIDAnnouncementsOptions as U, type FFIDSubscriptionBadgeProps as V, type FFIDUserMenuClassNames as W, type FFIDUserMenuProps as X, type FFIDApiResponse as a, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDOAuthUserInfo as e, type FFIDLogger as f, type FFIDUser as g, type FFIDOrganization as h, type FFIDSubscriptionContextValue as i, type FFIDAnnouncementsClientConfig as j, type FFIDAnnouncementsApiResponse as k, type FFIDAnnouncementsLogger as l, type Announcement as m, type AnnouncementStatus as n, type AnnouncementType as o, FFIDAnnouncementBadge as p, FFIDAnnouncementList as q, type FFIDAnnouncementsError as r, type FFIDAnnouncementsErrorCode as s, type FFIDAnnouncementsServerResponse as t, type FFIDContextValue as u, type FFIDJwtClaims as v, FFIDLoginButton as w, type FFIDOAuthTokenResponse as x, type FFIDOAuthUserInfoMemberRole as y, type FFIDOAuthUserInfoSubscription as z };
package/dist/index.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunk5XOQIUEZ_cjs = require('./chunk-5XOQIUEZ.cjs');
3
+ var chunkUBQEG3CS_cjs = require('./chunk-UBQEG3CS.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
7
  function withFFIDAuth(Component, options = {}) {
8
8
  const WrappedComponent = (props) => {
9
- const { isLoading, isAuthenticated, login } = chunk5XOQIUEZ_cjs.useFFIDContext();
9
+ const { isLoading, isAuthenticated, login } = chunkUBQEG3CS_cjs.useFFIDContext();
10
10
  const hasRedirected = react.useRef(false);
11
11
  react.useEffect(() => {
12
12
  if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
@@ -31,82 +31,82 @@ function withFFIDAuth(Component, options = {}) {
31
31
 
32
32
  Object.defineProperty(exports, "DEFAULT_API_BASE_URL", {
33
33
  enumerable: true,
34
- get: function () { return chunk5XOQIUEZ_cjs.DEFAULT_API_BASE_URL; }
34
+ get: function () { return chunkUBQEG3CS_cjs.DEFAULT_API_BASE_URL; }
35
35
  });
36
36
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
37
37
  enumerable: true,
38
- get: function () { return chunk5XOQIUEZ_cjs.FFIDAnnouncementBadge; }
38
+ get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementBadge; }
39
39
  });
40
40
  Object.defineProperty(exports, "FFIDAnnouncementList", {
41
41
  enumerable: true,
42
- get: function () { return chunk5XOQIUEZ_cjs.FFIDAnnouncementList; }
42
+ get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementList; }
43
43
  });
44
44
  Object.defineProperty(exports, "FFIDLoginButton", {
45
45
  enumerable: true,
46
- get: function () { return chunk5XOQIUEZ_cjs.FFIDLoginButton; }
46
+ get: function () { return chunkUBQEG3CS_cjs.FFIDLoginButton; }
47
47
  });
48
48
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
49
49
  enumerable: true,
50
- get: function () { return chunk5XOQIUEZ_cjs.FFIDOrganizationSwitcher; }
50
+ get: function () { return chunkUBQEG3CS_cjs.FFIDOrganizationSwitcher; }
51
51
  });
52
52
  Object.defineProperty(exports, "FFIDProvider", {
53
53
  enumerable: true,
54
- get: function () { return chunk5XOQIUEZ_cjs.FFIDProvider; }
54
+ get: function () { return chunkUBQEG3CS_cjs.FFIDProvider; }
55
55
  });
56
56
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
57
57
  enumerable: true,
58
- get: function () { return chunk5XOQIUEZ_cjs.FFIDSubscriptionBadge; }
58
+ get: function () { return chunkUBQEG3CS_cjs.FFIDSubscriptionBadge; }
59
59
  });
60
60
  Object.defineProperty(exports, "FFIDUserMenu", {
61
61
  enumerable: true,
62
- get: function () { return chunk5XOQIUEZ_cjs.FFIDUserMenu; }
62
+ get: function () { return chunkUBQEG3CS_cjs.FFIDUserMenu; }
63
63
  });
64
64
  Object.defineProperty(exports, "FFID_ANNOUNCEMENTS_ERROR_CODES", {
65
65
  enumerable: true,
66
- get: function () { return chunk5XOQIUEZ_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
66
+ get: function () { return chunkUBQEG3CS_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
67
67
  });
68
68
  Object.defineProperty(exports, "createFFIDAnnouncementsClient", {
69
69
  enumerable: true,
70
- get: function () { return chunk5XOQIUEZ_cjs.createFFIDAnnouncementsClient; }
70
+ get: function () { return chunkUBQEG3CS_cjs.createFFIDAnnouncementsClient; }
71
71
  });
72
72
  Object.defineProperty(exports, "createFFIDClient", {
73
73
  enumerable: true,
74
- get: function () { return chunk5XOQIUEZ_cjs.createFFIDClient; }
74
+ get: function () { return chunkUBQEG3CS_cjs.createFFIDClient; }
75
75
  });
76
76
  Object.defineProperty(exports, "createTokenStore", {
77
77
  enumerable: true,
78
- get: function () { return chunk5XOQIUEZ_cjs.createTokenStore; }
78
+ get: function () { return chunkUBQEG3CS_cjs.createTokenStore; }
79
79
  });
80
80
  Object.defineProperty(exports, "generateCodeChallenge", {
81
81
  enumerable: true,
82
- get: function () { return chunk5XOQIUEZ_cjs.generateCodeChallenge; }
82
+ get: function () { return chunkUBQEG3CS_cjs.generateCodeChallenge; }
83
83
  });
84
84
  Object.defineProperty(exports, "generateCodeVerifier", {
85
85
  enumerable: true,
86
- get: function () { return chunk5XOQIUEZ_cjs.generateCodeVerifier; }
86
+ get: function () { return chunkUBQEG3CS_cjs.generateCodeVerifier; }
87
87
  });
88
88
  Object.defineProperty(exports, "retrieveCodeVerifier", {
89
89
  enumerable: true,
90
- get: function () { return chunk5XOQIUEZ_cjs.retrieveCodeVerifier; }
90
+ get: function () { return chunkUBQEG3CS_cjs.retrieveCodeVerifier; }
91
91
  });
92
92
  Object.defineProperty(exports, "storeCodeVerifier", {
93
93
  enumerable: true,
94
- get: function () { return chunk5XOQIUEZ_cjs.storeCodeVerifier; }
94
+ get: function () { return chunkUBQEG3CS_cjs.storeCodeVerifier; }
95
95
  });
96
96
  Object.defineProperty(exports, "useFFID", {
97
97
  enumerable: true,
98
- get: function () { return chunk5XOQIUEZ_cjs.useFFID; }
98
+ get: function () { return chunkUBQEG3CS_cjs.useFFID; }
99
99
  });
100
100
  Object.defineProperty(exports, "useFFIDAnnouncements", {
101
101
  enumerable: true,
102
- get: function () { return chunk5XOQIUEZ_cjs.useFFIDAnnouncements; }
102
+ get: function () { return chunkUBQEG3CS_cjs.useFFIDAnnouncements; }
103
103
  });
104
104
  Object.defineProperty(exports, "useSubscription", {
105
105
  enumerable: true,
106
- get: function () { return chunk5XOQIUEZ_cjs.useSubscription; }
106
+ get: function () { return chunkUBQEG3CS_cjs.useSubscription; }
107
107
  });
108
108
  Object.defineProperty(exports, "withSubscription", {
109
109
  enumerable: true,
110
- get: function () { return chunk5XOQIUEZ_cjs.withSubscription; }
110
+ get: function () { return chunkUBQEG3CS_cjs.withSubscription; }
111
111
  });
112
112
  exports.withFFIDAuth = withFFIDAuth;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDConfig, a as FFIDApiResponse, b as FFIDSessionResponse, c as FFIDError, d as FFIDSubscriptionCheckResponse, e as FFIDOAuthUserInfo, f as FFIDLogger, g as FFIDUser, h as FFIDOrganization, i as FFIDSubscriptionContextValue, j as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, k as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, l as FFIDAnnouncementsLogger } from './index-DHmt43kQ.cjs';
2
- export { m as Announcement, n as AnnouncementStatus, o as AnnouncementType, p as FFIDAnnouncementBadge, q as FFIDAnnouncementList, r as FFIDAnnouncementsError, s as FFIDAnnouncementsErrorCode, t as FFIDAnnouncementsServerResponse, u as FFIDContextValue, v as FFIDLoginButton, w as FFIDOAuthTokenResponse, x as FFIDOAuthUserInfoMemberRole, y as FFIDOAuthUserInfoSubscription, z as FFIDOrganizationSwitcher, B as FFIDSeatModel, C as FFIDSubscription, D as FFIDSubscriptionBadge, E as FFIDSubscriptionStatus, G as FFIDTokenIntrospectionResponse, H as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, I as UseFFIDAnnouncementsReturn, J as useFFIDAnnouncements } from './index-DHmt43kQ.cjs';
1
+ import { F as FFIDConfig, a as FFIDApiResponse, b as FFIDSessionResponse, c as FFIDError, d as FFIDSubscriptionCheckResponse, e as FFIDOAuthUserInfo, f as FFIDLogger, g as FFIDUser, h as FFIDOrganization, i as FFIDSubscriptionContextValue, j as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, k as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, l as FFIDAnnouncementsLogger } from './index-DEtyiwFZ.cjs';
2
+ export { m as Announcement, n as AnnouncementStatus, o as AnnouncementType, p as FFIDAnnouncementBadge, q as FFIDAnnouncementList, r as FFIDAnnouncementsError, s as FFIDAnnouncementsErrorCode, t as FFIDAnnouncementsServerResponse, u as FFIDContextValue, v as FFIDJwtClaims, w as FFIDLoginButton, x as FFIDOAuthTokenResponse, y as FFIDOAuthUserInfoMemberRole, z as FFIDOAuthUserInfoSubscription, B as FFIDOrganizationSwitcher, C as FFIDSeatModel, D as FFIDSubscription, E as FFIDSubscriptionBadge, G as FFIDSubscriptionStatus, H as FFIDTokenIntrospectionResponse, I as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, J as UseFFIDAnnouncementsReturn, K as useFFIDAnnouncements } from './index-DEtyiwFZ.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, ComponentType, FC } from 'react';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDConfig, a as FFIDApiResponse, b as FFIDSessionResponse, c as FFIDError, d as FFIDSubscriptionCheckResponse, e as FFIDOAuthUserInfo, f as FFIDLogger, g as FFIDUser, h as FFIDOrganization, i as FFIDSubscriptionContextValue, j as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, k as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, l as FFIDAnnouncementsLogger } from './index-DHmt43kQ.js';
2
- export { m as Announcement, n as AnnouncementStatus, o as AnnouncementType, p as FFIDAnnouncementBadge, q as FFIDAnnouncementList, r as FFIDAnnouncementsError, s as FFIDAnnouncementsErrorCode, t as FFIDAnnouncementsServerResponse, u as FFIDContextValue, v as FFIDLoginButton, w as FFIDOAuthTokenResponse, x as FFIDOAuthUserInfoMemberRole, y as FFIDOAuthUserInfoSubscription, z as FFIDOrganizationSwitcher, B as FFIDSeatModel, C as FFIDSubscription, D as FFIDSubscriptionBadge, E as FFIDSubscriptionStatus, G as FFIDTokenIntrospectionResponse, H as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, I as UseFFIDAnnouncementsReturn, J as useFFIDAnnouncements } from './index-DHmt43kQ.js';
1
+ import { F as FFIDConfig, a as FFIDApiResponse, b as FFIDSessionResponse, c as FFIDError, d as FFIDSubscriptionCheckResponse, e as FFIDOAuthUserInfo, f as FFIDLogger, g as FFIDUser, h as FFIDOrganization, i as FFIDSubscriptionContextValue, j as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, k as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, l as FFIDAnnouncementsLogger } from './index-DEtyiwFZ.js';
2
+ export { m as Announcement, n as AnnouncementStatus, o as AnnouncementType, p as FFIDAnnouncementBadge, q as FFIDAnnouncementList, r as FFIDAnnouncementsError, s as FFIDAnnouncementsErrorCode, t as FFIDAnnouncementsServerResponse, u as FFIDContextValue, v as FFIDJwtClaims, w as FFIDLoginButton, x as FFIDOAuthTokenResponse, y as FFIDOAuthUserInfoMemberRole, z as FFIDOAuthUserInfoSubscription, B as FFIDOrganizationSwitcher, C as FFIDSeatModel, D as FFIDSubscription, E as FFIDSubscriptionBadge, G as FFIDSubscriptionStatus, H as FFIDTokenIntrospectionResponse, I as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, J as UseFFIDAnnouncementsReturn, K as useFFIDAnnouncements } from './index-DEtyiwFZ.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, ComponentType, FC } from 'react';
5
5
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useFFIDContext } from './chunk-S2YL5Y4O.js';
2
- export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-S2YL5Y4O.js';
1
+ import { useFFIDContext } from './chunk-YJFOE2PP.js';
2
+ export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-YJFOE2PP.js';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",
@@ -73,6 +73,9 @@
73
73
  "test:coverage": "vitest run --coverage",
74
74
  "prepublishOnly": "npm run build"
75
75
  },
76
+ "dependencies": {
77
+ "jose": "^6.0.0"
78
+ },
76
79
  "peerDependencies": {
77
80
  "react": "^18.0.0 || ^19.0.0",
78
81
  "react-dom": "^18.0.0 || ^19.0.0"