@c1m-public/platform-auth 0.8.2 → 0.8.4
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-GQ36R3RQ.js → chunk-Q7YI7RMG.js} +13 -3
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1 -1
- package/dist/next.d.ts +11 -6
- package/dist/next.js +15 -14
- package/package.json +1 -1
|
@@ -308,6 +308,16 @@ function createHandoffSource(config) {
|
|
|
308
308
|
// src/session-refresh.ts
|
|
309
309
|
var DEFAULT_TTL_MS = 5e3;
|
|
310
310
|
var DEFAULT_MAX = 1e3;
|
|
311
|
+
function parseRefreshEnvelope(value) {
|
|
312
|
+
if (!value || typeof value !== "object") return null;
|
|
313
|
+
const outer = value;
|
|
314
|
+
const payload = outer.data && typeof outer.data === "object" ? outer.data : value;
|
|
315
|
+
if (typeof payload.access_token !== "string" || !payload.access_token) return null;
|
|
316
|
+
return {
|
|
317
|
+
accessToken: payload.access_token,
|
|
318
|
+
refreshToken: typeof payload.refresh_token === "string" && payload.refresh_token ? payload.refresh_token : void 0
|
|
319
|
+
};
|
|
320
|
+
}
|
|
311
321
|
function createSessionRefresher(config) {
|
|
312
322
|
const ttl = config.singleflightTtlMs ?? DEFAULT_TTL_MS;
|
|
313
323
|
const max = config.maxSingleflights ?? DEFAULT_MAX;
|
|
@@ -330,8 +340,8 @@ function createSessionRefresher(config) {
|
|
|
330
340
|
fetch: config.fetch
|
|
331
341
|
});
|
|
332
342
|
if (!response.ok) return null;
|
|
333
|
-
const
|
|
334
|
-
return
|
|
343
|
+
const refreshed = parseRefreshEnvelope(await response.json());
|
|
344
|
+
return refreshed && hasTokenAudience(refreshed.accessToken, config.audience) ? refreshed : null;
|
|
335
345
|
} catch {
|
|
336
346
|
return null;
|
|
337
347
|
}
|
|
@@ -391,4 +401,4 @@ async function evaluateSessionGate(input) {
|
|
|
391
401
|
return { kind: "redirect_login" };
|
|
392
402
|
}
|
|
393
403
|
|
|
394
|
-
export { AUTH_ERROR_MESSAGES, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, SSO_ERROR_MESSAGES, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, isAuthErrorCode, isHandoffErrorCode, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath };
|
|
404
|
+
export { AUTH_ERROR_MESSAGES, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, SSO_ERROR_MESSAGES, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, isAuthErrorCode, isHandoffErrorCode, parseRefreshEnvelope, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath };
|
package/dist/index.d.ts
CHANGED
|
@@ -189,6 +189,13 @@ interface SessionRefresherConfig {
|
|
|
189
189
|
fetchTimeoutMs?: number;
|
|
190
190
|
fetch?: typeof fetch;
|
|
191
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Two refresh envelopes exist: the platform one (flat, with token_type and
|
|
194
|
+
* expires_at) and the end-user one (`{ data: { access_token, refresh_token? } }`,
|
|
195
|
+
* where a rotated refresh token is optional). Both carry the access token the
|
|
196
|
+
* same way; that is all a refresh needs.
|
|
197
|
+
*/
|
|
198
|
+
declare function parseRefreshEnvelope(value: unknown): RefreshedSession | null;
|
|
192
199
|
declare function createSessionRefresher(config: SessionRefresherConfig): {
|
|
193
200
|
refresh(refreshToken: string): Promise<RefreshedSession | null>;
|
|
194
201
|
size(): number;
|
|
@@ -221,4 +228,4 @@ interface SessionGateInput {
|
|
|
221
228
|
}
|
|
222
229
|
declare function evaluateSessionGate(input: SessionGateInput): Promise<SessionGateDecision>;
|
|
223
230
|
|
|
224
|
-
export { AUTH_ERROR_MESSAGES, type AuthResponse, type CookieOptions, type DeviceIdentity, type DeviceIdentityConfig, type DeviceIdentityStore, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, type HandoffSource, type HandoffSourceConfig, type HandoffSourceTarget, type HandoffTarget, type HandoffTargetConfig, type RefreshedSession, SSO_ERROR_MESSAGES, type SessionData, type SessionGateDecision, type SessionGateInput, type SessionRefresher, type SessionRefresherConfig, type SessionUser, type TokenPayload, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, decodeBase64Url, decodeDefaultSession, decodeTokenPayload, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, hasTokenAudience, isAuthErrorCode, isHandoffErrorCode, isTokenExpired, isTokenExpiringSoon, parseAuthResponse, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath, tokenMaxAgeSeconds };
|
|
231
|
+
export { AUTH_ERROR_MESSAGES, type AuthResponse, type CookieOptions, type DeviceIdentity, type DeviceIdentityConfig, type DeviceIdentityStore, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, type HandoffSource, type HandoffSourceConfig, type HandoffSourceTarget, type HandoffTarget, type HandoffTargetConfig, type RefreshedSession, SSO_ERROR_MESSAGES, type SessionData, type SessionGateDecision, type SessionGateInput, type SessionRefresher, type SessionRefresherConfig, type SessionUser, type TokenPayload, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, decodeBase64Url, decodeDefaultSession, decodeTokenPayload, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, hasTokenAudience, isAuthErrorCode, isHandoffErrorCode, isTokenExpired, isTokenExpiringSoon, parseAuthResponse, parseRefreshEnvelope, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath, tokenMaxAgeSeconds };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { AUTH_ERROR_MESSAGES, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, SSO_ERROR_MESSAGES, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, isAuthErrorCode, isHandoffErrorCode, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath } from './chunk-
|
|
1
|
+
export { AUTH_ERROR_MESSAGES, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, SSO_ERROR_MESSAGES, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, isAuthErrorCode, isHandoffErrorCode, parseRefreshEnvelope, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath } from './chunk-Q7YI7RMG.js';
|
|
2
2
|
export { decodeBase64Url, decodeDefaultSession, decodeTokenPayload, hasTokenAudience, isTokenExpired, isTokenExpiringSoon, parseAuthResponse, tokenMaxAgeSeconds } from './chunk-FBC2NUH7.js';
|
|
3
3
|
export { applyForwardedClientHeaders, forwardedRequestHeaders } from './chunk-ZWSJVE5S.js';
|
package/dist/next.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SessionData, CookieOptions } from './index.js';
|
|
2
|
-
export { AUTH_ERROR_MESSAGES, AuthResponse, DeviceIdentity, DeviceIdentityConfig, DeviceIdentityStore, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, HandoffSource, HandoffSourceConfig, HandoffSourceTarget, HandoffTarget, HandoffTargetConfig, RefreshedSession, SSO_ERROR_MESSAGES, SessionGateDecision, SessionGateInput, SessionRefresher, SessionRefresherConfig, SessionUser, TokenPayload, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, decodeBase64Url, decodeDefaultSession, decodeTokenPayload, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, hasTokenAudience, isAuthErrorCode, isHandoffErrorCode, isTokenExpired, isTokenExpiringSoon, parseAuthResponse, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath, tokenMaxAgeSeconds } from './index.js';
|
|
2
|
+
export { AUTH_ERROR_MESSAGES, AuthResponse, DeviceIdentity, DeviceIdentityConfig, DeviceIdentityStore, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, HandoffSource, HandoffSourceConfig, HandoffSourceTarget, HandoffTarget, HandoffTargetConfig, RefreshedSession, SSO_ERROR_MESSAGES, SessionGateDecision, SessionGateInput, SessionRefresher, SessionRefresherConfig, SessionUser, TokenPayload, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, decodeBase64Url, decodeDefaultSession, decodeTokenPayload, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, hasTokenAudience, isAuthErrorCode, isHandoffErrorCode, isTokenExpired, isTokenExpiringSoon, parseAuthResponse, parseRefreshEnvelope, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath, tokenMaxAgeSeconds } from './index.js';
|
|
3
3
|
export { applyForwardedClientHeaders, forwardedRequestHeaders } from '@c1m-public/transport';
|
|
4
4
|
import { R as Resolvable, A as AsyncResolvable } from './internal-D6RafCm2.js';
|
|
5
5
|
|
|
@@ -128,6 +128,11 @@ interface SessionStoreConfig {
|
|
|
128
128
|
/** Called when a cookie read/write fails outside a request (prerender); default swallows. */
|
|
129
129
|
onError?: (error: unknown, operation: string) => void;
|
|
130
130
|
}
|
|
131
|
+
/** Per-call overrides: a multi-host surface picks the cookie domain per request. */
|
|
132
|
+
interface SessionWriteOptions {
|
|
133
|
+
/** Ignored for `__Host-` names, which forbid Domain. */
|
|
134
|
+
cookieDomain?: string;
|
|
135
|
+
}
|
|
131
136
|
/**
|
|
132
137
|
* Session cookies for a first-party Next.js platform surface, written once.
|
|
133
138
|
*
|
|
@@ -148,24 +153,24 @@ interface SessionStoreConfig {
|
|
|
148
153
|
declare function createSessionStore(config: SessionStoreConfig): {
|
|
149
154
|
audience: string;
|
|
150
155
|
cookieNames: SessionCookieNames;
|
|
151
|
-
cookieOptions: (rememberMe: boolean, token?: string) => CookieOptions & {
|
|
156
|
+
cookieOptions: (rememberMe: boolean, token?: string, options?: SessionWriteOptions) => CookieOptions & {
|
|
152
157
|
httpOnly: true;
|
|
153
158
|
sameSite: "lax";
|
|
154
159
|
path: "/";
|
|
155
160
|
};
|
|
156
|
-
createSession: (accessToken: string, refreshToken?: string, rememberMe?: boolean) => Promise<void>;
|
|
161
|
+
createSession: (accessToken: string, refreshToken?: string, rememberMe?: boolean, options?: SessionWriteOptions) => Promise<void>;
|
|
157
162
|
writeSessionCookies: (response: Response, accessToken: string, refreshToken?: string, rememberMe?: boolean) => Response;
|
|
158
163
|
getAccessToken: () => Promise<string | null>;
|
|
159
164
|
getRefreshToken: () => Promise<string | null>;
|
|
160
165
|
getSession: () => Promise<SessionData | null>;
|
|
161
166
|
getSessionWithRefresh: () => Promise<SessionData | null>;
|
|
162
167
|
isRememberMe: () => Promise<boolean>;
|
|
163
|
-
updateAccessToken: (accessToken: string, refreshToken?: string) => Promise<void>;
|
|
164
|
-
destroySession: () => Promise<void>;
|
|
168
|
+
updateAccessToken: (accessToken: string, refreshToken?: string, options?: SessionWriteOptions) => Promise<void>;
|
|
169
|
+
destroySession: (options?: SessionWriteOptions) => Promise<void>;
|
|
165
170
|
clearSessionCookies: (response: Response) => Response;
|
|
166
171
|
requireSession: () => Promise<SessionData>;
|
|
167
172
|
isAuthenticated(): Promise<boolean>;
|
|
168
173
|
};
|
|
169
174
|
type SessionStore = ReturnType<typeof createSessionStore>;
|
|
170
175
|
|
|
171
|
-
export { CookieOptions, type PlatformFetch, type PlatformFetchConfig, type PlatformFetchTimeouts, PlatformServerFetchError, RecentAuthenticationRequiredError, SSOReauthenticationRequiredError, type SessionCookieNames, SessionData, SessionExpiredError, type SessionStore, type SessionStoreConfig, type SessionStoreRefreshConfig, authenticationErrorFor, buildForwardedRequestHeaders, controlRequest, createPlatformFetch, createSessionStore, isPlatformServerFetchError, isRecentAuthenticationRequiredError, isSSOReauthenticationRequiredError, isSessionExpiredError, mapControlError };
|
|
176
|
+
export { CookieOptions, type PlatformFetch, type PlatformFetchConfig, type PlatformFetchTimeouts, PlatformServerFetchError, RecentAuthenticationRequiredError, SSOReauthenticationRequiredError, type SessionCookieNames, SessionData, SessionExpiredError, type SessionStore, type SessionStoreConfig, type SessionStoreRefreshConfig, type SessionWriteOptions, authenticationErrorFor, buildForwardedRequestHeaders, controlRequest, createPlatformFetch, createSessionStore, isPlatformServerFetchError, isRecentAuthenticationRequiredError, isSSOReauthenticationRequiredError, isSessionExpiredError, mapControlError };
|
package/dist/next.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createSessionRefresher, setCookie, deleteCookie } from './chunk-
|
|
2
|
-
export { AUTH_ERROR_MESSAGES, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, SSO_ERROR_MESSAGES, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, isAuthErrorCode, isHandoffErrorCode, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath } from './chunk-
|
|
1
|
+
import { createSessionRefresher, setCookie, deleteCookie } from './chunk-Q7YI7RMG.js';
|
|
2
|
+
export { AUTH_ERROR_MESSAGES, HANDOFF_ERROR_FALLBACK, HANDOFF_ERROR_MESSAGES, SSO_ERROR_MESSAGES, authErrorMessage, brokerPaths, createDeviceIdentity, createHandoffSource, createHandoffTarget, createSessionRefresher, deleteCookie, evaluateSessionGate, handoffErrorMessage, hasSessionShape, isAuthErrorCode, isHandoffErrorCode, parseRefreshEnvelope, readCookie, safeInternalPath, serializeCookie, setCookie, sourceStartPath } from './chunk-Q7YI7RMG.js';
|
|
3
3
|
import { decodeDefaultSession, tokenMaxAgeSeconds, hasTokenAudience, isTokenExpiringSoon, isTokenExpired } from './chunk-FBC2NUH7.js';
|
|
4
4
|
export { decodeBase64Url, decodeDefaultSession, decodeTokenPayload, hasTokenAudience, isTokenExpired, isTokenExpiringSoon, parseAuthResponse, tokenMaxAgeSeconds } from './chunk-FBC2NUH7.js';
|
|
5
5
|
import { applyForwardedClientHeaders, resolveValue } from './chunk-ZWSJVE5S.js';
|
|
@@ -176,15 +176,16 @@ function createSessionStore(config) {
|
|
|
176
176
|
timeoutMs: config.refresh.timeoutMs,
|
|
177
177
|
fetch: config.refresh.fetch
|
|
178
178
|
}) : void 0;
|
|
179
|
-
function cookieOptions(rememberMe, token) {
|
|
179
|
+
function cookieOptions(rememberMe, token, options) {
|
|
180
180
|
const maxAge = token ? tokenMaxAgeSeconds(token, maxAgeCap) : maxAgeCap;
|
|
181
|
+
const effectiveDomain = hostPrefixed ? void 0 : options?.cookieDomain ?? domain;
|
|
181
182
|
return {
|
|
182
183
|
httpOnly: true,
|
|
183
184
|
secure,
|
|
184
185
|
sameSite: "lax",
|
|
185
186
|
path: "/",
|
|
186
187
|
...rememberMe ? { maxAge } : {},
|
|
187
|
-
...
|
|
188
|
+
...effectiveDomain ? { domain: effectiveDomain } : {}
|
|
188
189
|
};
|
|
189
190
|
}
|
|
190
191
|
function assertAudience(token) {
|
|
@@ -207,13 +208,13 @@ function createSessionStore(config) {
|
|
|
207
208
|
function rememberedIn(store) {
|
|
208
209
|
return store?.get(names.rememberMe)?.value === "true";
|
|
209
210
|
}
|
|
210
|
-
async function createSession(accessToken, refreshToken, rememberMe = config.defaultRememberMe ?? true) {
|
|
211
|
+
async function createSession(accessToken, refreshToken, rememberMe = config.defaultRememberMe ?? true, options) {
|
|
211
212
|
assertAudience(accessToken);
|
|
212
213
|
const store = await jar("createSession");
|
|
213
214
|
if (!store) throw new Error("Cannot create a session outside a request");
|
|
214
|
-
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken));
|
|
215
|
-
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken));
|
|
216
|
-
store.set(names.rememberMe, rememberMe ? "true" : "false", cookieOptions(rememberMe));
|
|
215
|
+
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken, options));
|
|
216
|
+
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken, options));
|
|
217
|
+
store.set(names.rememberMe, rememberMe ? "true" : "false", cookieOptions(rememberMe, void 0, options));
|
|
217
218
|
}
|
|
218
219
|
function writeSessionCookies(response, accessToken, refreshToken, rememberMe = config.defaultRememberMe ?? true) {
|
|
219
220
|
assertAudience(accessToken);
|
|
@@ -238,13 +239,13 @@ function createSessionStore(config) {
|
|
|
238
239
|
async function isRememberMe() {
|
|
239
240
|
return rememberedIn(await jar("isRememberMe"));
|
|
240
241
|
}
|
|
241
|
-
async function updateAccessToken(accessToken, refreshToken) {
|
|
242
|
+
async function updateAccessToken(accessToken, refreshToken, options) {
|
|
242
243
|
assertAudience(accessToken);
|
|
243
244
|
const store = await jar("updateAccessToken");
|
|
244
245
|
if (!store) throw new Error("Cannot update a session outside a request");
|
|
245
246
|
const rememberMe = rememberedIn(store);
|
|
246
|
-
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken));
|
|
247
|
-
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken));
|
|
247
|
+
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken, options));
|
|
248
|
+
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken, options));
|
|
248
249
|
}
|
|
249
250
|
async function getSessionWithRefresh() {
|
|
250
251
|
const store = await jar("getSessionWithRefresh");
|
|
@@ -264,12 +265,12 @@ function createSessionStore(config) {
|
|
|
264
265
|
function clearOptions() {
|
|
265
266
|
return { path: "/", secure };
|
|
266
267
|
}
|
|
267
|
-
async function destroySession() {
|
|
268
|
+
async function destroySession(options) {
|
|
268
269
|
const store = await jar("destroySession");
|
|
269
270
|
if (!store) return;
|
|
270
271
|
try {
|
|
271
|
-
const
|
|
272
|
-
for (const name of [names.session, names.refreshToken, names.rememberMe]) store.delete({ name, ...
|
|
272
|
+
const attributes = cookieOptions(false, void 0, options);
|
|
273
|
+
for (const name of [names.session, names.refreshToken, names.rememberMe]) store.delete({ name, ...attributes });
|
|
273
274
|
} catch (error) {
|
|
274
275
|
onError(error, "destroySession");
|
|
275
276
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c1m-public/platform-auth",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Session and authorization helpers for C1M platform surfaces. The root is runtime-neutral (Web Request/Response): token/session reads, the first-party handoff (PKCE target + source), proxy session gate and coalesced refresh; ./next adds the server-only guard; ./access carries the resolved access snapshot, typed permission keys, predicates, a Next loader and React bindings",
|