@vertesia/ui 1.6.0-dev.20260918.061604Z → 1.6.0-dev.20260918.090710Z
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/lib/env/index.d.ts +21 -7
- package/lib/env/index.d.ts.map +1 -1
- package/lib/env/index.js +7 -0
- package/lib/env/index.js.map +1 -1
- package/lib/session/UserSession.d.ts +1 -0
- package/lib/session/UserSession.d.ts.map +1 -1
- package/lib/session/UserSession.js +57 -2
- package/lib/session/UserSession.js.map +1 -1
- package/lib/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/session/UserSessionProvider.js +25 -0
- package/lib/session/UserSessionProvider.js.map +1 -1
- package/lib/session/auth/domainRouting.d.ts +3 -4
- package/lib/session/auth/domainRouting.d.ts.map +1 -1
- package/lib/session/auth/domainRouting.js +15 -4
- package/lib/session/auth/domainRouting.js.map +1 -1
- package/lib/session/auth/gateway.d.ts +8 -0
- package/lib/session/auth/gateway.d.ts.map +1 -0
- package/lib/session/auth/gateway.js +47 -0
- package/lib/session/auth/gateway.js.map +1 -0
- package/lib/session/auth/oauth.d.ts +4 -0
- package/lib/session/auth/oauth.d.ts.map +1 -0
- package/lib/session/auth/oauth.js +167 -0
- package/lib/session/auth/oauth.js.map +1 -0
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/package.json +7 -7
- package/src/env/index.test.ts +21 -0
- package/src/env/index.ts +18 -5
- package/src/session/UserSession.ts +58 -2
- package/src/session/UserSessionProvider.strict-mode.test.tsx +36 -0
- package/src/session/UserSessionProvider.tsx +24 -0
- package/src/session/auth/auth-flow.md +21 -9
- package/src/session/auth/domainRouting.test.ts +1 -1
- package/src/session/auth/domainRouting.ts +14 -4
- package/src/session/auth/gateway.test.ts +82 -0
- package/src/session/auth/gateway.ts +49 -0
- package/src/session/auth/oauth.test.ts +173 -0
- package/src/session/auth/oauth.ts +176 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { Env } from '@vertesia/ui/env';
|
|
2
|
+
import { jwtDecode } from 'jwt-decode';
|
|
3
|
+
import { usesGatewaySession } from './gateway';
|
|
4
|
+
const TRANSACTION_KEY = 'vertesia.oauth.transaction';
|
|
5
|
+
const TOKEN_KEY = 'vertesia.oauth.access';
|
|
6
|
+
const MAX_TRANSACTION_AGE = 10 * 60_000;
|
|
7
|
+
let pending;
|
|
8
|
+
export function usesAppOAuth() {
|
|
9
|
+
return Boolean(Env.oauth && window.parent === window && window.AUTH_MODE !== 'firebase' && !usesGatewaySession());
|
|
10
|
+
}
|
|
11
|
+
function base64url(bytes) {
|
|
12
|
+
return btoa(String.fromCharCode(...bytes))
|
|
13
|
+
.replace(/\+/g, '-')
|
|
14
|
+
.replace(/\//g, '_')
|
|
15
|
+
.replace(/=+$/, '');
|
|
16
|
+
}
|
|
17
|
+
function randomValue() {
|
|
18
|
+
return base64url(crypto.getRandomValues(new Uint8Array(32)));
|
|
19
|
+
}
|
|
20
|
+
function httpsUrl(value) {
|
|
21
|
+
const url = new URL(value);
|
|
22
|
+
if (url.protocol !== 'https:' || url.username || url.password)
|
|
23
|
+
throw new Error('OAuth endpoint must use HTTPS');
|
|
24
|
+
return url;
|
|
25
|
+
}
|
|
26
|
+
export function clearAppOAuth() {
|
|
27
|
+
sessionStorage.removeItem(TOKEN_KEY);
|
|
28
|
+
sessionStorage.removeItem(TRANSACTION_KEY);
|
|
29
|
+
}
|
|
30
|
+
/** Public-client PKCE for independently hosted apps. No Firebase identity token or client secret. */
|
|
31
|
+
async function acquireToken() {
|
|
32
|
+
const config = Env.oauth;
|
|
33
|
+
if (!config)
|
|
34
|
+
throw new Error('Application OAuth is not configured');
|
|
35
|
+
const clientId = config.clientId.trim();
|
|
36
|
+
if (!clientId)
|
|
37
|
+
throw new Error('OAuth client ID is required');
|
|
38
|
+
const redirect = new URL(config.redirectUri);
|
|
39
|
+
const loopback = redirect.hostname === 'localhost' ||
|
|
40
|
+
redirect.hostname.endsWith('.localhost') ||
|
|
41
|
+
redirect.hostname === '[::1]' ||
|
|
42
|
+
/^127\.\d+\.\d+\.\d+$/.test(redirect.hostname);
|
|
43
|
+
if (redirect.protocol !== 'https:' && !(loopback && redirect.protocol === 'http:')) {
|
|
44
|
+
throw new Error('OAuth callback must use HTTPS or loopback HTTP');
|
|
45
|
+
}
|
|
46
|
+
const redirectUri = redirect.toString();
|
|
47
|
+
if (new URL(redirectUri).origin !== window.location.origin)
|
|
48
|
+
throw new Error('OAuth callback must be same-origin');
|
|
49
|
+
const issuer = Env.endpoints.sts.replace(/\/+$/, '');
|
|
50
|
+
const current = new URL(window.location.href);
|
|
51
|
+
const callback = current.origin + current.pathname === new URL(redirectUri).origin + new URL(redirectUri).pathname;
|
|
52
|
+
const state = callback ? current.searchParams.get('state') : null;
|
|
53
|
+
const code = callback ? current.searchParams.get('code') : null;
|
|
54
|
+
const error = callback ? current.searchParams.get('error') : null;
|
|
55
|
+
let transaction;
|
|
56
|
+
if (state || code || error) {
|
|
57
|
+
const raw = sessionStorage.getItem(TRANSACTION_KEY);
|
|
58
|
+
sessionStorage.removeItem(TRANSACTION_KEY);
|
|
59
|
+
transaction = raw ? JSON.parse(raw) : undefined;
|
|
60
|
+
if (!transaction ||
|
|
61
|
+
transaction.state !== state ||
|
|
62
|
+
transaction.clientId !== clientId ||
|
|
63
|
+
transaction.redirectUri !== redirectUri ||
|
|
64
|
+
transaction.issuer !== issuer ||
|
|
65
|
+
Date.now() - transaction.created > MAX_TRANSACTION_AGE ||
|
|
66
|
+
transaction.created > Date.now()) {
|
|
67
|
+
throw new Error('Invalid or expired OAuth login state');
|
|
68
|
+
}
|
|
69
|
+
if (error || !code)
|
|
70
|
+
throw new Error(`Application sign-in was not completed (${error || 'missing code'})`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const raw = sessionStorage.getItem(TOKEN_KEY);
|
|
74
|
+
if (raw) {
|
|
75
|
+
const cached = JSON.parse(raw);
|
|
76
|
+
const claims = jwtDecode(cached.token);
|
|
77
|
+
if (cached.clientId === clientId &&
|
|
78
|
+
cached.issuer === issuer &&
|
|
79
|
+
claims.exp > Date.now() / 1000 + 30 &&
|
|
80
|
+
(!current.searchParams.get('p') || claims.project?.id === current.searchParams.get('p')) &&
|
|
81
|
+
(!current.searchParams.get('a') || claims.account?.id === current.searchParams.get('a'))) {
|
|
82
|
+
return cached.token;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const discovery = await fetch(`${issuer}/.well-known/oauth-authorization-server`);
|
|
87
|
+
if (!discovery.ok)
|
|
88
|
+
throw new Error(`OAuth discovery failed (${discovery.status})`);
|
|
89
|
+
const metadata = await discovery.json();
|
|
90
|
+
if (metadata.issuer.replace(/\/+$/, '') !== issuer)
|
|
91
|
+
throw new Error('OAuth issuer mismatch');
|
|
92
|
+
const authorize = httpsUrl(metadata.authorization_endpoint);
|
|
93
|
+
const tokenEndpoint = httpsUrl(metadata.token_endpoint);
|
|
94
|
+
if (transaction && code) {
|
|
95
|
+
const response = await fetch(tokenEndpoint, {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
98
|
+
body: new URLSearchParams({
|
|
99
|
+
grant_type: 'authorization_code',
|
|
100
|
+
code,
|
|
101
|
+
client_id: clientId,
|
|
102
|
+
redirect_uri: redirectUri,
|
|
103
|
+
code_verifier: transaction.verifier,
|
|
104
|
+
}),
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok)
|
|
107
|
+
throw new Error(`OAuth code exchange failed (${response.status})`);
|
|
108
|
+
const grant = await response.json();
|
|
109
|
+
if (!grant.access_token || grant.token_type?.toLowerCase() !== 'bearer')
|
|
110
|
+
throw new Error('Invalid OAuth grant');
|
|
111
|
+
const claims = jwtDecode(grant.access_token);
|
|
112
|
+
if (claims.iss.replace(/\/+$/, '') !== issuer ||
|
|
113
|
+
claims.client_id !== clientId ||
|
|
114
|
+
claims.exp <= Date.now() / 1000) {
|
|
115
|
+
throw new Error('OAuth grant does not match this application');
|
|
116
|
+
}
|
|
117
|
+
sessionStorage.setItem(TOKEN_KEY, JSON.stringify({ token: grant.access_token, clientId, issuer }));
|
|
118
|
+
const target = new URL(transaction.target);
|
|
119
|
+
if (target.origin !== window.location.origin)
|
|
120
|
+
throw new Error('Invalid OAuth return target');
|
|
121
|
+
window.history.replaceState(window.history.state, '', target);
|
|
122
|
+
return grant.access_token;
|
|
123
|
+
}
|
|
124
|
+
let scopes = config.scopes ?? ['openid', 'profile'];
|
|
125
|
+
if (clientId.startsWith('https://')) {
|
|
126
|
+
const documentResponse = await fetch(httpsUrl(clientId), { cache: 'no-store' });
|
|
127
|
+
if (!documentResponse.ok)
|
|
128
|
+
throw new Error(`Application CIMD unavailable (${documentResponse.status})`);
|
|
129
|
+
const document = await documentResponse.json();
|
|
130
|
+
if (!document.redirect_uris?.includes(redirectUri))
|
|
131
|
+
throw new Error('Application CIMD does not allow this callback');
|
|
132
|
+
if (!config.scopes && document.scope)
|
|
133
|
+
scopes = document.scope.split(/\s+/);
|
|
134
|
+
}
|
|
135
|
+
const verifier = randomValue();
|
|
136
|
+
const next = {
|
|
137
|
+
state: randomValue(),
|
|
138
|
+
verifier,
|
|
139
|
+
clientId,
|
|
140
|
+
redirectUri,
|
|
141
|
+
issuer,
|
|
142
|
+
target: current.toString(),
|
|
143
|
+
created: Date.now(),
|
|
144
|
+
};
|
|
145
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));
|
|
146
|
+
authorize.searchParams.set('client_id', clientId);
|
|
147
|
+
authorize.searchParams.set('redirect_uri', redirectUri);
|
|
148
|
+
authorize.searchParams.set('response_type', 'code');
|
|
149
|
+
authorize.searchParams.set('state', next.state);
|
|
150
|
+
authorize.searchParams.set('code_challenge_method', 'S256');
|
|
151
|
+
authorize.searchParams.set('code_challenge', base64url(new Uint8Array(digest)));
|
|
152
|
+
// This browser client intentionally requests no refresh token.
|
|
153
|
+
authorize.searchParams.set('scope', scopes.filter((s) => s !== 'offline_access').join(' '));
|
|
154
|
+
const project = current.searchParams.get('p');
|
|
155
|
+
if (project)
|
|
156
|
+
authorize.searchParams.set('project_id', project);
|
|
157
|
+
sessionStorage.setItem(TRANSACTION_KEY, JSON.stringify(next));
|
|
158
|
+
window.location.replace(authorize.toString());
|
|
159
|
+
return new Promise(() => { });
|
|
160
|
+
}
|
|
161
|
+
export function getAppOAuthToken() {
|
|
162
|
+
pending ??= acquireToken().finally(() => {
|
|
163
|
+
pending = undefined;
|
|
164
|
+
});
|
|
165
|
+
return pending;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/session/auth/oauth.ts"],"names":[],"mappings":"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"}
|
package/lib/vertesia-ui-env.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function e(){if(typeof window>`u`)return;let e=window.__VERTESIA_RUNTIME_CONFIG__;if(e?.authMode===`central`)return e;if(e?.authMode!==`firebase`)return;let t=e.firebase;if(t?.apiKey&&t.authDomain&&t.projectId&&t.appId)return e}function t(e){if(!e)return;let t=t=>typeof e[t]==`string`?e[t].trim():``,n=t(`VITE_AUTH_MODE`);if(n&&n!==`firebase`&&n!==`central`)throw Error(`VITE_AUTH_MODE must be firebase or central`);if(!n)return;if(n===`central`)return{authMode:`central`};let r={apiKey:`VITE_FIREBASE_API_KEY`,authDomain:`VITE_FIREBASE_AUTH_DOMAIN`,projectId:`VITE_FIREBASE_PROJECT_ID`,appId:`VITE_FIREBASE_APP_ID`},i=Object.values(r).filter(e=>!t(e));if(i.length)throw Error(`Firebase authentication requires: ${i.join(`, `)}`);return{authMode:`firebase`,firebase:{apiKey:t(r.apiKey),authDomain:t(r.authDomain),projectId:t(r.projectId),appId:t(r.appId)}}}var n=class{_props;constructor(e){this._props=e}init(n,r){let i=e()??t(r),a=i?.authMode===`firebase`?i.firebase:void 0;this._props=n&&a&&!n.firebase?{...n,firebase:a}:n;let o=typeof r?.VITE_FIREBASE_TENANT_ID==`string`?r.VITE_FIREBASE_TENANT_ID.trim():``;if(this._props?.firebase&&
|
|
1
|
+
function e(){if(typeof window>`u`)return;let e=window.__VERTESIA_RUNTIME_CONFIG__;if(e?.authMode===`central`)return e;if(e?.authMode!==`firebase`)return;let t=e.firebase;if(t?.apiKey&&t.authDomain&&t.projectId&&t.appId)return e}function t(e){if(!e)return;let t=t=>typeof e[t]==`string`?e[t].trim():``,n=t(`VITE_AUTH_MODE`);if(n&&n!==`firebase`&&n!==`central`)throw Error(`VITE_AUTH_MODE must be firebase or central`);if(!n)return;if(n===`central`)return{authMode:`central`};let r={apiKey:`VITE_FIREBASE_API_KEY`,authDomain:`VITE_FIREBASE_AUTH_DOMAIN`,projectId:`VITE_FIREBASE_PROJECT_ID`,appId:`VITE_FIREBASE_APP_ID`},i=Object.values(r).filter(e=>!t(e));if(i.length)throw Error(`Firebase authentication requires: ${i.join(`, `)}`);return{authMode:`firebase`,firebase:{apiKey:t(r.apiKey),authDomain:t(r.authDomain),projectId:t(r.projectId),appId:t(r.appId)}}}var n=class{_props;constructor(e){this._props=e}init(n,r){let i=e()??t(r),a=i?.authMode===`firebase`?i.firebase:void 0;this._props=n&&a&&!n.firebase?{...n,firebase:a}:n;let o=i?.authMode===`central`?i.authUrl?.trim():void 0;this._props&&o&&(this._props={...this._props,endpoints:{...this._props.endpoints,auth:o}});let s=typeof r?.VITE_FIREBASE_TENANT_ID==`string`?r.VITE_FIREBASE_TENANT_ID.trim():``;if(this._props?.firebase&&s&&!this._props.firebase.tenantId&&(this._props={...this._props,firebase:{...this._props.firebase,tenantId:s}}),this._props&&this._props.defaultAuthSelection===void 0&&r){let e=typeof r.VITE_VERTESIA_ACCOUNT_ID==`string`&&r.VITE_VERTESIA_ACCOUNT_ID.trim()||void 0,t=typeof r.VITE_VERTESIA_PROJECT_ID==`string`&&r.VITE_VERTESIA_PROJECT_ID.trim()||void 0;(e||t)&&(this._props={...this._props,defaultAuthSelection:{accountId:e,projectId:t}})}return i&&typeof window<`u`&&window.AUTH_MODE===void 0&&(window.AUTH_MODE=i.authMode),this}prop(e){if(!this._props)throw Error(`VertesiaEnvironment was not initialized`);return this._props[e]}get version(){return this.prop(`version`)}get commitTimestamp(){return this._props?.commitTimestamp}get sdkVersion(){return this._props?.sdkVersion}get name(){return this.prop(`name`)}get type(){return this.prop(`type`)}get isProd(){return this.type===`production`||this.type===`preview`}get isDev(){return!this.isProd}get isLocalDev(){return this.prop(`isLocalDev`)}get isDocker(){return this.prop(`isDocker`)}get endpoints(){return this.prop(`endpoints`)}get firebase(){return this.prop(`firebase`)}get region(){return this._props?.region}get datadog(){return this.datadogRum}get datadogRum(){return this._props?.datadogRum??!1}get datadogLogs(){return this._props?.datadogLogs??!1}get devAuthToken(){return this._props?.devAuthToken}get defaultAuthSelection(){return this._props?.defaultAuthSelection}get oauth(){return this._props?.oauth}get authTokenProvider(){return this._props?.authTokenProvider}get logger(){return this._props?.logger??console}onLogin(e){this._props?.onLogin?.(e)}onLogout(){this._props?.onLogout?.()}};const r=new n;export{r as Env,n as VertesiaEnvironment};
|
|
2
2
|
//# sourceMappingURL=vertesia-ui-env.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertesia-ui-env.js","names":[],"sources":["env/index.js"],"sourcesContent":["// hook to initialize the environment and auth session\n// the main app must call this hook before rendering the page.\nfunction injectedRuntimeConfig() {\n if (typeof window === 'undefined')\n return undefined;\n const runtimeConfig = window.__VERTESIA_RUNTIME_CONFIG__;\n if (runtimeConfig?.authMode === 'central')\n return runtimeConfig;\n if (runtimeConfig?.authMode !== 'firebase')\n return undefined;\n const firebase = runtimeConfig.firebase;\n if (!firebase?.apiKey || !firebase.authDomain || !firebase.projectId || !firebase.appId)\n return undefined;\n return runtimeConfig;\n}\nfunction buildRuntimeConfig(env) {\n if (!env)\n return undefined;\n const value = (name) => (typeof env[name] === 'string' ? env[name].trim() : '');\n const mode = value('VITE_AUTH_MODE');\n if (mode && mode !== 'firebase' && mode !== 'central') {\n throw new Error('VITE_AUTH_MODE must be firebase or central');\n }\n // Firebase build settings are only consumed after an explicit opt-in.\n if (!mode)\n return undefined;\n if (mode === 'central')\n return { authMode: 'central' };\n const fields = {\n apiKey: 'VITE_FIREBASE_API_KEY',\n authDomain: 'VITE_FIREBASE_AUTH_DOMAIN',\n projectId: 'VITE_FIREBASE_PROJECT_ID',\n appId: 'VITE_FIREBASE_APP_ID',\n };\n const missing = Object.values(fields).filter((name) => !value(name));\n if (missing.length) {\n throw new Error(`Firebase authentication requires: ${missing.join(', ')}`);\n }\n return {\n authMode: 'firebase',\n firebase: {\n apiKey: value(fields.apiKey),\n authDomain: value(fields.authDomain),\n projectId: value(fields.projectId),\n appId: value(fields.appId),\n },\n };\n}\nexport class VertesiaEnvironment {\n _props;\n constructor(_props) {\n this._props = _props;\n }\n init(props, buildEnv) {\n // Host runtime configuration takes precedence over static deployment defaults.\n const runtimeConfig = injectedRuntimeConfig() ?? buildRuntimeConfig(buildEnv);\n const runtimeFirebase = runtimeConfig?.authMode === 'firebase' ? runtimeConfig.firebase : undefined;\n this._props = props && runtimeFirebase && !props.firebase ? { ...props, firebase: runtimeFirebase } : props;\n const tenantId = typeof buildEnv?.VITE_FIREBASE_TENANT_ID === 'string' ? buildEnv.VITE_FIREBASE_TENANT_ID.trim() : '';\n if (this._props?.firebase && tenantId && !this._props.firebase.tenantId) {\n this._props = { ...this._props, firebase: { ...this._props.firebase, tenantId } };\n }\n if (this._props && this._props.defaultAuthSelection === undefined && buildEnv) {\n const accountId = typeof buildEnv.VITE_VERTESIA_ACCOUNT_ID === 'string'\n ? buildEnv.VITE_VERTESIA_ACCOUNT_ID.trim() || undefined\n : undefined;\n const projectId = typeof buildEnv.VITE_VERTESIA_PROJECT_ID === 'string'\n ? buildEnv.VITE_VERTESIA_PROJECT_ID.trim() || undefined\n : undefined;\n if (accountId || projectId)\n this._props = { ...this._props, defaultAuthSelection: { accountId, projectId } };\n }\n if (runtimeConfig && typeof window !== 'undefined' && window.AUTH_MODE === undefined) {\n window.AUTH_MODE = runtimeConfig.authMode;\n }\n return this;\n }\n prop(name) {\n if (!this._props) {\n throw new Error('VertesiaEnvironment was not initialized');\n }\n return this._props[name];\n }\n get version() {\n return this.prop('version');\n }\n get commitTimestamp() {\n return this._props?.commitTimestamp;\n }\n get sdkVersion() {\n return this._props?.sdkVersion;\n }\n get name() {\n return this.prop('name');\n }\n get type() {\n return this.prop('type');\n }\n get isProd() {\n return this.type === 'production' || this.type === 'preview';\n }\n get isDev() {\n return !this.isProd;\n }\n get isLocalDev() {\n return this.prop('isLocalDev');\n }\n get isDocker() {\n return this.prop('isDocker');\n }\n get endpoints() {\n return this.prop('endpoints');\n }\n get firebase() {\n return this.prop('firebase');\n }\n get region() {\n return this._props?.region;\n }\n /**\n * @deprecated Use datadogRum and datadogLogs instead for more granular control. This will be removed in a future release. Is an alias for DatadogRUM\n *\n */\n get datadog() {\n return this.datadogRum;\n }\n get datadogRum() {\n return this._props?.datadogRum ?? false;\n }\n get datadogLogs() {\n return this._props?.datadogLogs ?? false;\n }\n get devAuthToken() {\n return this._props?.devAuthToken;\n }\n get defaultAuthSelection() {\n return this._props?.defaultAuthSelection;\n }\n get authTokenProvider() {\n return this._props?.authTokenProvider;\n }\n get logger() {\n return this._props?.logger ?? console;\n }\n /**\n * Callback to notify the host app when the user logs in.\n */\n onLogin(token) {\n this._props?.onLogin?.(token);\n }\n /**\n * Callback to notify the host app when the user logs out\n */\n onLogout() {\n this._props?.onLogout?.();\n }\n}\nconst Env = new VertesiaEnvironment();\nexport { Env };\n//# sourceMappingURL=index.js.map"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vertesia-ui-env.js","names":[],"sources":["env/index.js"],"sourcesContent":["// hook to initialize the environment and auth session\n// the main app must call this hook before rendering the page.\nfunction injectedRuntimeConfig() {\n if (typeof window === 'undefined')\n return undefined;\n const runtimeConfig = window.__VERTESIA_RUNTIME_CONFIG__;\n if (runtimeConfig?.authMode === 'central')\n return runtimeConfig;\n if (runtimeConfig?.authMode !== 'firebase')\n return undefined;\n const firebase = runtimeConfig.firebase;\n if (!firebase?.apiKey || !firebase.authDomain || !firebase.projectId || !firebase.appId)\n return undefined;\n return runtimeConfig;\n}\nfunction buildRuntimeConfig(env) {\n if (!env)\n return undefined;\n const value = (name) => (typeof env[name] === 'string' ? env[name].trim() : '');\n const mode = value('VITE_AUTH_MODE');\n if (mode && mode !== 'firebase' && mode !== 'central') {\n throw new Error('VITE_AUTH_MODE must be firebase or central');\n }\n // Firebase build settings are only consumed after an explicit opt-in.\n if (!mode)\n return undefined;\n if (mode === 'central')\n return { authMode: 'central' };\n const fields = {\n apiKey: 'VITE_FIREBASE_API_KEY',\n authDomain: 'VITE_FIREBASE_AUTH_DOMAIN',\n projectId: 'VITE_FIREBASE_PROJECT_ID',\n appId: 'VITE_FIREBASE_APP_ID',\n };\n const missing = Object.values(fields).filter((name) => !value(name));\n if (missing.length) {\n throw new Error(`Firebase authentication requires: ${missing.join(', ')}`);\n }\n return {\n authMode: 'firebase',\n firebase: {\n apiKey: value(fields.apiKey),\n authDomain: value(fields.authDomain),\n projectId: value(fields.projectId),\n appId: value(fields.appId),\n },\n };\n}\nexport class VertesiaEnvironment {\n _props;\n constructor(_props) {\n this._props = _props;\n }\n init(props, buildEnv) {\n // Host runtime configuration takes precedence over static deployment defaults.\n const runtimeConfig = injectedRuntimeConfig() ?? buildRuntimeConfig(buildEnv);\n const runtimeFirebase = runtimeConfig?.authMode === 'firebase' ? runtimeConfig.firebase : undefined;\n this._props = props && runtimeFirebase && !props.firebase ? { ...props, firebase: runtimeFirebase } : props;\n const authUrl = runtimeConfig?.authMode === 'central' ? runtimeConfig.authUrl?.trim() : undefined;\n if (this._props && authUrl) {\n this._props = { ...this._props, endpoints: { ...this._props.endpoints, auth: authUrl } };\n }\n const tenantId = typeof buildEnv?.VITE_FIREBASE_TENANT_ID === 'string' ? buildEnv.VITE_FIREBASE_TENANT_ID.trim() : '';\n if (this._props?.firebase && tenantId && !this._props.firebase.tenantId) {\n this._props = { ...this._props, firebase: { ...this._props.firebase, tenantId } };\n }\n if (this._props && this._props.defaultAuthSelection === undefined && buildEnv) {\n const accountId = typeof buildEnv.VITE_VERTESIA_ACCOUNT_ID === 'string'\n ? buildEnv.VITE_VERTESIA_ACCOUNT_ID.trim() || undefined\n : undefined;\n const projectId = typeof buildEnv.VITE_VERTESIA_PROJECT_ID === 'string'\n ? buildEnv.VITE_VERTESIA_PROJECT_ID.trim() || undefined\n : undefined;\n if (accountId || projectId)\n this._props = { ...this._props, defaultAuthSelection: { accountId, projectId } };\n }\n if (runtimeConfig && typeof window !== 'undefined' && window.AUTH_MODE === undefined) {\n window.AUTH_MODE = runtimeConfig.authMode;\n }\n return this;\n }\n prop(name) {\n if (!this._props) {\n throw new Error('VertesiaEnvironment was not initialized');\n }\n return this._props[name];\n }\n get version() {\n return this.prop('version');\n }\n get commitTimestamp() {\n return this._props?.commitTimestamp;\n }\n get sdkVersion() {\n return this._props?.sdkVersion;\n }\n get name() {\n return this.prop('name');\n }\n get type() {\n return this.prop('type');\n }\n get isProd() {\n return this.type === 'production' || this.type === 'preview';\n }\n get isDev() {\n return !this.isProd;\n }\n get isLocalDev() {\n return this.prop('isLocalDev');\n }\n get isDocker() {\n return this.prop('isDocker');\n }\n get endpoints() {\n return this.prop('endpoints');\n }\n get firebase() {\n return this.prop('firebase');\n }\n get region() {\n return this._props?.region;\n }\n /**\n * @deprecated Use datadogRum and datadogLogs instead for more granular control. This will be removed in a future release. Is an alias for DatadogRUM\n *\n */\n get datadog() {\n return this.datadogRum;\n }\n get datadogRum() {\n return this._props?.datadogRum ?? false;\n }\n get datadogLogs() {\n return this._props?.datadogLogs ?? false;\n }\n get devAuthToken() {\n return this._props?.devAuthToken;\n }\n get defaultAuthSelection() {\n return this._props?.defaultAuthSelection;\n }\n get oauth() {\n return this._props?.oauth;\n }\n get authTokenProvider() {\n return this._props?.authTokenProvider;\n }\n get logger() {\n return this._props?.logger ?? console;\n }\n /**\n * Callback to notify the host app when the user logs in.\n */\n onLogin(token) {\n this._props?.onLogin?.(token);\n }\n /**\n * Callback to notify the host app when the user logs out\n */\n onLogout() {\n this._props?.onLogout?.();\n }\n}\nconst Env = new VertesiaEnvironment();\nexport { Env };\n//# sourceMappingURL=index.js.map"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{NO_ACCESSIBLE_ACCOUNT_ERROR_CODE as e,REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE as t,RESTRICTED_ENVIRONMENT_ERROR_CODE as n}from"@vertesia/common";import{Env as r}from"@vertesia/ui/env";import{jwtDecode as i}from"jwt-decode";import{getAnalytics as a,logEvent as o}from"firebase/analytics";import{initializeApp as s}from"firebase/app";import{getAuth as c,onAuthStateChanged as l}from"firebase/auth";import{createContext as u,useCallback as d,useContext as f,useEffect as p,useMemo as m,useRef as h,useState as g}from"react";import{NAMESPACE as ee,i18nInstance as _}from"@vertesia/ui/i18n";import{VertesiaClient as te}from"@vertesia/client";import{jsx as ne}from"react/jsx-runtime";const v=`composableai.lastSelectedAccountId`,y=`composableai.lastSelectedProjectId`,b=`auth_state`,x=`auth_state_expiry`;function S(){let e=crypto.randomUUID();return sessionStorage.setItem(b,e),sessionStorage.setItem(x,String(Date.now()+3e5)),e}function re(e){if(!e)return`Missing state`;let t=sessionStorage.getItem(b),n=parseInt(sessionStorage.getItem(x)||`0`,10);if(t!==e)return`State mismatched (${t} !== ${e})`;if(Date.now()>n)return`State expired`}function ie(){sessionStorage.removeItem(b),sessionStorage.removeItem(x)}function C(){return r.endpoints.auth||`https://internal-auth.vertesia.app/`}function ae(e){return window.AUTH_MODE===`firebase`}function w(e){return!ae()}function T(){let e=new URL(document.baseURI),t=new URL(window.location.href),n=t.pathname.startsWith(e.pathname)?t:e;return n.hash=``,n}function E(){let e=new URL(document.baseURI);return e.hash=``,e.search=``,e}function D(e,t,n,r,i={}){let a=new URL(n);i.projectId&&a.searchParams.set(`p`,i.projectId),i.accountId&&a.searchParams.set(`a`,i.accountId);let o=new URL(e);return o.searchParams.set(`sts`,t),o.searchParams.set(`redirect_uri`,a.toString()),o.searchParams.set(`state`,r),o}function oe(e,t){return`vtsauth=${e}; Path=/; Max-Age=${t}; SameSite=Lax${window.location.protocol===`https:`?`; Secure`:``}`}function se(){document.cookie=oe(`1`,300)}function ce(){document.cookie=oe(``,0)}function O(e={}){let t=D(C(),r.endpoints.sts??`https://sts.vertesia.io`,T(),S(),e);se(),location.replace(t.toString())}function le(){if(!w()||r.authTokenProvider||r.isLocalDev&&r.devAuthToken)return!1;let e=new URLSearchParams(window.location.hash.substring(1));return!(e.get(`token`)&&e.get(`state`))}let k=null,ue=null,A=null;function j(){if(!k)try{if(!r.firebase)throw Error(`Firebase configuration is not available in the environment`);k=s(r.firebase)}catch(e){throw console.error(`Failed to initialize Firebase app:`,e),Error(`Firebase initialization failed - environment may not be properly initialized`,{cause:e})}return k}function de(){return ue||=a(j()),ue}function M(){return A||(A=c(j()),A.tenantId=r.firebase?.tenantId??null),A}async function fe(e){if(r.firebase?.tenantId)return M().tenantId=r.firebase.tenantId,{firebaseTenantId:r.firebase.tenantId,provider:r.firebase.providerType??`oidc`,name:``,label:``};if(!e){console.log(`No tenant name or email specified, skipping tenant setup`);return}if(!r.firebase){console.log(`Firebase configuration is not available in the environment`);return}try{e&&console.log(`Resolving tenant ID from email: ${e}`);let t=3,n=250;for(;t>0;)try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e}),signal:AbortSignal.timeout(5e3)});if(!t)throw Error(`No response received from tenant API`);if(!t.ok){try{let e=await t.json();console.error(`Failed to resolve tenant ID:`,e.error)}catch{console.error(`Failed to resolve tenant ID: HTTP ${t.status}`)}if(t.status===404){console.warn(`Tenant not found for ${e}`);return}throw Error(`HTTP error ${t.status}`)}let n=await t.json();if(n?.firebaseTenantId){let e=M();return e.tenantId=n.firebaseTenantId,r.firebase.providerType=n.provider??`oidc`,console.log(`Tenant ID set to ${e.tenantId}`),n}console.error(`Invalid response format, missing tenantId for ${e}`);return}catch(e){if(t>1)console.warn(`Tenant resolution failed, retrying in ${n}ms...`,e),await new Promise(e=>setTimeout(e,n)),n*=2,t--;else throw e}}catch(e){console.error(`Error setting Firebase tenant:`,e instanceof Error?e.message:`Unknown error`)}}async function pe(e){let t=M().currentUser;return t?t.getIdToken(e).then(n=>(r.logger.debug(`Got Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e}}),n)).catch(n=>(r.logger.error(`Failed to get Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e,error:n}}),console.error(`Failed to get access token`,n),null)):(r.logger.warn(`No user found`),Promise.resolve(null))}let N,P,F=!1;const I=`vt.centralAuthRenewalAt`;function L(){if(!F||!w())return!1;let e=0;try{e=Number(sessionStorage.getItem(I)??`0`)}catch{}if(Number.isFinite(e)&&e>0&&Date.now()-e<6e4)return r.logger.warn(`Central Auth session renewal already attempted; surfacing the failure instead`,{vertesia:{last_attempt_ms_ago:Date.now()-e}}),!1;try{sessionStorage.setItem(I,String(Date.now()))}catch{}r.logger.info(`Renewing an expired Central Auth session through the broker`);let t=D(C(),r.endpoints.sts??`https://sts.vertesia.io`,T(),S());return location.replace(t.toString()),!0}function me(e,t){if(!e)return;let n=`${y}-${e}`;if(t){let r=localStorage.getItem(n)===t;r&&localStorage.removeItem(n),r&&localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&localStorage.removeItem(v);return}localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&(localStorage.removeItem(v),localStorage.removeItem(n))}function he(e){try{let t=i(e);return typeof t.email!=`string`||!t.email?void 0:{email:t.email,name:typeof t.name==`string`&&t.name?t.name:void 0}}catch{return}}function R(e){let t=e.searchParams.has(`a`)||e.searchParams.has(`p`)?void 0:r.defaultAuthSelection,n=e.searchParams.get(`a`)??t?.accountId,i=e.searchParams.get(`p`)??t?.projectId,a=n??(i===void 0?localStorage.getItem(`composableai.lastSelectedAccountId`)??void 0:void 0);return{accountId:a,projectId:i??localStorage.getItem(`composableai.lastSelectedProjectId-${a}`)??void 0}}function z(e){return e?.replace(/\/+$/,``)}function B(e){return i(e)}function V(e){if(!e)return!1;try{return z(B(e).iss)===z(r.endpoints.sts)}catch{return!1}}function ge(e,t,n){let r=B(e);return!(!r.exp||r.exp<=Date.now()/1e3+300||!(r.permissions?.length||r.account_roles?.length||r.project_roles?.length||r.apps?.length)||t&&r.account?.id!==t||n&&r.project?.id!==n)}async function H(a,o,s,c,l=0){r.logger.debug(`Getting/refreshing composable token`,{vertesia:{account_id:o,project_id:s,retry_count:l}});let u=await a();if(!u)throw Error(`No id token found`);let d=r.endpoints.sts;r.logger.debug(`Using STS for token generation`,{vertesia:{account_id:o,project_id:s,sts_url:d}});try{let f=new URL(`${d}/token/issue`),p={type:`user`,account_id:o,project_id:s,expires_at:c?Math.floor(Date.now()/1e3)+c:void 0},m=await fetch(f,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${u}`},body:JSON.stringify(p)}).catch(e=>{throw console.error(`Failed to call STS endpoint`,e),r.logger.error(`Failed to call STS endpoint`,{vertesia:{account_id:o,project_id:s,error:e}}),new Y(`The authentication service could not be reached`,d,{cause:e})});if(u&&m?.status===404){r.logger.debug(`404: User not found - calling ensure-user endpoint`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=await fetch(`${r.endpoints.studio}/auth/ensure-user`,{method:`POST`,headers:{Authorization:`Bearer ${u}`,"Content-Type":`application/json`}});if(e.status===412){r.logger.debug(`412: No invite found - signup required`,{vertesia:{account_id:o,project_id:s}});let e=i(u);throw e?.email?new W(`User not found - signup required`,e.email):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(e.status===403)throw r.logger.warn(`403: Customer-domain user requires an invite to join`,{vertesia:{account_id:o,project_id:s}}),Error(`Customer-domain user requires an invite to join`);if(!e.ok)throw console.error(`Failed to ensure user exists`,e.status),r.logger.error(`Failed to ensure user exists`,{vertesia:{account_id:o,project_id:s,status:e.status}}),Error(`Failed to ensure user exists`);return r.logger.debug(`User ensured - retrying token generation`,{vertesia:{account_id:o,project_id:s}}),H(a,o,s,c,l)}if(u&&m?.status===412){r.logger.info(`412: auth succeeded but user doesn't exist - signup required`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=i(u);throw e?.email?(r.logger.info(`User not found`,{vertesia:{account_id:o,project_id:s,email:e.email}}),new W(`User not found`,e.email)):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(m.status===401)throw r.logger.warn(`STS rejected the identity credential`,{vertesia:{account_id:o,project_id:s,status:m.status}}),new J(`Your sign-in credentials could not be verified`,d,{status:m.status});if(m.status===403){let i=await m.json().catch(()=>void 0),a=he(u);throw i?.errorCode===n?(r.logger.warn(`403: User lacks early-access for this restricted environment`,{vertesia:{account_id:o,project_id:s}}),new X(i.message??`You don't have sufficient permission to visit unstable environments`)):i?.errorCode===e?(r.logger.warn(`STS identity has no accessible account`,{vertesia:{error_code:i.errorCode,status:m.status}}),new q(d,i.message,a)):!i?.errorCode||i.errorCode===t?(r.logger.warn(`STS rejected the requested account or project`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i?.errorCode??t}}),new K(d,o,s,i?.errorCode?i.message:void 0,a)):(r.logger.error(`STS returned an unrecognized forbidden response`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i.errorCode}}),new Y(`The authentication service rejected the request`,d,{status:m.status,errorCode:i.errorCode,cause:i}))}if(!m.ok){let e=await m.text();throw console.error(`STS token generation failed:`,m.status,e),r.logger.error(`STS token generation failed`,{vertesia:{status:m.status,error:e,account_id:o,project_id:s}}),new Y(`The authentication service could not complete sign-in`,d,{status:m.status,cause:e})}let{token:h}=await m.json();return r.logger.debug(`Successfully got token from STS`),h}catch(e){throw e instanceof W||e instanceof G||e instanceof X||e instanceof Error&&e.message===`Customer-domain user requires an invite to join`?e:(console.error(`Failed to get composable token from STS`,e),r.logger.error(`Failed to get composable token from STS`,{vertesia:{account_id:o,project_id:s,error:e}}),new Y(`The authentication service could not complete sign-in`,d,{cause:e}))}}async function _e(e,t,n){return H(pe,e,t,n)}async function ve(e,t,n,r){return H(()=>Promise.resolve(e),t,n,r)}function ye(){return N}async function U(e,t,n,i=!1,a=!1){let o=e??(t===void 0?localStorage.getItem(`composableai.lastSelectedAccountId`)??void 0:void 0),s=t??localStorage.getItem(`composableai.lastSelectedProjectId-${o}`)??void 0,c=r.isLocalDev?r.devAuthToken:void 0,l=c??n??N,u=(!o||P?.account?.id===o)&&(!s||P?.project?.id===s);if(!i&&N&&P&&u&&P.exp>Date.now()/1e3+300)return F=!0,{rawToken:N,token:P,error:!1};if(!i&&V(l)&&ge(l,o,s)){if(N=l,P=B(N),!P.exp)throw Error(`Invalid composable token`);return F=!0,{rawToken:N,token:P,error:!1}}try{if(!c&&!a&&M().currentUser)N=await _e(o,s);else if(c)c&&(N=c);else{let e=await r.authTokenProvider?.()??n??N;N=!i&&e&&V(e)&&ge(e,o,s)?e:e?await H(()=>Promise.resolve(e),o,s):void 0}}catch(e){throw(e instanceof K||e instanceof q||e instanceof J)&&(N=void 0,P=void 0,e instanceof K&&me(o,s)),e instanceof J&&L(),e}if(!N)throw r.logger.error(`Cannot acquire a composable token`,{vertesia:{account_id:o,project_id:s}}),L(),Error(`Cannot acquire a composable token`);if(P=B(N),!P?.exp||!N)throw console.error(`Invalid composable token`,P),r.logger.error(`Invalid composable token`,{vertesia:{account_id:o,project_id:s}}),Error(`Invalid composable token`);return F=!0,{rawToken:N,token:P,error:!1}}var W=class extends Error{email;constructor(e,t){super(e),this.name=`UserNotFoundError`,this.email=t}},G=class extends Error{stsURL;status;errorCode;constructor(e,t,n){super(e,n),this.name=`STSError`,this.stsURL=t,this.status=n?.status,this.errorCode=n?.errorCode}},K=class extends G{accountId;projectId;identity;requestedScope;selectorSource;recoveryUrl;constructor(e,n,r,i,a){super(i??`The requested account or project is not available.`,e,{status:403,errorCode:t}),this.accountId=n,this.projectId=r,this.identity=a,this.name=`RequestedScopeUnavailableError`,this.requestedScope=r?`project`:`account`}};const be=K;var q=class extends G{identity;constructor(t,n,r){super(n??`No accessible account is available for this user.`,t,{status:403,errorCode:e}),this.identity=r,this.name=`NoAccessibleAccountError`}},J=class extends G{constructor(e,t,n){super(e,t,n),this.name=`CredentialError`}},Y=class extends G{constructor(e,t,n){super(e,t,n),this.name=`AuthenticationServiceError`}};function xe(e){return e instanceof K}function Se(e){return e instanceof q}function Ce(e){return e instanceof J}function we(e){return e instanceof Y}var X=class extends Error{constructor(e){super(e),this.name=`RestrictedEnvironmentError`}};function Z(){return{generateState:d(()=>S(),[]),verifyState:d(e=>re(e),[]),clearState:d(()=>ie(),[])}}var Q=class e{isLoading=!0;client;authError;authToken;setSession;lastSelectedAccount;lastSelectedProject;onboardingComplete;constructor(e,t){this.client=e||new te({serverUrl:r.endpoints.studio,storeUrl:r.endpoints.zeno,tokenServerUrl:r.endpoints.sts}),t&&(this.setSession=t),this.logout=this.logout.bind(this),this.signOut=this.signOut.bind(this)}get store(){return this.client.store}get user(){return this.authToken}get account(){return this.authToken?.account}get project(){return this.authToken?.project}get accounts(){return this.authToken?.accounts}get authCallback(){return this.rawAuthToken.then(e=>`Bearer ${e}`)}get rawAuthToken(){return U().then(e=>{let t=e?.rawToken;if(!t)throw Error(`No token available`);return this.authToken=i(t),t})}async refreshAuthToken(){let e=(await U(void 0,void 0,void 0,!0))?.rawToken;if(!e)throw Error(`No token available`);return this.authToken=i(e),this.setSession?.(this.clone()),this.authToken}signOut(){this.logout()}getAccount(){return this.authToken?.account}async login(e,t={}){return this.authError=void 0,this.isLoading=!1,this.client.withAuthCallback(()=>this.authCallback),this.authToken=i(e),console.log(`Logging in as ${this.authToken?.name} with account ${this.authToken?.account.name} (${this.authToken?.account.id}, and project ${this.authToken?.project?.name} (${this.authToken?.project?.id})`),localStorage.setItem(v,this.authToken.account.id),localStorage.setItem(`${y}-${this.authToken.account.id}`,this.authToken.project?.id??``),r.onLogin?.(this.authToken),(t.loadOnboardingStatus??!0)&&await this.fetchOnboardingStatus(),Promise.resolve()}isLoggedIn(){return!!this.authToken}logout(){if(console.log(`Logging out`),w()){console.log(`Using central auth logout`),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0);let e=new URL(C()),t=T();e.pathname=`/logout`,e.searchParams.set(`redirect_uri`,t.toString()),location.replace(e.toString())}else{console.log(`Using Firebase logout`);let e=!!this.authToken;this.authToken&&M().signOut(),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0),e&&location.replace(E().toString())}}async switchAccount(e){localStorage.setItem(v,e),this&&(this.account&&this.project?localStorage.setItem(`${y}-${this.account.id}`,this.project.id):this.account&&localStorage.removeItem(`${y}-${this.account.id}`));let t=E();t.searchParams.set(`a`,e),window.location.replace(t.toString())}async switchProject(e){this.account&&localStorage.setItem(`${y}-${this.account.id}`,e);let t=E();this.account?.id&&t.searchParams.set(`a`,this.account.id),t.searchParams.set(`p`,e),window.location.replace(t.toString())}async fetchAccounts(){return this.client.accounts.list().then(e=>{if(!this.authToken)throw Error(`No token available`);this.authToken.accounts=e,this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch accounts`,e),e})}async fetchProjects(e){return this.client.projects.list([e]).then(t=>{if(!this.authToken)throw Error(`No token available`);this.authToken={...this.authToken,accounts:this.authToken.accounts?.map(n=>n.id===e?{...n,projects:t.filter(t=>t.account===e)}:n)},this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch projects`,e),e})}async fetchOnboardingStatus(){if(!this.project?.id)return!1;if(this.onboardingComplete)return console.log(`Onboarding already completed`),!1;let e=this.onboardingComplete;try{let t=await this.client.account.onboardingProgress();return this.onboardingComplete=Object.values(t).every(e=>e===!0),e!==this.onboardingComplete&&this.setSession?.(this.clone()),e===!1&&this.onboardingComplete}catch(t){console.error(`Error fetching onboarding status:`,t),this.onboardingComplete=!1,e!==this.onboardingComplete&&this.setSession?.(this.clone())}return!1}clone(){let t=new e(this.client);return t.isLoading=this.isLoading,t.authError=this.authError,t.authToken=this.authToken,t.setSession=this.setSession,t.lastSelectedAccount=this.lastSelectedAccount,t.switchAccount=this.switchAccount,t.onboardingComplete=this.onboardingComplete,t}};const $=u(void 0);function Te(){let e=f($);if(!e)throw Error(`useUserSession must be used within a UserSessionProvider`);return e}function Ee(){let{user:e}=Te(),[t,n]=g(null),[r,i]=g(!0),[a,o]=g(null);return p(()=>{(async()=>{if(!e?.email){n(null),i(!1);return}try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e.email})});if(t.ok){let e=await t.json();n(e?{tenantKey:e.name||`unknown`,name:e.label||e.name||`Unknown`,domain:e.domain||[],firebaseTenantId:e.firebaseTenantId,provider:e.provider,logo:e.logo}:null)}else n(null)}catch(e){console.error(`Error loading current tenant:`,e),o(_.getFixedT(null,ee)(`errors.failedToLoadTenantConfig`)),n(null)}finally{i(!1)}})()},[e?.email]),{currentTenant:t,isLoading:r,error:a}}function De(e){let[,t]=e.split(`.`);if(!t)throw Error(`Invalid Vertesia auth token`);let n=t.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(Math.ceil(t.length/4)*4,`=`);return JSON.parse(atob(n))}function Oe({children:e,token:t}){let n=m(()=>{let e=new Q;e.isLoading=!1;try{e.authToken=De(t),e.client.withAuthCallback(()=>Promise.resolve(`Bearer ${t}`)),localStorage.setItem(v,e.authToken.account.id),localStorage.setItem(`${y}-${e.authToken.account.id}`,e.authToken.project?.id??``)}catch(t){e.authError=t instanceof Error?t:Error(String(t))}return e.clone()},[t]);return ne($.Provider,{value:n,children:e})}function ke(){let e=new URL(window.location.href);e.hash=``,window.history.replaceState(window.history.state,``,`${e.pathname}${e.search}`)}function Ae(e,t,n=!1){let r=new URL(e),i=r.searchParams.get(`a`)??void 0,a=r.searchParams.get(`p`)??void 0;return i&&a&&i===t.accountId&&a===t.projectId?(r.searchParams.delete(`a`),r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):a&&a===t.projectId?(r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):i&&i===t.accountId?(r.searchParams.delete(`a`),t.requestedScope=`account`,t.selectorSource=`url`):(t.requestedScope=t.projectId?`project`:`account`,t.selectorSource=`persisted`),n&&(r.hash=``),t.recoveryUrl=r.toString(),r}function je({children:e,loadOnboardingStatus:n=!0}){let i=new URLSearchParams(location.hash.substring(1)),a=i.get(`token`),o=i.get(`state`),[s,c]=g(new Q),{verifyState:u,clearState:d}=Z(),f=h(!1),m=h(void 0),ee=(e,n=!1)=>{let i=Ae(new URL(window.location.href),e,n);window.history.replaceState(window.history.state,``,i),r.logger.warn(`Sanitized an unavailable authentication scope`,{vertesia:{account_id:e.accountId,project_id:e.projectId,error_code:t,selector_source:e.selectorSource,requested_scope:e.requestedScope,recovery_action:`url_sanitized`}})},_=(e,t=!1)=>e instanceof K||e instanceof q||e instanceof J||e instanceof Y||e instanceof W||e instanceof X?(e instanceof K?ee(e,t):t&&ke(),s.isLoading=!1,s.authError=e,c(s.clone()),!0):!1;return m.current=()=>{if(f.current){r.logger.debug(`Skipping duplicate auth flow initiation`);return}f.current=!0,r.logger.debug(`Starting auth flow`);let{accountId:e,projectId:t}=R(new URL(window.location.href));if(r.logger.debug(`Selected account and project`,{vertesia:{account_id:e,project_id:t}}),r.isLocalDev&&r.devAuthToken){s.setSession=c,U(e,t,r.devAuthToken).then(e=>s.login(e.rawToken).then(()=>c(s.clone()))).catch(n=>{_(n)||(console.error(`Failed to initialize dev auth token`,n),r.logger.error(`Failed to initialize dev auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))});return}if(a&&o){s.setSession=c;let i=u(o);i?(console.error(`Auth: invalid state: ${i}`),r.logger.error(`Invalid state: ${i}`,{vertesia:{state:o}}),O({accountId:e,projectId:t})):d(),U(e,t,a,!1,w()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>{c(s.clone()),ke()})).catch(n=>{_(n,!0)||(console.error(`Failed to fetch user token from studio, redirecting to central auth`,n),r.logger.error(`Failed to fetch user token from studio, redirecting to central auth`,{vertesia:{error:n}}),O({accountId:e,projectId:t}))});return}let i=!1,p,m=()=>{if(!i){if(!s.isLoggedIn()){if(r.logger.debug(`Not logged in & no token/state`,{vertesia:{account_id:e,project_id:t}}),w()){r.logger.debug(`Redirecting to central auth with selection`,{vertesia:{account_id:e,project_id:t}}),O({accountId:e,projectId:t});return}r.logger.debug(`Host is in Firebase auth allowlist`,{vertesia:{account_id:e,project_id:t}})}p=l(M(),async i=>{i?(r.logger.debug(`Successful login with firebase`,{vertesia:{account_id:e,project_id:t}}),s.setSession=c,await U(e,t,void 0,!1,w()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>c(s.clone()))).catch(n=>{_(n)||(console.error(`Unexpected failure while fetching a user token`,n),r.logger.error(`Unexpected failure while fetching a user token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.logout(),s.isLoading=!1,s.authError=n,c(s.clone()))})):(r.logger.debug(`Using anonymous user`,{vertesia:{account_id:e,project_id:t}}),s.client.withAuthCallback(void 0),s.logout(),c(s.clone()))})}};return r.authTokenProvider?(s.setSession=c,r.authTokenProvider().then(async r=>{if(i)return;if(!r){m();return}let a=await U(e,t,r,!1,w());await s.login(a.rawToken,{loadOnboardingStatus:n}),i||c(s.clone())}).catch(n=>{i||_(n)||(console.warn(`Auth: failed to initialize injected auth token`,n),r.logger.warn(`Failed to initialize injected auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))}),()=>{i=!0,f.current=!1,p?.()}):(m(),()=>{i=!0,f.current=!1,p?.()})},p(()=>m.current?.(),[]),ne($.Provider,{value:s,children:e})}function Me(){return{tagUserSession:async e=>{let t=window.localStorage.getItem(`composableSignupData`);if(!e){console.error(`No user found -- skipping tagging`);return}t&&window.localStorage.removeItem(`composableSignupData`)},trackEvent:(e,t)=>{r.isProd||console.debug(`track event`,e,t),r.firebase?.apiKey&&o(de(),e,{...t,debug_mode:!r.isProd})}}}export{Y as AuthenticationServiceError,J as CredentialError,Oe as DevSessionProvider,v as LastSelectedAccountId_KEY,y as LastSelectedProjectId_KEY,q as NoAccessibleAccountError,K as RequestedScopeUnavailableError,X as RestrictedEnvironmentError,G as STSError,be as TokenAuthorizationError,W as UserNotFoundError,Q as UserSession,$ as UserSessionContext,je as UserSessionProvider,D as buildCentralAuthRedirectUrl,ce as clearCentralAuthRoundTripMarker,H as fetchComposableToken,_e as fetchComposableTokenFromFirebaseToken,ve as fetchComposableTokenFromVertesiaToken,U as getComposableToken,ye as getCurrentVertesiaToken,de as getFirebaseAnalytics,j as getFirebaseApp,M as getFirebaseAuth,pe as getFirebaseAuthToken,we as isAuthenticationServiceError,le as isCentralAuthRedirectPending,Ce as isCredentialError,Se as isNoAccessibleAccountError,xe as isRequestedScopeUnavailableError,O as redirectToCentralAuth,R as resolveAuthSelection,Ae as sanitizeRejectedScopeUrl,fe as setFirebaseTenant,Z as useAuthState,Ee as useCurrentTenant,Me as useUXTracking,Te as useUserSession};
|
|
1
|
+
import{NO_ACCESSIBLE_ACCOUNT_ERROR_CODE as e,REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE as t,RESTRICTED_ENVIRONMENT_ERROR_CODE as n}from"@vertesia/common";import{Env as r}from"@vertesia/ui/env";import{jwtDecode as i}from"jwt-decode";import{getAnalytics as a,logEvent as o}from"firebase/analytics";import{initializeApp as s}from"firebase/app";import{getAuth as c,onAuthStateChanged as l}from"firebase/auth";import{createContext as u,useCallback as d,useContext as f,useEffect as p,useMemo as m,useRef as h,useState as g}from"react";import{NAMESPACE as _,i18nInstance as v}from"@vertesia/ui/i18n";import{VertesiaClient as y}from"@vertesia/client";import{jsx as b}from"react/jsx-runtime";const x=`composableai.lastSelectedAccountId`,S=`composableai.lastSelectedProjectId`,ee=`auth_state`,te=`auth_state_expiry`;function C(){let e=crypto.randomUUID();return sessionStorage.setItem(ee,e),sessionStorage.setItem(te,String(Date.now()+3e5)),e}function ne(e){if(!e)return`Missing state`;let t=sessionStorage.getItem(ee),n=parseInt(sessionStorage.getItem(te)||`0`,10);if(t!==e)return`State mismatched (${t} !== ${e})`;if(Date.now()>n)return`State expired`}function re(){sessionStorage.removeItem(ee),sessionStorage.removeItem(te)}function w(){if(typeof window>`u`||window.parent!==window)return!1;let e=window.__VERTESIA_RUNTIME_CONFIG__;return e?.authMode===`central`&&e.gatewaySession===!0}function ie(){let e=new URL(window.location.href),t=new URL(`/__appgen/auth/login`,e.origin);return t.searchParams.set(`target`,`${e.pathname}${e.search}${e.hash}`),t.toString()}async function T(e,t){let n=new Request(e,t);if(new URL(n.url).origin!==window.location.origin)throw Error(`Gateway session requests must stay on the application origin`);let r=new Headers(n.headers);r.delete(`authorization`),r.set(`x-vertesia-app-session`,`1`);let i=await fetch(new Request(n,{headers:r,credentials:`same-origin`,cache:`no-store`}));return i.status===401&&i.headers.get(`x-vertesia-session-required`)===`1`?(window.location.replace(ie()),new Promise(()=>{})):i}async function ae(){let e=await T(new URL(`/__appgen/session`,window.location.origin).toString());if(!e.ok)throw Error(`Application session could not be loaded (${e.status})`);let t=await e.json();if(!t.sub||!t.account?.id||!t.project?.id)throw Error(`Application session returned invalid user information`);return t}async function oe(){let e=await T(new URL(`/__appgen/session/logout`,window.location.origin).toString(),{method:`POST`});if(!e.ok)throw Error(`Application sign-out failed (${e.status})`)}const E=`vertesia.oauth.transaction`,D=`vertesia.oauth.access`;let O;function k(){return!(!r.oauth||window.parent!==window||window.AUTH_MODE===`firebase`||w())}function se(e){return btoa(String.fromCharCode(...e)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function ce(){return se(crypto.getRandomValues(new Uint8Array(32)))}function le(e){let t=new URL(e);if(t.protocol!==`https:`||t.username||t.password)throw Error(`OAuth endpoint must use HTTPS`);return t}function ue(){sessionStorage.removeItem(D),sessionStorage.removeItem(E)}async function de(){let e=r.oauth;if(!e)throw Error(`Application OAuth is not configured`);let t=e.clientId.trim();if(!t)throw Error(`OAuth client ID is required`);let n=new URL(e.redirectUri),a=n.hostname===`localhost`||n.hostname.endsWith(`.localhost`)||n.hostname===`[::1]`||/^127\.\d+\.\d+\.\d+$/.test(n.hostname);if(n.protocol!==`https:`&&!(a&&n.protocol===`http:`))throw Error(`OAuth callback must use HTTPS or loopback HTTP`);let o=n.toString();if(new URL(o).origin!==window.location.origin)throw Error(`OAuth callback must be same-origin`);let s=r.endpoints.sts.replace(/\/+$/,``),c=new URL(window.location.href),l=c.origin+c.pathname===new URL(o).origin+new URL(o).pathname,u=l?c.searchParams.get(`state`):null,d=l?c.searchParams.get(`code`):null,f=l?c.searchParams.get(`error`):null,p;if(u||d||f){let e=sessionStorage.getItem(E);if(sessionStorage.removeItem(E),p=e?JSON.parse(e):void 0,!p||p.state!==u||p.clientId!==t||p.redirectUri!==o||p.issuer!==s||Date.now()-p.created>6e5||p.created>Date.now())throw Error(`Invalid or expired OAuth login state`);if(f||!d)throw Error(`Application sign-in was not completed (${f||`missing code`})`)}else{let e=sessionStorage.getItem(D);if(e){let n=JSON.parse(e),r=i(n.token);if(n.clientId===t&&n.issuer===s&&r.exp>Date.now()/1e3+30&&(!c.searchParams.get(`p`)||r.project?.id===c.searchParams.get(`p`))&&(!c.searchParams.get(`a`)||r.account?.id===c.searchParams.get(`a`)))return n.token}}let m=await fetch(`${s}/.well-known/oauth-authorization-server`);if(!m.ok)throw Error(`OAuth discovery failed (${m.status})`);let h=await m.json();if(h.issuer.replace(/\/+$/,``)!==s)throw Error(`OAuth issuer mismatch`);let g=le(h.authorization_endpoint),_=le(h.token_endpoint);if(p&&d){let e=await fetch(_,{method:`POST`,headers:{"Content-Type":`application/x-www-form-urlencoded`},body:new URLSearchParams({grant_type:`authorization_code`,code:d,client_id:t,redirect_uri:o,code_verifier:p.verifier})});if(!e.ok)throw Error(`OAuth code exchange failed (${e.status})`);let n=await e.json();if(!n.access_token||n.token_type?.toLowerCase()!==`bearer`)throw Error(`Invalid OAuth grant`);let r=i(n.access_token);if(r.iss.replace(/\/+$/,``)!==s||r.client_id!==t||r.exp<=Date.now()/1e3)throw Error(`OAuth grant does not match this application`);sessionStorage.setItem(D,JSON.stringify({token:n.access_token,clientId:t,issuer:s}));let a=new URL(p.target);if(a.origin!==window.location.origin)throw Error(`Invalid OAuth return target`);return window.history.replaceState(window.history.state,``,a),n.access_token}let v=e.scopes??[`openid`,`profile`];if(t.startsWith(`https://`)){let n=await fetch(le(t),{cache:`no-store`});if(!n.ok)throw Error(`Application CIMD unavailable (${n.status})`);let r=await n.json();if(!r.redirect_uris?.includes(o))throw Error(`Application CIMD does not allow this callback`);!e.scopes&&r.scope&&(v=r.scope.split(/\s+/))}let y=ce(),b={state:ce(),verifier:y,clientId:t,redirectUri:o,issuer:s,target:c.toString(),created:Date.now()},x=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(y));g.searchParams.set(`client_id`,t),g.searchParams.set(`redirect_uri`,o),g.searchParams.set(`response_type`,`code`),g.searchParams.set(`state`,b.state),g.searchParams.set(`code_challenge_method`,`S256`),g.searchParams.set(`code_challenge`,se(new Uint8Array(x))),g.searchParams.set(`scope`,v.filter(e=>e!==`offline_access`).join(` `));let S=c.searchParams.get(`p`);return S&&g.searchParams.set(`project_id`,S),sessionStorage.setItem(E,JSON.stringify(b)),window.location.replace(g.toString()),new Promise(()=>{})}function A(){return O??=de().finally(()=>{O=void 0}),O}function fe(){return r.endpoints.auth||`https://auth.vertesia.io/`}function pe(e){return window.AUTH_MODE===`firebase`}function j(e){return!pe()}function M(){let e=new URL(document.baseURI),t=new URL(window.location.href),n=t.pathname.startsWith(e.pathname)?t:e;return n.hash=``,n}function N(){let e=new URL(document.baseURI);return e.hash=``,e.search=``,e}function P(e,t,n,r,i={}){let a=new URL(n);i.projectId&&a.searchParams.set(`p`,i.projectId),i.accountId&&a.searchParams.set(`a`,i.accountId);let o=new URL(e);return o.searchParams.set(`sts`,t),o.searchParams.set(`redirect_uri`,a.toString()),o.searchParams.set(`state`,r),o}function me(e,t){return`vtsauth=${e}; Path=/; Max-Age=${t}; SameSite=Lax${window.location.protocol===`https:`?`; Secure`:``}`}function he(){document.cookie=me(`1`,300)}function ge(){document.cookie=me(``,0)}function F(e={}){if(k()){A().catch(e=>r.logger.error(`Application OAuth sign-in failed`,e));return}if(w()){window.location.replace(ie());return}let t=P(fe(),r.endpoints.sts??`https://sts.vertesia.io`,M(),C(),e);he(),location.replace(t.toString())}function _e(){if(w()||k()||!j()||r.authTokenProvider||r.isLocalDev&&r.devAuthToken)return!1;let e=new URLSearchParams(window.location.hash.substring(1));return!(e.get(`token`)&&e.get(`state`))}let I=null,ve=null,L=null;function R(){if(!I)try{if(!r.firebase)throw Error(`Firebase configuration is not available in the environment`);I=s(r.firebase)}catch(e){throw console.error(`Failed to initialize Firebase app:`,e),Error(`Firebase initialization failed - environment may not be properly initialized`,{cause:e})}return I}function ye(){return ve||=a(R()),ve}function z(){return L||(L=c(R()),L.tenantId=r.firebase?.tenantId??null),L}async function be(e){if(r.firebase?.tenantId)return z().tenantId=r.firebase.tenantId,{firebaseTenantId:r.firebase.tenantId,provider:r.firebase.providerType??`oidc`,name:``,label:``};if(!e){console.log(`No tenant name or email specified, skipping tenant setup`);return}if(!r.firebase){console.log(`Firebase configuration is not available in the environment`);return}try{e&&console.log(`Resolving tenant ID from email: ${e}`);let t=3,n=250;for(;t>0;)try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e}),signal:AbortSignal.timeout(5e3)});if(!t)throw Error(`No response received from tenant API`);if(!t.ok){try{let e=await t.json();console.error(`Failed to resolve tenant ID:`,e.error)}catch{console.error(`Failed to resolve tenant ID: HTTP ${t.status}`)}if(t.status===404){console.warn(`Tenant not found for ${e}`);return}throw Error(`HTTP error ${t.status}`)}let n=await t.json();if(n?.firebaseTenantId){let e=z();return e.tenantId=n.firebaseTenantId,r.firebase.providerType=n.provider??`oidc`,console.log(`Tenant ID set to ${e.tenantId}`),n}console.error(`Invalid response format, missing tenantId for ${e}`);return}catch(e){if(t>1)console.warn(`Tenant resolution failed, retrying in ${n}ms...`,e),await new Promise(e=>setTimeout(e,n)),n*=2,t--;else throw e}}catch(e){console.error(`Error setting Firebase tenant:`,e instanceof Error?e.message:`Unknown error`)}}async function xe(e){let t=z().currentUser;return t?t.getIdToken(e).then(n=>(r.logger.debug(`Got Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e}}),n)).catch(n=>(r.logger.error(`Failed to get Firebase token`,{vertesia:{user_email:t.email,user_name:t.displayName,user_id:t.uid,refresh:e,error:n}}),console.error(`Failed to get access token`,n),null)):(r.logger.warn(`No user found`),Promise.resolve(null))}let B,V,H=!1;const Se=`vt.centralAuthRenewalAt`;function Ce(){if(!H||!j())return!1;let e=0;try{e=Number(sessionStorage.getItem(Se)??`0`)}catch{}if(Number.isFinite(e)&&e>0&&Date.now()-e<6e4)return r.logger.warn(`Central Auth session renewal already attempted; surfacing the failure instead`,{vertesia:{last_attempt_ms_ago:Date.now()-e}}),!1;try{sessionStorage.setItem(Se,String(Date.now()))}catch{}r.logger.info(`Renewing an expired Central Auth session through the broker`);let t=P(fe(),r.endpoints.sts??`https://sts.vertesia.io`,M(),C());return location.replace(t.toString()),!0}function we(e,t){if(!e)return;let n=`${S}-${e}`;if(t){let r=localStorage.getItem(n)===t;r&&localStorage.removeItem(n),r&&localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&localStorage.removeItem(x);return}localStorage.getItem(`composableai.lastSelectedAccountId`)===e&&(localStorage.removeItem(x),localStorage.removeItem(n))}function Te(e){try{let t=i(e);return typeof t.email!=`string`||!t.email?void 0:{email:t.email,name:typeof t.name==`string`&&t.name?t.name:void 0}}catch{return}}function Ee(e){let t=e.searchParams.has(`a`)||e.searchParams.has(`p`)?void 0:r.defaultAuthSelection,n=e.searchParams.get(`a`)??t?.accountId,i=e.searchParams.get(`p`)??t?.projectId,a=n??(i===void 0?localStorage.getItem(`composableai.lastSelectedAccountId`)??void 0:void 0);return{accountId:a,projectId:i??localStorage.getItem(`composableai.lastSelectedProjectId-${a}`)??void 0}}function De(e){return e?.replace(/\/+$/,``)}function U(e){return i(e)}function Oe(e){if(!e)return!1;try{return De(U(e).iss)===De(r.endpoints.sts)}catch{return!1}}function ke(e,t,n){let r=U(e);return!(!r.exp||r.exp<=Date.now()/1e3+300||!(r.permissions?.length||r.account_roles?.length||r.project_roles?.length||r.apps?.length)||t&&r.account?.id!==t||n&&r.project?.id!==n)}async function W(a,o,s,c,l=0){r.logger.debug(`Getting/refreshing composable token`,{vertesia:{account_id:o,project_id:s,retry_count:l}});let u=await a();if(!u)throw Error(`No id token found`);let d=r.endpoints.sts;r.logger.debug(`Using STS for token generation`,{vertesia:{account_id:o,project_id:s,sts_url:d}});try{let f=new URL(`${d}/token/issue`),p={type:`user`,account_id:o,project_id:s,expires_at:c?Math.floor(Date.now()/1e3)+c:void 0},m=await fetch(f,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${u}`},body:JSON.stringify(p)}).catch(e=>{throw console.error(`Failed to call STS endpoint`,e),r.logger.error(`Failed to call STS endpoint`,{vertesia:{account_id:o,project_id:s,error:e}}),new Z(`The authentication service could not be reached`,d,{cause:e})});if(u&&m?.status===404){r.logger.debug(`404: User not found - calling ensure-user endpoint`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=await fetch(`${r.endpoints.studio}/auth/ensure-user`,{method:`POST`,headers:{Authorization:`Bearer ${u}`,"Content-Type":`application/json`}});if(e.status===412){r.logger.debug(`412: No invite found - signup required`,{vertesia:{account_id:o,project_id:s}});let e=i(u);throw e?.email?new K(`User not found - signup required`,e.email):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(e.status===403)throw r.logger.warn(`403: Customer-domain user requires an invite to join`,{vertesia:{account_id:o,project_id:s}}),Error(`Customer-domain user requires an invite to join`);if(!e.ok)throw console.error(`Failed to ensure user exists`,e.status),r.logger.error(`Failed to ensure user exists`,{vertesia:{account_id:o,project_id:s,status:e.status}}),Error(`Failed to ensure user exists`);return r.logger.debug(`User ensured - retrying token generation`,{vertesia:{account_id:o,project_id:s}}),W(a,o,s,c,l)}if(u&&m?.status===412){r.logger.info(`412: auth succeeded but user doesn't exist - signup required`,{vertesia:{account_id:o,project_id:s,status:m?.status}});let e=i(u);throw e?.email?(r.logger.info(`User not found`,{vertesia:{account_id:o,project_id:s,email:e.email}}),new K(`User not found`,e.email)):(r.logger.error(`No email found in id token`),Error(`No email found in id token`))}if(m.status===401)throw r.logger.warn(`STS rejected the identity credential`,{vertesia:{account_id:o,project_id:s,status:m.status}}),new X(`Your sign-in credentials could not be verified`,d,{status:m.status});if(m.status===403){let i=await m.json().catch(()=>void 0),a=Te(u);throw i?.errorCode===n?(r.logger.warn(`403: User lacks early-access for this restricted environment`,{vertesia:{account_id:o,project_id:s}}),new Q(i.message??`You don't have sufficient permission to visit unstable environments`)):i?.errorCode===e?(r.logger.warn(`STS identity has no accessible account`,{vertesia:{error_code:i.errorCode,status:m.status}}),new Y(d,i.message,a)):!i?.errorCode||i.errorCode===t?(r.logger.warn(`STS rejected the requested account or project`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i?.errorCode??t}}),new J(d,o,s,i?.errorCode?i.message:void 0,a)):(r.logger.error(`STS returned an unrecognized forbidden response`,{vertesia:{account_id:o,project_id:s,status:m.status,error_code:i.errorCode}}),new Z(`The authentication service rejected the request`,d,{status:m.status,errorCode:i.errorCode,cause:i}))}if(!m.ok){let e=await m.text();throw console.error(`STS token generation failed:`,m.status,e),r.logger.error(`STS token generation failed`,{vertesia:{status:m.status,error:e,account_id:o,project_id:s}}),new Z(`The authentication service could not complete sign-in`,d,{status:m.status,cause:e})}let{token:h}=await m.json();return r.logger.debug(`Successfully got token from STS`),h}catch(e){throw e instanceof K||e instanceof q||e instanceof Q||e instanceof Error&&e.message===`Customer-domain user requires an invite to join`?e:(console.error(`Failed to get composable token from STS`,e),r.logger.error(`Failed to get composable token from STS`,{vertesia:{account_id:o,project_id:s,error:e}}),new Z(`The authentication service could not complete sign-in`,d,{cause:e}))}}async function Ae(e,t,n){return W(xe,e,t,n)}async function je(e,t,n,r){return W(()=>Promise.resolve(e),t,n,r)}function Me(){return B}async function G(e,t,n,i=!1,a=!1){let o=e??(t===void 0?localStorage.getItem(`composableai.lastSelectedAccountId`)??void 0:void 0),s=t??localStorage.getItem(`composableai.lastSelectedProjectId-${o}`)??void 0,c=r.isLocalDev?r.devAuthToken:void 0,l=c??n??B,u=(!o||V?.account?.id===o)&&(!s||V?.project?.id===s);if(!i&&B&&V&&u&&V.exp>Date.now()/1e3+300)return H=!0,{rawToken:B,token:V,error:!1};if(!i&&Oe(l)&&ke(l,o,s)){if(B=l,V=U(B),!V.exp)throw Error(`Invalid composable token`);return H=!0,{rawToken:B,token:V,error:!1}}try{if(!c&&!a&&z().currentUser)B=await Ae(o,s);else if(c)c&&(B=c);else{let e=await r.authTokenProvider?.()??n??B;B=!i&&e&&Oe(e)&&ke(e,o,s)?e:e?await W(()=>Promise.resolve(e),o,s):void 0}}catch(e){throw(e instanceof J||e instanceof Y||e instanceof X)&&(B=void 0,V=void 0,e instanceof J&&we(o,s)),e instanceof X&&Ce(),e}if(!B)throw r.logger.error(`Cannot acquire a composable token`,{vertesia:{account_id:o,project_id:s}}),Ce(),Error(`Cannot acquire a composable token`);if(V=U(B),!V?.exp||!B)throw console.error(`Invalid composable token`,V),r.logger.error(`Invalid composable token`,{vertesia:{account_id:o,project_id:s}}),Error(`Invalid composable token`);return H=!0,{rawToken:B,token:V,error:!1}}var K=class extends Error{email;constructor(e,t){super(e),this.name=`UserNotFoundError`,this.email=t}},q=class extends Error{stsURL;status;errorCode;constructor(e,t,n){super(e,n),this.name=`STSError`,this.stsURL=t,this.status=n?.status,this.errorCode=n?.errorCode}},J=class extends q{accountId;projectId;identity;requestedScope;selectorSource;recoveryUrl;constructor(e,n,r,i,a){super(i??`The requested account or project is not available.`,e,{status:403,errorCode:t}),this.accountId=n,this.projectId=r,this.identity=a,this.name=`RequestedScopeUnavailableError`,this.requestedScope=r?`project`:`account`}};const Ne=J;var Y=class extends q{identity;constructor(t,n,r){super(n??`No accessible account is available for this user.`,t,{status:403,errorCode:e}),this.identity=r,this.name=`NoAccessibleAccountError`}},X=class extends q{constructor(e,t,n){super(e,t,n),this.name=`CredentialError`}},Z=class extends q{constructor(e,t,n){super(e,t,n),this.name=`AuthenticationServiceError`}};function Pe(e){return e instanceof J}function Fe(e){return e instanceof Y}function Ie(e){return e instanceof X}function Le(e){return e instanceof Z}var Q=class extends Error{constructor(e){super(e),this.name=`RestrictedEnvironmentError`}};function Re(){return{generateState:d(()=>C(),[]),verifyState:d(e=>ne(e),[]),clearState:d(()=>re(),[])}}var ze=class e{isLoading=!0;client;authError;authToken;setSession;lastSelectedAccount;lastSelectedProject;onboardingComplete;constructor(e,t){this.client=e||new y({serverUrl:w()?`${window.location.origin}/__appgen/session/studio`:r.endpoints.studio,storeUrl:w()?`${window.location.origin}/__appgen/session/store`:r.endpoints.zeno,tokenServerUrl:r.endpoints.sts,fetch:w()?T:void 0}),t&&(this.setSession=t),this.logout=this.logout.bind(this),this.signOut=this.signOut.bind(this)}get store(){return this.client.store}get user(){return this.authToken}get account(){return this.authToken?.account}get project(){return this.authToken?.project}get accounts(){return this.authToken?.accounts}get authCallback(){return this.rawAuthToken.then(e=>`Bearer ${e}`)}get rawAuthToken(){return k()?A():w()?Promise.reject(Error(`Gateway session credentials are not available to application JavaScript`)):G().then(e=>{let t=e?.rawToken;if(!t)throw Error(`No token available`);return this.authToken=i(t),t})}async refreshAuthToken(){if(w()){let e=await this.loginGatewaySession();return this.setSession?.(this.clone()),e}if(k())return ue(),this.authToken=i(await A()),this.setSession?.(this.clone()),this.authToken;let e=(await G(void 0,void 0,void 0,!0))?.rawToken;if(!e)throw Error(`No token available`);return this.authToken=i(e),this.setSession?.(this.clone()),this.authToken}signOut(){this.logout()}getAccount(){return this.authToken?.account}async login(e,t={}){return this.authError=void 0,this.isLoading=!1,this.client.withAuthCallback(()=>this.authCallback),this.authToken=i(e),console.log(`Logging in as ${this.authToken?.name} with account ${this.authToken?.account.name} (${this.authToken?.account.id}, and project ${this.authToken?.project?.name} (${this.authToken?.project?.id})`),localStorage.setItem(x,this.authToken.account.id),localStorage.setItem(`${S}-${this.authToken.account.id}`,this.authToken.project?.id??``),r.onLogin?.(this.authToken),(t.loadOnboardingStatus??!0)&&await this.fetchOnboardingStatus(),Promise.resolve()}async loginGatewaySession(){return this.authToken=await ae(),this.client.withAuthCallback(void 0),this.authError=void 0,this.isLoading=!1,r.onLogin?.(this.authToken),this.authToken}isLoggedIn(){return!!this.authToken}logout(){if(console.log(`Logging out`),w()){oe().then(()=>{this.authToken=void 0,this.authError=void 0,this.isLoading=!1,r.onLogout?.(),this.setSession?.(this.clone())}).catch(e=>{this.authError=e instanceof Error?e:Error(String(e)),this.setSession?.(this.clone())});return}if(k()){ue(),this.client.withAuthCallback(void 0),this.authToken=void 0,this.authError=void 0,this.isLoading=!1,r.onLogout?.(),this.setSession?.(this.clone());return}if(j()){console.log(`Using central auth logout`),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0);let e=new URL(fe()),t=M();e.pathname=`/logout`,e.searchParams.set(`redirect_uri`,t.toString()),location.replace(e.toString())}else{console.log(`Using Firebase logout`);let e=!!this.authToken;this.authToken&&z().signOut(),this.authError=void 0,this.isLoading=!1,this.authToken=void 0,this.setSession=void 0,this.client.withAuthCallback(void 0),e&&location.replace(N().toString())}}async switchAccount(e){localStorage.setItem(x,e),this&&(this.account&&this.project?localStorage.setItem(`${S}-${this.account.id}`,this.project.id):this.account&&localStorage.removeItem(`${S}-${this.account.id}`));let t=N();t.searchParams.set(`a`,e),window.location.replace(t.toString())}async switchProject(e){this.account&&localStorage.setItem(`${S}-${this.account.id}`,e);let t=N();this.account?.id&&t.searchParams.set(`a`,this.account.id),t.searchParams.set(`p`,e),window.location.replace(t.toString())}async fetchAccounts(){return this.client.accounts.list().then(e=>{if(!this.authToken)throw Error(`No token available`);this.authToken.accounts=e,this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch accounts`,e),e})}async fetchProjects(e){return this.client.projects.list([e]).then(t=>{if(!this.authToken)throw Error(`No token available`);this.authToken={...this.authToken,accounts:this.authToken.accounts?.map(n=>n.id===e?{...n,projects:t.filter(t=>t.account===e)}:n)},this.setSession?.(this.clone())}).catch(e=>{throw console.error(`Failed to fetch projects`,e),e})}async fetchOnboardingStatus(){if(!this.project?.id)return!1;if(this.onboardingComplete)return console.log(`Onboarding already completed`),!1;let e=this.onboardingComplete;try{let t=await this.client.account.onboardingProgress();return this.onboardingComplete=Object.values(t).every(e=>e===!0),e!==this.onboardingComplete&&this.setSession?.(this.clone()),e===!1&&this.onboardingComplete}catch(t){console.error(`Error fetching onboarding status:`,t),this.onboardingComplete=!1,e!==this.onboardingComplete&&this.setSession?.(this.clone())}return!1}clone(){let t=new e(this.client);return t.isLoading=this.isLoading,t.authError=this.authError,t.authToken=this.authToken,t.setSession=this.setSession,t.lastSelectedAccount=this.lastSelectedAccount,t.switchAccount=this.switchAccount,t.onboardingComplete=this.onboardingComplete,t}};const $=u(void 0);function Be(){let e=f($);if(!e)throw Error(`useUserSession must be used within a UserSessionProvider`);return e}function Ve(){let{user:e}=Be(),[t,n]=g(null),[r,i]=g(!0),[a,o]=g(null);return p(()=>{(async()=>{if(!e?.email){n(null),i(!1);return}try{let t=await fetch(`/api/resolve-tenant`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({tenantEmail:e.email})});if(t.ok){let e=await t.json();n(e?{tenantKey:e.name||`unknown`,name:e.label||e.name||`Unknown`,domain:e.domain||[],firebaseTenantId:e.firebaseTenantId,provider:e.provider,logo:e.logo}:null)}else n(null)}catch(e){console.error(`Error loading current tenant:`,e),o(v.getFixedT(null,_)(`errors.failedToLoadTenantConfig`)),n(null)}finally{i(!1)}})()},[e?.email]),{currentTenant:t,isLoading:r,error:a}}function He(e){let[,t]=e.split(`.`);if(!t)throw Error(`Invalid Vertesia auth token`);let n=t.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(Math.ceil(t.length/4)*4,`=`);return JSON.parse(atob(n))}function Ue({children:e,token:t}){let n=m(()=>{let e=new ze;e.isLoading=!1;try{e.authToken=He(t),e.client.withAuthCallback(()=>Promise.resolve(`Bearer ${t}`)),localStorage.setItem(x,e.authToken.account.id),localStorage.setItem(`${S}-${e.authToken.account.id}`,e.authToken.project?.id??``)}catch(t){e.authError=t instanceof Error?t:Error(String(t))}return e.clone()},[t]);return b($.Provider,{value:n,children:e})}function We(){let e=new URL(window.location.href);e.hash=``,window.history.replaceState(window.history.state,``,`${e.pathname}${e.search}`)}function Ge(e,t,n=!1){let r=new URL(e),i=r.searchParams.get(`a`)??void 0,a=r.searchParams.get(`p`)??void 0;return i&&a&&i===t.accountId&&a===t.projectId?(r.searchParams.delete(`a`),r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):a&&a===t.projectId?(r.searchParams.delete(`p`),t.requestedScope=`project`,t.selectorSource=`url`):i&&i===t.accountId?(r.searchParams.delete(`a`),t.requestedScope=`account`,t.selectorSource=`url`):(t.requestedScope=t.projectId?`project`:`account`,t.selectorSource=`persisted`),n&&(r.hash=``),t.recoveryUrl=r.toString(),r}function Ke({children:e,loadOnboardingStatus:n=!0}){let i=new URLSearchParams(location.hash.substring(1)),a=i.get(`token`),o=i.get(`state`),[s,c]=g(new ze),{verifyState:u,clearState:d}=Re(),f=h(!1),m=h(void 0),_=(e,n=!1)=>{let i=Ge(new URL(window.location.href),e,n);window.history.replaceState(window.history.state,``,i),r.logger.warn(`Sanitized an unavailable authentication scope`,{vertesia:{account_id:e.accountId,project_id:e.projectId,error_code:t,selector_source:e.selectorSource,requested_scope:e.requestedScope,recovery_action:`url_sanitized`}})},v=(e,t=!1)=>e instanceof J||e instanceof Y||e instanceof X||e instanceof Z||e instanceof K||e instanceof Q?(e instanceof J?_(e,t):t&&We(),s.isLoading=!1,s.authError=e,c(s.clone()),!0):!1;return m.current=()=>{if(f.current){r.logger.debug(`Skipping duplicate auth flow initiation`);return}f.current=!0,r.logger.debug(`Starting auth flow`);let{accountId:e,projectId:t}=Ee(new URL(window.location.href));if(r.logger.debug(`Selected account and project`,{vertesia:{account_id:e,project_id:t}}),w()||k()){let e=!1;return s.setSession=c,(w()?s.loginGatewaySession():A().then(e=>s.login(e,{loadOnboardingStatus:!1}))).then(()=>{e||c(s.clone())}).catch(t=>{e||(s.isLoading=!1,s.authError=t instanceof Error?t:Error(String(t)),c(s.clone()))}),()=>{e=!0,f.current=!1}}if(r.isLocalDev&&r.devAuthToken){s.setSession=c,G(e,t,r.devAuthToken).then(e=>s.login(e.rawToken).then(()=>c(s.clone()))).catch(n=>{v(n)||(console.error(`Failed to initialize dev auth token`,n),r.logger.error(`Failed to initialize dev auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))});return}if(a&&o){s.setSession=c;let i=u(o);i?(console.error(`Auth: invalid state: ${i}`),r.logger.error(`Invalid state: ${i}`,{vertesia:{state:o}}),F({accountId:e,projectId:t})):d(),G(e,t,a,!1,j()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>{c(s.clone()),We()})).catch(n=>{v(n,!0)||(console.error(`Failed to fetch user token from studio, redirecting to central auth`,n),r.logger.error(`Failed to fetch user token from studio, redirecting to central auth`,{vertesia:{error:n}}),F({accountId:e,projectId:t}))});return}let i=!1,p,m=()=>{if(!i){if(!s.isLoggedIn()){if(r.logger.debug(`Not logged in & no token/state`,{vertesia:{account_id:e,project_id:t}}),j()){r.logger.debug(`Redirecting to central auth with selection`,{vertesia:{account_id:e,project_id:t}}),F({accountId:e,projectId:t});return}r.logger.debug(`Host is in Firebase auth allowlist`,{vertesia:{account_id:e,project_id:t}})}p=l(z(),async i=>{i?(r.logger.debug(`Successful login with firebase`,{vertesia:{account_id:e,project_id:t}}),s.setSession=c,await G(e,t,void 0,!1,j()).then(e=>s.login(e.rawToken,{loadOnboardingStatus:n}).then(()=>c(s.clone()))).catch(n=>{v(n)||(console.error(`Unexpected failure while fetching a user token`,n),r.logger.error(`Unexpected failure while fetching a user token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.logout(),s.isLoading=!1,s.authError=n,c(s.clone()))})):(r.logger.debug(`Using anonymous user`,{vertesia:{account_id:e,project_id:t}}),s.client.withAuthCallback(void 0),s.logout(),c(s.clone()))})}};return r.authTokenProvider?(s.setSession=c,r.authTokenProvider().then(async r=>{if(i)return;if(!r){m();return}let a=await G(e,t,r,!1,j());await s.login(a.rawToken,{loadOnboardingStatus:n}),i||c(s.clone())}).catch(n=>{i||v(n)||(console.warn(`Auth: failed to initialize injected auth token`,n),r.logger.warn(`Failed to initialize injected auth token`,{vertesia:{account_id:e,project_id:t,error:n}}),s.isLoading=!1,s.authError=n instanceof Error?n:Error(String(n)),c(s.clone()))}),()=>{i=!0,f.current=!1,p?.()}):(m(),()=>{i=!0,f.current=!1,p?.()})},p(()=>m.current?.(),[]),b($.Provider,{value:s,children:e})}function qe(){return{tagUserSession:async e=>{let t=window.localStorage.getItem(`composableSignupData`);if(!e){console.error(`No user found -- skipping tagging`);return}t&&window.localStorage.removeItem(`composableSignupData`)},trackEvent:(e,t)=>{r.isProd||console.debug(`track event`,e,t),r.firebase?.apiKey&&o(ye(),e,{...t,debug_mode:!r.isProd})}}}export{Z as AuthenticationServiceError,X as CredentialError,Ue as DevSessionProvider,x as LastSelectedAccountId_KEY,S as LastSelectedProjectId_KEY,Y as NoAccessibleAccountError,J as RequestedScopeUnavailableError,Q as RestrictedEnvironmentError,q as STSError,Ne as TokenAuthorizationError,K as UserNotFoundError,ze as UserSession,$ as UserSessionContext,Ke as UserSessionProvider,P as buildCentralAuthRedirectUrl,ge as clearCentralAuthRoundTripMarker,W as fetchComposableToken,Ae as fetchComposableTokenFromFirebaseToken,je as fetchComposableTokenFromVertesiaToken,G as getComposableToken,Me as getCurrentVertesiaToken,ye as getFirebaseAnalytics,R as getFirebaseApp,z as getFirebaseAuth,xe as getFirebaseAuthToken,Le as isAuthenticationServiceError,_e as isCentralAuthRedirectPending,Ie as isCredentialError,Fe as isNoAccessibleAccountError,Pe as isRequestedScopeUnavailableError,F as redirectToCentralAuth,Ee as resolveAuthSelection,Ge as sanitizeRejectedScopeUrl,be as setFirebaseTenant,Re as useAuthState,Ve as useCurrentTenant,qe as useUXTracking,Be as useUserSession};
|
|
2
2
|
//# sourceMappingURL=vertesia-ui-session.js.map
|