@openai-oauth/web 2.0.0-beta.0 → 2.0.0-beta.2

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/README.md CHANGED
@@ -24,6 +24,29 @@ await fetch("/api/chat", {
24
24
 
25
25
  `@openai-oauth/web` is the lower-level web package. Use it when you need browser primitives without React.
26
26
 
27
+ ### Hosted Sign-in
28
+
29
+ Hosted browser sign-in uses the open-source [Sign in with ChatGPT Chrome extension](https://chromewebstore.google.com/detail/sign-in-with-chatgpt/odbgboachaefbbbdiffcefhpkekhfcna) to complete OpenAI's local OAuth callback. The extension shows the destination app for confirmation and then returns the callback directly to it.
30
+
31
+ `startLogin()` uses this extension flow by default. When installation is needed, it returns the official Chrome Web Store URL for your interface to display:
32
+
33
+ ```ts
34
+ import { startLogin } from "@openai-oauth/web";
35
+
36
+ const result = await startLogin();
37
+
38
+ if (result.status === "needs-extension") {
39
+ installLink.href = result.installUrl;
40
+ installScreen.hidden = false;
41
+ }
42
+ ```
43
+
44
+ After installation, call `startLogin()` again when the user returns to your app or presses Sign in again. It will start OAuth once the extension is available.
45
+
46
+ The extension uses a single static redirect for `http://localhost:1455/auth/callback`. After the user confirms the destination, call `completeLogin()` on the returned app URL to exchange the code and save the browser session.
47
+
48
+ `startLogin()` returns `{ status: "started" }` when OAuth begins or `{ status: "needs-extension", installUrl }` when your interface should show installation UI. Provide an explicit `redirectUri` only when your environment handles its own registered callback without the extension.
49
+
27
50
  ### Browser Session
28
51
 
29
52
  ```ts
@@ -36,7 +59,7 @@ const headers = await openaiAuthHeaders({ sessionStore });
36
59
 
37
60
  `getSession()` reads the browser session store and refreshes with the stored refresh token when needed.
38
61
 
39
- `openaiAuthHeaders()` returns request headers for your own app route:
62
+ `openaiAuthHeaders()` returns a plain object of request headers for your own app route:
40
63
 
41
64
  ```ts
42
65
  const headers = await openaiAuthHeaders({
@@ -44,6 +67,8 @@ const headers = await openaiAuthHeaders({
44
67
  });
45
68
  ```
46
69
 
70
+ Because it returns a plain object, the result can be passed directly to `fetch`, AI SDK hooks, and other code that spreads header objects.
71
+
47
72
  It includes:
48
73
 
49
74
  - `Authorization: Bearer <access token>`
@@ -112,6 +137,8 @@ await completeLogin();
112
137
  await logout();
113
138
  ```
114
139
 
140
+ `completeLogin()` returns the signed-in session when the current URL contains an OAuth callback, and `null` when there is no callback to complete.
141
+
115
142
  Useful browser options:
116
143
 
117
144
  ```ts
@@ -135,7 +162,6 @@ type WebServerOpenAIOAuthOptions = {
135
162
  headers?: Record<string, string>;
136
163
  instructions?: string;
137
164
  openAIBaseURL?: string;
138
- storeResponses?: boolean;
139
165
  };
140
166
  ```
141
167
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type FetchFunction, type OpenAIOAuthRequest, type OpenAIOAuthRequestOptions, type OpenAIOAuthSession, type SessionStore } from "@openai-oauth/core";
1
+ import { type FetchFunction, type OpenAIOAuthRequestOptions, type OpenAIOAuthSession, type SessionStore } from "@openai-oauth/core";
2
2
  export type { OpenAIOAuthSession, SessionStore };
3
3
  export type BrowserSessionStoreOptions = {
4
4
  dbName?: string;
@@ -38,6 +38,7 @@ export type OpenAIAuthHeadersOptions = BrowserSessionOptions & {
38
38
  headers?: HeadersInit;
39
39
  optional?: boolean;
40
40
  };
41
+ export type OpenAIAuthHeaders = Record<string, string>;
41
42
  export type StartLoginOptions = Omit<OpenAIOAuthRequestOptions, "redirectUri"> & {
42
43
  callbackPath?: string;
43
44
  redirectUri?: string;
@@ -60,8 +61,13 @@ export declare const createSessionStore: (options?: BrowserSessionStoreOptions)
60
61
  export declare const exchangeCode: (input: ExchangeCodeInput, options?: ExchangeCodeOptions) => Promise<OpenAIOAuthSession>;
61
62
  export declare const refreshSession: (input: RefreshSessionInput, options?: RefreshSessionOptions) => Promise<OpenAIOAuthSession>;
62
63
  export declare const getSession: (options?: BrowserSessionOptions) => Promise<OpenAIOAuthSession | null>;
63
- export declare const openaiAuthHeaders: (options?: OpenAIAuthHeadersOptions) => Promise<Headers>;
64
- export declare const startLogin: (options?: StartLoginOptions) => Promise<OpenAIOAuthRequest>;
64
+ export declare const openaiAuthHeaders: (options?: OpenAIAuthHeadersOptions) => Promise<OpenAIAuthHeaders>;
65
+ export declare const startLogin: (options?: StartLoginOptions) => Promise<{
66
+ status: "needs-extension";
67
+ installUrl: string;
68
+ } | {
69
+ status: "started";
70
+ }>;
65
71
  export declare const completeLogin: (options?: CompleteLoginOptions) => Promise<OpenAIOAuthSession | null>;
66
72
  export declare const logout: (options?: LogoutOptions) => Promise<void>;
67
73
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,6 +6,12 @@ const defaultStoreSettings = {
6
6
  cryptoKey: "openai-oauth:crypto-key",
7
7
  };
8
8
  const pendingLoginKey = "openai-oauth:pending-login";
9
+ const browserExtensionStatePrefix = "oo2_";
10
+ const browserExtensionRedirectUri = "http://localhost:1455/auth/callback";
11
+ const browserExtensionId = "odbgboachaefbbbdiffcefhpkekhfcna";
12
+ const browserExtensionInstalledPath = "src/installed.json";
13
+ const browserExtensionInstallUrl = "https://chromewebstore.google.com/detail/sign-in-with-chatgpt/odbgboachaefbbbdiffcefhpkekhfcna";
14
+ const browserExtensionDetectionTimeoutMs = 750;
9
15
  const refreshExpiryMarginMs = 5 * 60 * 1000;
10
16
  const refreshIntervalMs = 55 * 60 * 1000;
11
17
  const textEncoder = new TextEncoder();
@@ -22,6 +28,35 @@ const assertBrowserWindow = () => {
22
28
  }
23
29
  return window;
24
30
  };
31
+ const isBrowserExtensionInstalled = async () => {
32
+ const fetchImpl = globalThis.fetch;
33
+ if (!fetchImpl) {
34
+ return false;
35
+ }
36
+ const controller = typeof AbortController === "undefined" ? null : new AbortController();
37
+ const timeout = controller
38
+ ? globalThis.setTimeout(() => controller.abort(), browserExtensionDetectionTimeoutMs)
39
+ : null;
40
+ try {
41
+ const response = await fetchImpl(`chrome-extension://${browserExtensionId}/${browserExtensionInstalledPath}`, {
42
+ cache: "no-store",
43
+ signal: controller?.signal,
44
+ });
45
+ if (!response.ok) {
46
+ return false;
47
+ }
48
+ const marker = (await response.json().catch(() => null));
49
+ return marker?.installed === true;
50
+ }
51
+ catch {
52
+ return false;
53
+ }
54
+ finally {
55
+ if (timeout !== null) {
56
+ globalThis.clearTimeout(timeout);
57
+ }
58
+ }
59
+ };
25
60
  const requestToPromise = (request) => new Promise((resolve, reject) => {
26
61
  request.onsuccess = () => resolve(request.result);
27
62
  request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed."));
@@ -207,6 +242,7 @@ const toSession = (token, options) => {
207
242
  return {
208
243
  accessToken: token.accessToken,
209
244
  accountId,
245
+ isFedRamp: token.isFedRamp,
210
246
  idToken: token.idToken,
211
247
  refreshToken: token.refreshToken ?? options.previousRefreshToken,
212
248
  expiresAt: typeof token.expiresIn === "number"
@@ -258,21 +294,34 @@ export const getSession = async (options = {}) => {
258
294
  const refreshed = await refreshSession({
259
295
  refreshToken: session.refreshToken,
260
296
  }, options);
261
- await sessionStore.set(refreshed);
262
- return refreshed;
297
+ const nextSession = session.isFedRamp && !refreshed.isFedRamp
298
+ ? { ...refreshed, isFedRamp: true }
299
+ : refreshed;
300
+ await sessionStore.set(nextSession);
301
+ return nextSession;
263
302
  };
264
303
  export const openaiAuthHeaders = async (options = {}) => {
265
304
  const session = await getSession(options);
266
305
  if (!session) {
267
306
  if (options.optional) {
268
- return new Headers(options.headers);
307
+ return toPlainHeaders(new Headers(options.headers));
269
308
  }
270
309
  throw new Error("OpenAI OAuth session not found.");
271
310
  }
272
311
  const headers = new Headers(options.headers);
273
312
  headers.set("Authorization", `Bearer ${session.accessToken}`);
274
313
  headers.set("chatgpt-account-id", session.accountId);
275
- return headers;
314
+ if (session.isFedRamp) {
315
+ headers.set("X-OpenAI-Fedramp", "true");
316
+ }
317
+ return toPlainHeaders(headers);
318
+ };
319
+ const toPlainHeaders = (headers) => {
320
+ const output = {};
321
+ headers.forEach((value, key) => {
322
+ output[key] = value;
323
+ });
324
+ return output;
276
325
  };
277
326
  const readPendingLogin = () => {
278
327
  const browserWindow = assertBrowserWindow();
@@ -295,15 +344,52 @@ const getCurrentRelativeUrl = () => {
295
344
  return `${browserWindow.location.pathname}${browserWindow.location.search}${browserWindow.location.hash}`;
296
345
  };
297
346
  const getDefaultRedirectUri = (callbackPath) => new URL(callbackPath, assertBrowserWindow().location.origin).toString();
347
+ const getCurrentUrl = () => new URL(getCurrentRelativeUrl(), assertBrowserWindow().location.origin).toString();
348
+ const bytesToBase64Url = (bytes) => bytesToBase64(bytes)
349
+ .replaceAll("+", "-")
350
+ .replaceAll("/", "_")
351
+ .replace(/=+$/, "");
352
+ const randomURLSafeString = (byteLength) => {
353
+ const bytes = new Uint8Array(byteLength);
354
+ globalThis.crypto.getRandomValues(bytes);
355
+ return bytesToBase64Url(bytes);
356
+ };
357
+ const encodeBase64Url = (value) => bytesToBase64Url(textEncoder.encode(value));
358
+ const createBrowserExtensionState = (callbackUrl, appState) => {
359
+ const payload = {
360
+ type: "openai-oauth-callback",
361
+ version: 1,
362
+ nonce: randomURLSafeString(24),
363
+ callbackUrl,
364
+ };
365
+ if (appState) {
366
+ payload.appState = appState;
367
+ }
368
+ return `${browserExtensionStatePrefix}${encodeBase64Url(JSON.stringify(payload))}`;
369
+ };
298
370
  export const startLogin = async (options = {}) => {
299
371
  const browserWindow = assertBrowserWindow();
300
- const redirectUri = options.redirectUri ??
301
- getDefaultRedirectUri(options.callbackPath ?? "/auth/callback");
372
+ const usesBrowserExtension = options.redirectUri === undefined;
373
+ if (usesBrowserExtension && !(await isBrowserExtensionInstalled())) {
374
+ return {
375
+ status: "needs-extension",
376
+ installUrl: browserExtensionInstallUrl,
377
+ };
378
+ }
379
+ const returnTo = options.returnTo ?? getCurrentRelativeUrl();
380
+ const callbackUrl = options.callbackPath
381
+ ? getDefaultRedirectUri(options.callbackPath)
382
+ : usesBrowserExtension
383
+ ? getCurrentUrl()
384
+ : getDefaultRedirectUri("/auth/callback");
385
+ const redirectUri = options.redirectUri ?? browserExtensionRedirectUri;
302
386
  const request = await createOpenAIOAuthRequest({
303
387
  clientId: options.clientId,
304
388
  issuer: options.issuer,
305
389
  scope: options.scope,
306
- state: options.state,
390
+ state: usesBrowserExtension
391
+ ? createBrowserExtensionState(callbackUrl, options.state)
392
+ : options.state,
307
393
  codeVerifier: options.codeVerifier,
308
394
  simplifiedFlow: options.simplifiedFlow,
309
395
  idTokenAddOrganizations: options.idTokenAddOrganizations,
@@ -314,17 +400,17 @@ export const startLogin = async (options = {}) => {
314
400
  state: request.state,
315
401
  codeVerifier: request.codeVerifier,
316
402
  redirectUri: request.redirectUri,
317
- returnTo: options.returnTo ?? getCurrentRelativeUrl(),
403
+ returnTo,
318
404
  });
319
405
  if (options.openMode === "popup") {
320
406
  const popup = browserWindow.open(request.authorizationUrl, "_blank", "popup,width=520,height=720");
321
407
  if (!popup) {
322
408
  throw new Error("The ChatGPT login popup was blocked.");
323
409
  }
324
- return request;
410
+ return { status: "started" };
325
411
  }
326
412
  browserWindow.location.assign(request.authorizationUrl);
327
- return request;
413
+ return { status: "started" };
328
414
  };
329
415
  export const completeLogin = async (options = {}) => {
330
416
  const browserWindow = assertBrowserWindow();
@@ -345,6 +431,13 @@ export const completeLogin = async (options = {}) => {
345
431
  }
346
432
  }
347
433
  if (oauthError) {
434
+ if (oauthError === "access_denied" &&
435
+ pending &&
436
+ callbackState === pending.state) {
437
+ clearPendingLogin();
438
+ browserWindow.history.replaceState(null, "", pending.returnTo || "/");
439
+ return null;
440
+ }
348
441
  throw new Error(url.searchParams.get("error_description") ??
349
442
  `OpenAI OAuth returned ${oauthError}.`);
350
443
  }
package/dist/server.d.ts CHANGED
@@ -5,7 +5,6 @@ export type WebServerOpenAIOAuthOptions = {
5
5
  headers?: Record<string, string>;
6
6
  instructions?: string;
7
7
  openAIBaseURL?: string;
8
- storeResponses?: boolean;
9
8
  };
10
9
  export declare const openaiCredentials: (input: Request | Headers, options?: WebServerOpenAIOAuthOptions) => OpenAIOAuth;
11
10
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,aAAa,EACb,WAAW,EAEX,MAAM,oBAAoB,CAAA;AAE3B,MAAM,MAAM,2BAA2B,GAAG;IACzC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AA4BD,eAAO,MAAM,iBAAiB,GAC7B,OAAO,OAAO,GAAG,OAAO,EACxB,UAAS,2BAAgC,KACvC,WAcF,CAAA"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,aAAa,EACb,WAAW,EAEX,MAAM,oBAAoB,CAAA;AAE3B,MAAM,MAAM,2BAA2B,GAAG;IACzC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AA6BD,eAAO,MAAM,iBAAiB,GAC7B,OAAO,OAAO,GAAG,OAAO,EACxB,UAAS,2BAAgC,KACvC,WAaF,CAAA"}
package/dist/server.js CHANGED
@@ -14,6 +14,7 @@ const getRequestSession = (input) => {
14
14
  return {
15
15
  accessToken,
16
16
  accountId,
17
+ isFedRamp: headers.get("x-openai-fedramp") === "true",
17
18
  };
18
19
  };
19
20
  export const openaiCredentials = (input, options = {}) => {
@@ -25,7 +26,6 @@ export const openaiCredentials = (input, options = {}) => {
25
26
  headers: options.headers,
26
27
  instructions: options.instructions,
27
28
  openAIBaseURL: options.openAIBaseURL,
28
- storeResponses: options.storeResponses,
29
29
  getSession: async () => session,
30
30
  refreshSession: async () => session,
31
31
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openai-oauth/web",
3
- "version": "2.0.0-beta.0",
3
+ "version": "2.0.0-beta.2",
4
4
  "description": "Browser credential storage and web utilities for openai-oauth.",
5
5
  "keywords": [
6
6
  "openai",
@@ -41,7 +41,7 @@
41
41
  "access": "public"
42
42
  },
43
43
  "dependencies": {
44
- "@openai-oauth/core": "2.0.0-beta.0"
44
+ "@openai-oauth/core": "2.0.0-beta.2"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/node": "20.17.24",