@feelflow/ffid-sdk 1.2.2 → 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,6 +179,191 @@ 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
+ }
237
+
238
+ // src/client/verify-access-token.ts
239
+ var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
240
+ function createVerifyAccessToken(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
+ }
255
+ async function verifyAccessToken(accessToken) {
256
+ if (authMode !== "service-key") {
257
+ return {
258
+ error: createError(
259
+ errorCodes.TOKEN_VERIFICATION_ERROR,
260
+ "verifyAccessToken \u306F service-key \u30E2\u30FC\u30C9\u3067\u306E\u307F\u5229\u7528\u53EF\u80FD\u3067\u3059"
261
+ )
262
+ };
263
+ }
264
+ if (!accessToken || !accessToken.trim()) {
265
+ return {
266
+ error: createError(
267
+ errorCodes.TOKEN_VERIFICATION_ERROR,
268
+ "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093"
269
+ )
270
+ };
271
+ }
272
+ if (verifyStrategy === "jwt") {
273
+ return getJwtVerifier()(accessToken);
274
+ }
275
+ return verifyViaIntrospect(accessToken);
276
+ }
277
+ async function verifyViaIntrospect(accessToken) {
278
+ if (!serviceApiKey) {
279
+ return {
280
+ error: createError(
281
+ errorCodes.TOKEN_VERIFICATION_ERROR,
282
+ "serviceApiKey \u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093"
283
+ )
284
+ };
285
+ }
286
+ const url = `${baseUrl}${OAUTH_INTROSPECT_ENDPOINT}`;
287
+ logger.debug("Verifying access token:", url);
288
+ let response;
289
+ try {
290
+ response = await fetch(url, {
291
+ method: "POST",
292
+ credentials: "omit",
293
+ headers: {
294
+ "Content-Type": "application/x-www-form-urlencoded",
295
+ "X-Service-Api-Key": serviceApiKey
296
+ },
297
+ body: new URLSearchParams({ token: accessToken }).toString()
298
+ });
299
+ } catch (error) {
300
+ logger.error("Network error during token verification:", error);
301
+ return {
302
+ error: {
303
+ code: errorCodes.NETWORK_ERROR,
304
+ message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
305
+ }
306
+ };
307
+ }
308
+ let introspectResponse;
309
+ try {
310
+ introspectResponse = await response.json();
311
+ } catch (parseError) {
312
+ logger.error("Parse error during token verification:", parseError);
313
+ return {
314
+ error: {
315
+ code: errorCodes.PARSE_ERROR,
316
+ message: `\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u4E0D\u6B63\u306A\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F (status: ${response.status})`
317
+ }
318
+ };
319
+ }
320
+ if (!response.ok) {
321
+ const errorBody = introspectResponse;
322
+ return {
323
+ error: {
324
+ code: errorBody.error?.code ?? errorCodes.TOKEN_VERIFICATION_ERROR,
325
+ message: errorBody.error?.message ?? "\u30C8\u30FC\u30AF\u30F3\u691C\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
326
+ }
327
+ };
328
+ }
329
+ if (!introspectResponse.active) {
330
+ return {
331
+ error: {
332
+ code: errorCodes.TOKEN_VERIFICATION_ERROR,
333
+ message: "\u30C8\u30FC\u30AF\u30F3\u304C\u7121\u52B9\u307E\u305F\u306F\u671F\u9650\u5207\u308C\u3067\u3059"
334
+ }
335
+ };
336
+ }
337
+ if (!introspectResponse.sub) {
338
+ logger.error("Active token introspection returned no sub claim");
339
+ return {
340
+ error: {
341
+ code: errorCodes.TOKEN_VERIFICATION_ERROR,
342
+ message: "\u30C8\u30FC\u30AF\u30F3\u691C\u8A3C\u30EC\u30B9\u30DD\u30F3\u30B9\u306B\u30E6\u30FC\u30B6\u30FCID\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u305B\u3093"
343
+ }
344
+ };
345
+ }
346
+ const base = {
347
+ sub: introspectResponse.sub,
348
+ email: introspectResponse.email ?? null,
349
+ name: introspectResponse.name ?? null,
350
+ picture: introspectResponse.picture ?? null,
351
+ organization_id: introspectResponse.organization_id ?? null
352
+ };
353
+ const raw = introspectResponse.subscription ? {
354
+ ...base,
355
+ subscription: {
356
+ status: introspectResponse.subscription.status,
357
+ plan_code: introspectResponse.subscription.plan_code,
358
+ seat_model: introspectResponse.subscription.seat_model,
359
+ member_role: introspectResponse.subscription.member_role,
360
+ organization_id: introspectResponse.subscription.organization_id
361
+ }
362
+ } : base;
363
+ return { data: normalizeUserinfo(raw) };
364
+ }
365
+ return verifyAccessToken;
366
+ }
181
367
 
