@agent-native/core 0.22.2 → 0.22.3
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/server/auth.d.ts +3 -2
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +43 -45
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +27 -16
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/cookie-namespace.d.ts +14 -0
- package/dist/server/cookie-namespace.d.ts.map +1 -0
- package/dist/server/cookie-namespace.js +118 -0
- package/dist/server/cookie-namespace.js.map +1 -0
- package/dist/server/derived-secret.d.ts +3 -0
- package/dist/server/derived-secret.d.ts.map +1 -0
- package/dist/server/derived-secret.js +19 -0
- package/dist/server/derived-secret.js.map +1 -0
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +8 -4
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/short-lived-token.d.ts +3 -2
- package/dist/server/short-lived-token.d.ts.map +1 -1
- package/dist/server/short-lived-token.js +8 -4
- package/dist/server/short-lived-token.js.map +1 -1
- package/docs/content/authentication.md +21 -0
- package/docs/content/security.md +3 -3
- package/package.json +1 -1
package/dist/server/auth.d.ts
CHANGED
|
@@ -138,11 +138,12 @@ export interface AuthOptions {
|
|
|
138
138
|
}
|
|
139
139
|
/**
|
|
140
140
|
* When set, the framework session cookie is shared across every subdomain
|
|
141
|
-
* matching this domain
|
|
142
|
-
*
|
|
141
|
+
* matching this domain. Returns undefined when unset or deliberately ignored
|
|
142
|
+
* for first-party hosted apps, so cookies stay scoped to the origin host.
|
|
143
143
|
*/
|
|
144
144
|
export declare function getCookieDomain(): string | undefined;
|
|
145
145
|
export declare const COOKIE_NAME: string;
|
|
146
|
+
export declare const BETTER_AUTH_COOKIE_PREFIX: string;
|
|
146
147
|
/**
|
|
147
148
|
* Cookie domain attribute spread into every `setCookie`/`deleteCookie`.
|
|
148
149
|
* Empty when `COOKIE_DOMAIN` isn't set so the cookie stays scoped to the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAsChE,KAAK,KAAK,GAAG,SAAS,CAAC;AAQvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAMlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAwB5D,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/server/auth.js
CHANGED
|
@@ -46,6 +46,7 @@ import { captureAuthError } from "./sentry.js";
|
|
|
46
46
|
import { extractOAuthStateAppId } from "../shared/oauth-state.js";
|
|
47
47
|
import { isValidWorkspaceAppIdFormat } from "../shared/workspace-app-id.js";
|
|
48
48
|
import { normalizeWorkspaceAppAudience, workspaceAppAudienceFromEnv, workspaceAppRouteAccessFromEnv, } from "../shared/workspace-app-audience.js";
|
|
49
|
+
import { resolveAuthCookieNamespace } from "./cookie-namespace.js";
|
|
49
50
|
import { BUILDER_CONNECT_OWNER_COOKIE, BUILDER_CONNECT_PARAM, BUILDER_STATE_PARAM, verifyBuilderCallbackStateAndGetOwner, verifyBuilderConnectTokenAndGetOwner, } from "./builder-browser.js";
|
|
50
51
|
// Pure env-read feature switch from a leaf module (no dependency back on
|
|
51
52
|
// auth.ts), so the guard and the SSO route handler share one validator and
|
|
@@ -70,7 +71,8 @@ export function getSessionMaxAge() {
|
|
|
70
71
|
* deploys on a shared domain), they would otherwise stomp on each other's
|
|
71
72
|
* `an_session` cookie and ping-pong each other into a logged-out state.
|
|
72
73
|
*
|
|
73
|
-
* When
|
|
74
|
+
* When an isolated app slug is resolved, suffix the cookie so each app gets
|
|
75
|
+
* its own slot.
|
|
74
76
|
*
|
|
75
77
|
* Workspace exception: in workspace mode (`AGENT_NATIVE_WORKSPACE=1`),
|
|
76
78
|
* every app shares the same origin AND the same DB, and cross-app SSO is
|
|
@@ -81,39 +83,24 @@ export function getSessionMaxAge() {
|
|
|
81
83
|
* exchange relies on — see `desktop-exchange` and `oauthCallbackResponse`)
|
|
82
84
|
* is recognised by every app in the workspace.
|
|
83
85
|
*
|
|
84
|
-
* Cross-subdomain exception: when `COOKIE_DOMAIN` is set
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* shared cookie since each subdomain reads a different name.
|
|
86
|
+
* Cross-subdomain exception: when `COOKIE_DOMAIN` is set for a custom domain,
|
|
87
|
+
* use the unsuffixed `an_session` and emit `Domain=<COOKIE_DOMAIN>` so the
|
|
88
|
+
* cookie is shared across every subdomain. First-party `*.agent-native.com`
|
|
89
|
+
* apps are deliberately excluded from that behavior by default because each
|
|
90
|
+
* hosted app has its own auth database; they use Dispatch identity federation
|
|
91
|
+
* instead of a shared browser cookie.
|
|
91
92
|
*/
|
|
92
|
-
const
|
|
93
|
-
.toLowerCase()
|
|
94
|
-
.replace(/[^a-z0-9]+/g, "_")
|
|
95
|
-
.replace(/^_+|_+$/g, "");
|
|
96
|
-
const IS_WORKSPACE_MODE = process.env.AGENT_NATIVE_WORKSPACE === "1";
|
|
93
|
+
const AUTH_COOKIE_NAMESPACE = resolveAuthCookieNamespace();
|
|
97
94
|
/**
|
|
98
95
|
* When set, the framework session cookie is shared across every subdomain
|
|
99
|
-
* matching this domain
|
|
100
|
-
*
|
|
96
|
+
* matching this domain. Returns undefined when unset or deliberately ignored
|
|
97
|
+
* for first-party hosted apps, so cookies stay scoped to the origin host.
|
|
101
98
|
*/
|
|
102
99
|
export function getCookieDomain() {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return trimmed || undefined;
|
|
108
|
-
}
|
|
109
|
-
const HAS_COOKIE_DOMAIN = !!getCookieDomain();
|
|
110
|
-
export const COOKIE_NAME = HAS_COOKIE_DOMAIN
|
|
111
|
-
? "an_session"
|
|
112
|
-
: IS_WORKSPACE_MODE
|
|
113
|
-
? "an_session_workspace"
|
|
114
|
-
: APP_NAME_SLUG
|
|
115
|
-
? `an_session_${APP_NAME_SLUG}`
|
|
116
|
-
: "an_session";
|
|
100
|
+
return AUTH_COOKIE_NAMESPACE.frameworkCookieDomain;
|
|
101
|
+
}
|
|
102
|
+
export const COOKIE_NAME = AUTH_COOKIE_NAMESPACE.frameworkCookieName;
|
|
103
|
+
export const BETTER_AUTH_COOKIE_PREFIX = AUTH_COOKIE_NAMESPACE.betterAuthCookiePrefix;
|
|
117
104
|
/**
|
|
118
105
|
* Cookie domain attribute spread into every `setCookie`/`deleteCookie`.
|
|
119
106
|
* Empty when `COOKIE_DOMAIN` isn't set so the cookie stays scoped to the
|
|
@@ -158,22 +145,30 @@ function getCookieValues(event, name) {
|
|
|
158
145
|
return values;
|
|
159
146
|
}
|
|
160
147
|
export function getFrameworkSessionCookieValues(event) {
|
|
161
|
-
return
|
|
148
|
+
return getFrameworkSessionCookieEntries(event).map((entry) => entry.value);
|
|
149
|
+
}
|
|
150
|
+
function getFrameworkSessionCookieEntries(event) {
|
|
151
|
+
const entries = [];
|
|
152
|
+
const seenValues = new Set();
|
|
153
|
+
for (const name of frameworkSessionCookieNamesToClear()) {
|
|
154
|
+
for (const value of getCookieValues(event, name)) {
|
|
155
|
+
if (seenValues.has(value))
|
|
156
|
+
continue;
|
|
157
|
+
seenValues.add(value);
|
|
158
|
+
entries.push({ name, value });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return entries;
|
|
162
162
|
}
|
|
163
163
|
function frameworkSessionCookieNamesToClear() {
|
|
164
|
-
|
|
165
|
-
if (APP_NAME_SLUG)
|
|
166
|
-
names.add(`an_session_${APP_NAME_SLUG}`);
|
|
167
|
-
return [...names];
|
|
164
|
+
return AUTH_COOKIE_NAMESPACE.frameworkCookieNamesToClear;
|
|
168
165
|
}
|
|
169
166
|
function deleteCookieFromEveryScope(event, name) {
|
|
170
|
-
// Clear host-only cookies first.
|
|
171
|
-
//
|
|
172
|
-
// browsers send older same-path duplicates first.
|
|
167
|
+
// Clear host-only cookies first. Then clear any configured domain scope so
|
|
168
|
+
// stale shared cookies stop shadowing isolated app sessions.
|
|
173
169
|
deleteCookie(event, name, { path: "/" });
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
deleteCookie(event, name, { path: "/", ...domainAttrs });
|
|
170
|
+
for (const domain of AUTH_COOKIE_NAMESPACE.frameworkCookieDomainsToClear) {
|
|
171
|
+
deleteCookie(event, name, { path: "/", domain });
|
|
177
172
|
}
|
|
178
173
|
}
|
|
179
174
|
export function clearFrameworkSessionCookies(event) {
|
|
@@ -182,10 +177,13 @@ export function clearFrameworkSessionCookies(event) {
|
|
|
182
177
|
}
|
|
183
178
|
}
|
|
184
179
|
async function getLegacyCookieSession(event) {
|
|
185
|
-
for (const
|
|
186
|
-
const email = await getSessionEmail(
|
|
187
|
-
if (email)
|
|
188
|
-
|
|
180
|
+
for (const { name, value } of getFrameworkSessionCookieEntries(event)) {
|
|
181
|
+
const email = await getSessionEmail(value);
|
|
182
|
+
if (email) {
|
|
183
|
+
if (name !== COOKIE_NAME)
|
|
184
|
+
setFrameworkSessionCookie(event, value);
|
|
185
|
+
return { email, token: value };
|
|
186
|
+
}
|
|
189
187
|
}
|
|
190
188
|
return null;
|
|
191
189
|
}
|
|
@@ -854,7 +852,7 @@ function shouldBypassAuthForBuilderConnect(event, p) {
|
|
|
854
852
|
// session-lost popup case) — when a session IS present, the normal
|
|
855
853
|
// guard runs and the callback handler cross-checks the state owner
|
|
856
854
|
// against the session.
|
|
857
|
-
const hasSession =
|
|
855
|
+
const hasSession = getFrameworkSessionCookieValues(event).length > 0;
|
|
858
856
|
if (hasSession)
|
|
859
857
|
return false;
|
|
860
858
|
return Boolean(verifyBuilderCallbackStateAndGetOwner(state) ||
|