@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.
- package/dist/{chunk-2IGDU2LY.cjs → chunk-UBQEG3CS.cjs} +200 -1
- package/dist/{chunk-FZWW3B4X.js → chunk-YJFOE2PP.js} +200 -1
- package/dist/components/index.cjs +7 -7
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{index-Bzwet6m2.d.cts → index-DEtyiwFZ.d.cts} +69 -4
- package/dist/{index-Bzwet6m2.d.ts → index-DEtyiwFZ.d.ts} +69 -4
- package/dist/index.cjs +22 -22
- package/dist/index.d.cts +4 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +2 -2
- package/package.json +4 -1
|
@@ -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
|
|
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
|
|
9
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementBadge; }
|
|
10
10
|
});
|
|
11
11
|
Object.defineProperty(exports, "FFIDAnnouncementList", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementList; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "FFIDLoginButton", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDLoginButton; }
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
|
|
20
20
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
21
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDOrganizationSwitcher; }
|
|
22
22
|
});
|
|
23
23
|
Object.defineProperty(exports, "FFIDSubscriptionBadge", {
|
|
24
24
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
25
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDSubscriptionBadge; }
|
|
26
26
|
});
|
|
27
27
|
Object.defineProperty(exports, "FFIDUserMenu", {
|
|
28
28
|
enumerable: true,
|
|
29
|
-
get: function () { return
|
|
29
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDUserMenu; }
|
|
30
30
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
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 {
|
|
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';
|
package/dist/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-
|
|
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'
|
|
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,
|
|
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'
|
|
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,
|
|
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
|
|
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 } =
|
|
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
|
|
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
|
|
38
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementBadge; }
|
|
39
39
|
});
|
|
40
40
|
Object.defineProperty(exports, "FFIDAnnouncementList", {
|
|
41
41
|
enumerable: true,
|
|
42
|
-
get: function () { return
|
|
42
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDAnnouncementList; }
|
|
43
43
|
});
|
|
44
44
|
Object.defineProperty(exports, "FFIDLoginButton", {
|
|
45
45
|
enumerable: true,
|
|
46
|
-
get: function () { return
|
|
46
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDLoginButton; }
|
|
47
47
|
});
|
|
48
48
|
Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
|
|
49
49
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
50
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDOrganizationSwitcher; }
|
|
51
51
|
});
|
|
52
52
|
Object.defineProperty(exports, "FFIDProvider", {
|
|
53
53
|
enumerable: true,
|
|
54
|
-
get: function () { return
|
|
54
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDProvider; }
|
|
55
55
|
});
|
|
56
56
|
Object.defineProperty(exports, "FFIDSubscriptionBadge", {
|
|
57
57
|
enumerable: true,
|
|
58
|
-
get: function () { return
|
|
58
|
+
get: function () { return chunkUBQEG3CS_cjs.FFIDSubscriptionBadge; }
|
|
59
59
|
});
|
|
60
60
|
Object.defineProperty(exports, "FFIDUserMenu", {
|
|
61
61
|
enumerable: true,
|
|
62
|
-
get: function () { return
|
|
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
|
|
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
|
|
70
|
+
get: function () { return chunkUBQEG3CS_cjs.createFFIDAnnouncementsClient; }
|
|
71
71
|
});
|
|
72
72
|
Object.defineProperty(exports, "createFFIDClient", {
|
|
73
73
|
enumerable: true,
|
|
74
|
-
get: function () { return
|
|
74
|
+
get: function () { return chunkUBQEG3CS_cjs.createFFIDClient; }
|
|
75
75
|
});
|
|
76
76
|
Object.defineProperty(exports, "createTokenStore", {
|
|
77
77
|
enumerable: true,
|
|
78
|
-
get: function () { return
|
|
78
|
+
get: function () { return chunkUBQEG3CS_cjs.createTokenStore; }
|
|
79
79
|
});
|
|
80
80
|
Object.defineProperty(exports, "generateCodeChallenge", {
|
|
81
81
|
enumerable: true,
|
|
82
|
-
get: function () { return
|
|
82
|
+
get: function () { return chunkUBQEG3CS_cjs.generateCodeChallenge; }
|
|
83
83
|
});
|
|
84
84
|
Object.defineProperty(exports, "generateCodeVerifier", {
|
|
85
85
|
enumerable: true,
|
|
86
|
-
get: function () { return
|
|
86
|
+
get: function () { return chunkUBQEG3CS_cjs.generateCodeVerifier; }
|
|
87
87
|
});
|
|
88
88
|
Object.defineProperty(exports, "retrieveCodeVerifier", {
|
|
89
89
|
enumerable: true,
|
|
90
|
-
get: function () { return
|
|
90
|
+
get: function () { return chunkUBQEG3CS_cjs.retrieveCodeVerifier; }
|
|
91
91
|
});
|
|
92
92
|
Object.defineProperty(exports, "storeCodeVerifier", {
|
|
93
93
|
enumerable: true,
|
|
94
|
-
get: function () { return
|
|
94
|
+
get: function () { return chunkUBQEG3CS_cjs.storeCodeVerifier; }
|
|
95
95
|
});
|
|
96
96
|
Object.defineProperty(exports, "useFFID", {
|
|
97
97
|
enumerable: true,
|
|
98
|
-
get: function () { return
|
|
98
|
+
get: function () { return chunkUBQEG3CS_cjs.useFFID; }
|
|
99
99
|
});
|
|
100
100
|
Object.defineProperty(exports, "useFFIDAnnouncements", {
|
|
101
101
|
enumerable: true,
|
|
102
|
-
get: function () { return
|
|
102
|
+
get: function () { return chunkUBQEG3CS_cjs.useFFIDAnnouncements; }
|
|
103
103
|
});
|
|
104
104
|
Object.defineProperty(exports, "useSubscription", {
|
|
105
105
|
enumerable: true,
|
|
106
|
-
get: function () { return
|
|
106
|
+
get: function () { return chunkUBQEG3CS_cjs.useSubscription; }
|
|
107
107
|
});
|
|
108
108
|
Object.defineProperty(exports, "withSubscription", {
|
|
109
109
|
enumerable: true,
|
|
110
|
-
get: function () { return
|
|
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
|
|
2
|
-
export {
|
|
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
|
|
2
|
-
export {
|
|
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-
|
|
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-
|
|
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.
|
|
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"
|