182
368
  // src/client/ffid-client.ts
183
369
  var NO_CONTENT_STATUS = 204;
@@ -214,7 +400,8 @@ var FFID_ERROR_CODES = {
214
400
  UNKNOWN_ERROR: "UNKNOWN_ERROR",
215
401
  TOKEN_EXCHANGE_ERROR: "TOKEN_EXCHANGE_ERROR",
216
402
  TOKEN_REFRESH_ERROR: "TOKEN_REFRESH_ERROR",
217
- NO_TOKENS: "NO_TOKENS"
403
+ NO_TOKENS: "NO_TOKENS",
404
+ TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
218
405
  };
219
406
  function createFFIDClient(config) {
220
407
  if (!config.serviceCode || !config.serviceCode.trim()) {
@@ -224,6 +411,7 @@ function createFFIDClient(config) {
224
411
  const authMode = config.authMode ?? "cookie";
225
412
  const clientId = config.clientId ?? config.serviceCode;
226
413
  const serviceApiKey = config.serviceApiKey?.trim();
414
+ const verifyStrategy = config.verifyStrategy ?? "jwt";
227
415
  if (authMode === "service-key" && !serviceApiKey) {
228
416
  throw new Error("FFID Client: service-key \u30E2\u30FC\u30C9\u3067\u306F serviceApiKey \u304C\u5FC5\u9808\u3067\u3059");
229
417
  }
@@ -712,6 +900,16 @@ function createFFIDClient(config) {
712
900
  `${EXT_CHECK_ENDPOINT}?${query.toString()}`
713
901
  );
714
902
  }
903
+ const verifyAccessToken = createVerifyAccessToken({
904
+ authMode,
905
+ baseUrl,
906
+ serviceCode: config.serviceCode,
907
+ serviceApiKey,
908
+ verifyStrategy,
909
+ logger,
910
+ createError,
911
+ errorCodes: FFID_ERROR_CODES
912
+ });
715
913
  return {
716
914
  getSession,
717
915
  signOut,
@@ -722,6 +920,7 @@ function createFFIDClient(config) {
722
920
  exchangeCodeForTokens,
723
921
  refreshAccessToken,
724
922
  checkSubscription,
923
+ verifyAccessToken,
725
924
  /** Token store (token mode only) */
726
925
  tokenStore,
727
926
  /** Resolved auth mode */
@@ -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,6 +177,191 @@ 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
+ }
235
+
236
+ // src/client/verify-access-token.ts
237
+ var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
238
+ function createVerifyAccessToken(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
+ }
253
+ async function verifyAccessToken(accessToken) {
254
+ if (authMode !== "service-key") {
255
+ return {
256
+ error: createError(
257
+ errorCodes.TOKEN_VERIFICATION_ERROR,
258
+ "verifyAccessToken \u306F service-key \u30E2\u30FC\u30C9\u3067\u306E\u307F\u5229\u7528\u53EF\u80FD\u3067\u3059"
259
+ )
260
+ };
261
+ }
262
+ if (!accessToken || !accessToken.trim()) {
263
+ return {
264
+ error: createError(
265
+ errorCodes.TOKEN_VERIFICATION_ERROR,
266
+ "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093"
267
+ )
268
+ };
269
+ }
270
+ if (verifyStrategy === "jwt") {
271
+ return getJwtVerifier()(accessToken);
272
+ }
273
+ return verifyViaIntrospect(accessToken);
274
+ }
275
+ async function verifyViaIntrospect(accessToken) {
276
+ if (!serviceApiKey) {
277
+ return {
278
+ error: createError(
279
+ errorCodes.TOKEN_VERIFICATION_ERROR,
280
+ "serviceApiKey \u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093"
281
+ )
282
+ };
283
+ }
284
+ const url = `${baseUrl}${OAUTH_INTROSPECT_ENDPOINT}`;
285
+ logger.debug("Verifying access token:", url);
286
+ let response;
287
+ try {
288
+ response = await fetch(url, {
289
+ method: "POST",
290
+ credentials: "omit",
291
+ headers: {
292
+ "Content-Type": "application/x-www-form-urlencoded",
293
+ "X-Service-Api-Key": serviceApiKey
294
+ },
295
+ body: new URLSearchParams({ token: accessToken }).toString()
296
+ });
297
+ } catch (error) {
298
+ logger.error("Network error during token verification:", error);
299
+ return {
300
+ error: {
301
+ code: errorCodes.NETWORK_ERROR,
302
+ message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
303
+ }
304
+ };
305
+ }
306
+ let introspectResponse;
307
+ try {
308
+ introspectResponse = await response.json();
309
+ } catch (parseError) {
310
+ logger.error("Parse error during token verification:", parseError);
311
+ return {
312
+ error: {
313
+ code: errorCodes.PARSE_ERROR,
314
+ message: `\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u4E0D\u6B63\u306A\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F (status: ${response.status})`
315
+ }
316
+ };
317
+ }
318
+ if (!response.ok) {
319
+ const errorBody = introspectResponse;
320
+ return {
321
+ error: {
322
+ code: errorBody.error?.code ?? errorCodes.TOKEN_VERIFICATION_ERROR,
323
+ message: errorBody.error?.message ?? "\u30C8\u30FC\u30AF\u30F3\u691C\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
324
+ }
325
+ };
326
+ }
327
+ if (!introspectResponse.active) {
328
+ return {
329
+ error: {
330
+ code: errorCodes.TOKEN_VERIFICATION_ERROR,
331
+ message: "\u30C8\u30FC\u30AF\u30F3\u304C\u7121\u52B9\u307E\u305F\u306F\u671F\u9650\u5207\u308C\u3067\u3059"
332
+ }
333
+ };
334
+ }
335
+ if (!introspectResponse.sub) {
336
+ logger.error("Active token introspection returned no sub claim");
337
+ return {
338
+ error: {
339
+ code: errorCodes.TOKEN_VERIFICATION_ERROR,
340
+ message: "\u30C8\u30FC\u30AF\u30F3\u691C\u8A3C\u30EC\u30B9\u30DD\u30F3\u30B9\u306B\u30E6\u30FC\u30B6\u30FCID\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u305B\u3093"
341
+ }
342
+ };
343
+ }
344
+ const base = {
345
+ sub: introspectResponse.sub,
346
+ email: introspectResponse.email ?? null,
347
+ name: introspectResponse.name ?? null,
348
+ picture: introspectResponse.picture ?? null,
349
+ organization_id: introspectResponse.organization_id ?? null
350
+ };
351
+ const raw = introspectResponse.subscription ? {
352
+ ...base,
353
+ subscription: {
354
+ status: introspectResponse.subscription.status,
355
+ plan_code: introspectResponse.subscription.plan_code,
356
+ seat_model: introspectResponse.subscription.seat_model,
357
+ member_role: introspectResponse.subscription.member_role,
358
+ organization_id: introspectResponse.subscription.organization_id
359
+ }
360
+ } : base;
361
+ return { data: normalizeUserinfo(raw) };
362
+ }
363
+ return verifyAccessToken;
364
+ }
179
365
 
180
366
  // src/client/ffid-client.ts
181
367
  var NO_CONTENT_STATUS = 204;
@@ -212,7 +398,8 @@ var FFID_ERROR_CODES = {
212
398
  UNKNOWN_ERROR: "UNKNOWN_ERROR",
213
399
  TOKEN_EXCHANGE_ERROR: "TOKEN_EXCHANGE_ERROR",
214
400
  TOKEN_REFRESH_ERROR: "TOKEN_REFRESH_ERROR",
215
- NO_TOKENS: "NO_TOKENS"
401
+ NO_TOKENS: "NO_TOKENS",
402
+ TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
216
403
  };
217
404
  function createFFIDClient(config) {
218
405
  if (!config.serviceCode || !config.serviceCode.trim()) {
@@ -222,6 +409,7 @@ function createFFIDClient(config) {
222
409
  const authMode = config.authMode ?? "cookie";
223
410
  const clientId = config.clientId ?? config.serviceCode;
224
411
  const serviceApiKey = config.serviceApiKey?.trim();
412
+ const verifyStrategy = config.verifyStrategy ?? "jwt";
225
413
  if (authMode === "service-key" && !serviceApiKey) {
226
414
  throw new Error("FFID Client: service-key \u30E2\u30FC\u30C9\u3067\u306F serviceApiKey \u304C\u5FC5\u9808\u3067\u3059");
227
415
  }
@@ -710,6 +898,16 @@ function createFFIDClient(config) {
710
898
  `${EXT_CHECK_ENDPOINT}?${query.toString()}`
711
899
  );
712
900
  }
901
+ const verifyAccessToken = createVerifyAccessToken({
902
+ authMode,
903
+ baseUrl,
904
+ serviceCode: config.serviceCode,
905
+ serviceApiKey,
906
+ verifyStrategy,
907
+ logger,
908
+ createError,
909
+ errorCodes: FFID_ERROR_CODES
910
+ });
713
911
  return {
714
912
  getSession,
715
913
  signOut,
@@ -720,6 +918,7 @@ function createFFIDClient(config) {
720
918
  exchangeCodeForTokens,
721
919
  refreshAccessToken,
722
920
  checkSubscription,
921
+ verifyAccessToken,
723
922
  /** Token store (token mode only) */
724
923
  tokenStore,
725
924
  /** Resolved auth mode */
@@ -1,30 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var chunk2IGDU2LY_cjs = require('../chunk-2IGDU2LY.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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_cjs.FFIDUserMenu; }
29
+ get: function () { return chunkUBQEG3CS_cjs.FFIDUserMenu; }
30
30
  });
@@ -1,3 +1,3 @@
1
- export { o as FFIDAnnouncementBadge, J as FFIDAnnouncementBadgeClassNames, K as FFIDAnnouncementBadgeProps, p as FFIDAnnouncementList, M as FFIDAnnouncementListClassNames, N as FFIDAnnouncementListProps, u as FFIDLoginButton, O as FFIDLoginButtonProps, z as FFIDOrganizationSwitcher, P as FFIDOrganizationSwitcherClassNames, Q as FFIDOrganizationSwitcherProps, D as FFIDSubscriptionBadge, R as FFIDSubscriptionBadgeClassNames, S as FFIDSubscriptionBadgeProps, G as FFIDUserMenu, T as FFIDUserMenuClassNames, V as FFIDUserMenuProps } from '../index-Bzwet6m2.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 { o as FFIDAnnouncementBadge, J as FFIDAnnouncementBadgeClassNames, K as FFIDAnnouncementBadgeProps, p as FFIDAnnouncementList, M as FFIDAnnouncementListClassNames, N as FFIDAnnouncementListProps, u as FFIDLoginButton, O as FFIDLoginButtonProps, z as FFIDOrganizationSwitcher, P as FFIDOrganizationSwitcherClassNames, Q as FFIDOrganizationSwitcherProps, D as FFIDSubscriptionBadge, R as FFIDSubscriptionBadgeClassNames, S as FFIDSubscriptionBadgeProps, G as FFIDUserMenu, T as FFIDUserMenuClassNames, V as FFIDUserMenuProps } from '../index-Bzwet6m2.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-FZWW3B4X.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-YJFOE2PP.js';
@@ -9,7 +9,7 @@ import { ButtonHTMLAttributes, ReactNode, CSSProperties } from 'react';
9
9
  /**
10
10
  * User information from FFID
11
11
  */
12
- type FFIDSeatModel = 'organization' | 'individual';
12
+ type FFIDSeatModel = 'organization';
13
13
  /** Userinfo member role for OAuth responses */
14
14
  type FFIDOAuthUserInfoMemberRole = 'owner' | 'admin' | 'member' | 'viewer';
15
15
  interface FFIDUser {
@@ -104,8 +104,8 @@ interface FFIDOAuthUserInfo {
104
104
  email: string | null;
105
105
  name: string | null;
106
106
  picture: string | null;
107
- organizationId?: string | null;
108
- subscription?: FFIDOAuthUserInfoSubscription;
107
+ organizationId?: string | null | undefined;
108
+ subscription?: FFIDOAuthUserInfoSubscription | undefined;
109
109
  }
110
110
  /**
111
111
  * SDK configuration options
@@ -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
@@ -256,6 +292,35 @@ interface FFIDOAuthTokenResponse {
256
292
  expires_in: number;
257
293
  refresh_token: string;
258
294
  }
295
+ /**
296
+ * RFC 7662 Token Introspection response (raw format from server)
297
+ *
298
+ * Used internally by verifyAccessToken(). Consumers receive the normalized
299
+ * FFIDOAuthUserInfo type instead.
300
+ *
301
+ * @see https://tools.ietf.org/html/rfc7662
302
+ */
303
+ interface FFIDTokenIntrospectionResponse {
304
+ active: boolean;
305
+ sub?: string;
306
+ email?: string;
307
+ name?: string;
308
+ picture?: string | null;
309
+ scope?: string | null;
310
+ exp?: number;
311
+ iat?: number;
312
+ iss?: string;
313
+ token_type?: 'Bearer';
314
+ client_id?: string;
315
+ organization_id?: string | null;
316
+ subscription?: {
317
+ status: FFIDOAuthUserInfoSubscription['status'];
318
+ plan_code: string | null;
319
+ seat_model: FFIDOAuthUserInfoSubscription['seatModel'];
320
+ member_role: FFIDOAuthUserInfoSubscription['memberRole'];
321
+ organization_id: string | null;
322
+ };
323
+ }
259
324
 
260
325
  /**
261
326
  * FFID Announcements SDK Type Definitions
@@ -618,4 +683,4 @@ interface FFIDAnnouncementListProps {
618
683
  */
619
684
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
620
685
 
621
- export { type AnnouncementListResponse as A, type FFIDSeatModel as B, type FFIDSubscription as C, FFIDSubscriptionBadge as D, type FFIDSubscriptionStatus as E, type FFIDConfig as F, FFIDUserMenu as G, type UseFFIDAnnouncementsReturn as H, useFFIDAnnouncements as I, type FFIDAnnouncementBadgeClassNames as J, type FFIDAnnouncementBadgeProps as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementListClassNames as M, type FFIDAnnouncementListProps as N, type FFIDLoginButtonProps as O, type FFIDOrganizationSwitcherClassNames as P, type FFIDOrganizationSwitcherProps as Q, type FFIDSubscriptionBadgeClassNames as R, type FFIDSubscriptionBadgeProps as S, type FFIDUserMenuClassNames as T, type UseFFIDAnnouncementsOptions as U, type FFIDUserMenuProps as V, type FFIDApiResponse as a, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDLogger as e, type FFIDUser as f, type FFIDOrganization as g, type FFIDSubscriptionContextValue as h, type FFIDAnnouncementsClientConfig as i, type FFIDAnnouncementsApiResponse as j, type FFIDAnnouncementsLogger as k, type Announcement as l, type AnnouncementStatus as m, type AnnouncementType as n, FFIDAnnouncementBadge as o, FFIDAnnouncementList as p, type FFIDAnnouncementsError as q, type FFIDAnnouncementsErrorCode as r, type FFIDAnnouncementsServerResponse as s, type FFIDContextValue as t, FFIDLoginButton as u, type FFIDOAuthTokenResponse as v, type FFIDOAuthUserInfo 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 };
@@ -9,7 +9,7 @@ import { ButtonHTMLAttributes, ReactNode, CSSProperties } from 'react';
9
9
  /**
10
10
  * User information from FFID
11
11
  */
12
- type FFIDSeatModel = 'organization' | 'individual';
12
+ type FFIDSeatModel = 'organization';
13
13
  /** Userinfo member role for OAuth responses */
14
14
  type FFIDOAuthUserInfoMemberRole = 'owner' | 'admin' | 'member' | 'viewer';
15
15
  interface FFIDUser {
@@ -104,8 +104,8 @@ interface FFIDOAuthUserInfo {
104
104
  email: string | null;
105
105
  name: string | null;
106
106
  picture: string | null;
107
- organizationId?: string | null;
108
- subscription?: FFIDOAuthUserInfoSubscription;
107
+ organizationId?: string | null | undefined;
108
+ subscription?: FFIDOAuthUserInfoSubscription | undefined;
109
109
  }
110
110
  /**
111
111
  * SDK configuration options
@@ -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
@@ -256,6 +292,35 @@ interface FFIDOAuthTokenResponse {
256
292
  expires_in: number;
257
293
  refresh_token: string;
258
294
  }
295
+ /**
296
+ * RFC 7662 Token Introspection response (raw format from server)
297
+ *
298
+ * Used internally by verifyAccessToken(). Consumers receive the normalized
299
+ * FFIDOAuthUserInfo type instead.
300
+ *
301
+ * @see https://tools.ietf.org/html/rfc7662
302
+ */
303
+ interface FFIDTokenIntrospectionResponse {
304
+ active: boolean;
305
+ sub?: string;
306
+ email?: string;
307
+ name?: string;
308
+ picture?: string | null;
309
+ scope?: string | null;
310
+ exp?: number;
311
+ iat?: number;
312
+ iss?: string;
313
+ token_type?: 'Bearer';
314
+ client_id?: string;
315
+ organization_id?: string | null;
316
+ subscription?: {
317
+ status: FFIDOAuthUserInfoSubscription['status'];
318
+ plan_code: string | null;
319
+ seat_model: FFIDOAuthUserInfoSubscription['seatModel'];
320
+ member_role: FFIDOAuthUserInfoSubscription['memberRole'];
321
+ organization_id: string | null;
322
+ };
323
+ }
259
324
 
260
325
  /**
261
326
  * FFID Announcements SDK Type Definitions
@@ -618,4 +683,4 @@ interface FFIDAnnouncementListProps {
618
683
  */
619
684
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
620
685
 
621
- export { type AnnouncementListResponse as A, type FFIDSeatModel as B, type FFIDSubscription as C, FFIDSubscriptionBadge as D, type FFIDSubscriptionStatus as E, type FFIDConfig as F, FFIDUserMenu as G, type UseFFIDAnnouncementsReturn as H, useFFIDAnnouncements as I, type FFIDAnnouncementBadgeClassNames as J, type FFIDAnnouncementBadgeProps as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementListClassNames as M, type FFIDAnnouncementListProps as N, type FFIDLoginButtonProps as O, type FFIDOrganizationSwitcherClassNames as P, type FFIDOrganizationSwitcherProps as Q, type FFIDSubscriptionBadgeClassNames as R, type FFIDSubscriptionBadgeProps as S, type FFIDUserMenuClassNames as T, type UseFFIDAnnouncementsOptions as U, type FFIDUserMenuProps as V, type FFIDApiResponse as a, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDLogger as e, type FFIDUser as f, type FFIDOrganization as g, type FFIDSubscriptionContextValue as h, type FFIDAnnouncementsClientConfig as i, type FFIDAnnouncementsApiResponse as j, type FFIDAnnouncementsLogger as k, type Announcement as l, type AnnouncementStatus as m, type AnnouncementType as n, FFIDAnnouncementBadge as o, FFIDAnnouncementList as p, type FFIDAnnouncementsError as q, type FFIDAnnouncementsErrorCode as r, type FFIDAnnouncementsServerResponse as s, type FFIDContextValue as t, FFIDLoginButton as u, type FFIDOAuthTokenResponse as v, type FFIDOAuthUserInfo 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 chunk2IGDU2LY_cjs = require('./chunk-2IGDU2LY.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 } = chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 chunk2IGDU2LY_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 FFIDLogger, f as FFIDUser, g as FFIDOrganization, h as FFIDSubscriptionContextValue, i as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, j as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, k as FFIDAnnouncementsLogger } from './index-Bzwet6m2.cjs';
2
- export { l as Announcement, m as AnnouncementStatus, n as AnnouncementType, o as FFIDAnnouncementBadge, p as FFIDAnnouncementList, q as FFIDAnnouncementsError, r as FFIDAnnouncementsErrorCode, s as FFIDAnnouncementsServerResponse, t as FFIDContextValue, u as FFIDLoginButton, v as FFIDOAuthTokenResponse, w as FFIDOAuthUserInfo, x as FFIDOAuthUserInfoMemberRole, y as FFIDOAuthUserInfoSubscription, z as FFIDOrganizationSwitcher, B as FFIDSeatModel, C as FFIDSubscription, D as FFIDSubscriptionBadge, E as FFIDSubscriptionStatus, G as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, H as UseFFIDAnnouncementsReturn, I as useFFIDAnnouncements } from './index-Bzwet6m2.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
 
@@ -84,8 +84,6 @@ declare function storeCodeVerifier(verifier: string): void;
84
84
  */
85
85
  declare function retrieveCodeVerifier(): string | null;
86
86
 
87
- /** FFID API Client - Supports cookie, token, and service-key auth modes */
88
-
89
87
  /** Creates an FFID API client instance */
90
88
  declare function createFFIDClient(config: FFIDConfig): {
91
89
  getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
@@ -100,6 +98,7 @@ declare function createFFIDClient(config: FFIDConfig): {
100
98
  userId: string;
101
99
  organizationId: string;
102
100
  }) => Promise<FFIDApiResponse<FFIDSubscriptionCheckResponse>>;
101
+ verifyAccessToken: (accessToken: string) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
103
102
  /** Token store (token mode only) */
104
103
  tokenStore: TokenStore;
105
104
  /** Resolved auth mode */
@@ -339,4 +338,4 @@ declare function createFFIDAnnouncementsClient(config?: FFIDAnnouncementsClientC
339
338
  /** Type of the FFID Announcements client */
340
339
  type FFIDAnnouncementsClient = ReturnType<typeof createFFIDAnnouncementsClient>;
341
340
 
342
- export { AnnouncementListResponse, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDClient, FFIDConfig, FFIDError, FFIDLogger, FFIDOrganization, FFIDProvider, type FFIDProviderProps, FFIDSessionResponse, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, FFIDUser, FFID_ANNOUNCEMENTS_ERROR_CODES, ListAnnouncementsOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
341
+ export { AnnouncementListResponse, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDClient, FFIDConfig, FFIDError, FFIDLogger, FFIDOAuthUserInfo, FFIDOrganization, FFIDProvider, type FFIDProviderProps, FFIDSessionResponse, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, FFIDUser, FFID_ANNOUNCEMENTS_ERROR_CODES, ListAnnouncementsOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
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 FFIDLogger, f as FFIDUser, g as FFIDOrganization, h as FFIDSubscriptionContextValue, i as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, j as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, k as FFIDAnnouncementsLogger } from './index-Bzwet6m2.js';
2
- export { l as Announcement, m as AnnouncementStatus, n as AnnouncementType, o as FFIDAnnouncementBadge, p as FFIDAnnouncementList, q as FFIDAnnouncementsError, r as FFIDAnnouncementsErrorCode, s as FFIDAnnouncementsServerResponse, t as FFIDContextValue, u as FFIDLoginButton, v as FFIDOAuthTokenResponse, w as FFIDOAuthUserInfo, x as FFIDOAuthUserInfoMemberRole, y as FFIDOAuthUserInfoSubscription, z as FFIDOrganizationSwitcher, B as FFIDSeatModel, C as FFIDSubscription, D as FFIDSubscriptionBadge, E as FFIDSubscriptionStatus, G as FFIDUserMenu, U as UseFFIDAnnouncementsOptions, H as UseFFIDAnnouncementsReturn, I as useFFIDAnnouncements } from './index-Bzwet6m2.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
 
@@ -84,8 +84,6 @@ declare function storeCodeVerifier(verifier: string): void;
84
84
  */
85
85
  declare function retrieveCodeVerifier(): string | null;
86
86
 
87
- /** FFID API Client - Supports cookie, token, and service-key auth modes */
88
-
89
87
  /** Creates an FFID API client instance */
90
88
  declare function createFFIDClient(config: FFIDConfig): {
91
89
  getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
@@ -100,6 +98,7 @@ declare function createFFIDClient(config: FFIDConfig): {
100
98
  userId: string;
101
99
  organizationId: string;
102
100
  }) => Promise<FFIDApiResponse<FFIDSubscriptionCheckResponse>>;
101
+ verifyAccessToken: (accessToken: string) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
103
102
  /** Token store (token mode only) */
104
103
  tokenStore: TokenStore;
105
104
  /** Resolved auth mode */
@@ -339,4 +338,4 @@ declare function createFFIDAnnouncementsClient(config?: FFIDAnnouncementsClientC
339
338
  /** Type of the FFID Announcements client */
340
339
  type FFIDAnnouncementsClient = ReturnType<typeof createFFIDAnnouncementsClient>;
341
340
 
342
- export { AnnouncementListResponse, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDClient, FFIDConfig, FFIDError, FFIDLogger, FFIDOrganization, FFIDProvider, type FFIDProviderProps, FFIDSessionResponse, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, FFIDUser, FFID_ANNOUNCEMENTS_ERROR_CODES, ListAnnouncementsOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
341
+ export { AnnouncementListResponse, DEFAULT_API_BASE_URL, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDClient, FFIDConfig, FFIDError, FFIDLogger, FFIDOAuthUserInfo, FFIDOrganization, FFIDProvider, type FFIDProviderProps, FFIDSessionResponse, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, FFIDUser, FFID_ANNOUNCEMENTS_ERROR_CODES, ListAnnouncementsOptions, type TokenData, type TokenStore, type UseFFIDReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, retrieveCodeVerifier, storeCodeVerifier, useFFID, useSubscription, withFFIDAuth, withSubscription };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useFFIDContext } from './chunk-FZWW3B4X.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-FZWW3B4X.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.2.2",
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"