@guuey/widget-auth 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -7
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# @guuey/widget-auth
|
|
2
2
|
|
|
3
|
-
Mint end-user identity tokens for a [guuey](https://guuey.com) embeddable widget
|
|
3
|
+
Mint end-user identity tokens for a [guuey](https://guuey.com) embeddable widget — or for any
|
|
4
|
+
surface you build on `@guuey/agent-client` / `@guuey/chat` — from your own backend.
|
|
4
5
|
|
|
5
6
|
Zero runtime dependencies. Node 18+.
|
|
6
7
|
|
|
@@ -81,6 +82,39 @@ export async function GET() {
|
|
|
81
82
|
|
|
82
83
|
Your endpoint is called by the browser; the app secret stays on your server.
|
|
83
84
|
|
|
85
|
+
## Using the token on your own surface
|
|
86
|
+
|
|
87
|
+
The token is not widget-specific: it is a plain signed JWT bound to your app's own issuer
|
|
88
|
+
and audience, and every guuey surface verifies it the same way and derives the same
|
|
89
|
+
end-user identity from `userId`. So the same token endpoint also signs users into a page
|
|
90
|
+
you build yourself with [`@guuey/agent-client`](https://www.npmjs.com/package/@guuey/agent-client)
|
|
91
|
+
or [`@guuey/chat`](https://www.npmjs.com/package/@guuey/chat) — hand it to `getAccessToken`:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { createWebAdapters } from "@guuey/agent-client";
|
|
95
|
+
|
|
96
|
+
const adapters = createWebAdapters({
|
|
97
|
+
apiBaseUrl: "https://api.us-east-1.guuey.com/v1",
|
|
98
|
+
getAccessToken: async ({ forceRefresh } = {}) => {
|
|
99
|
+
// `forceRefresh` is the SDK's "that token was rejected" signal — the same
|
|
100
|
+
// as the widget's reason "expired". Mint fresh, ignoring any cache.
|
|
101
|
+
const res = await fetch(`/api/guuey-token?reason=${forceRefresh ? "expired" : "initial"}`);
|
|
102
|
+
if (!res.ok) throw new Error(`token endpoint failed: ${res.status}`);
|
|
103
|
+
return res.text();
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Throw on failure — never return `null`.** To the SDK, `null` means "signed out on
|
|
109
|
+
purpose", and a signed-in surface would silently continue as an anonymous visitor.
|
|
110
|
+
|
|
111
|
+
A user is **the same identity on every surface** — widget embed, standalone agent page,
|
|
112
|
+
your own page — as long as your backend sends the same `userId`. Conversations, memory,
|
|
113
|
+
files and profile follow them across all three. Add your page's origin to the app's
|
|
114
|
+
allowed domains (`guuey apps update <appId> --domains yourapp.com`) so the browser can
|
|
115
|
+
reach the agent from it. The full walkthrough is at
|
|
116
|
+
[docs.guuey.com/surface-identity](https://docs.guuey.com/surface-identity/).
|
|
117
|
+
|
|
84
118
|
## The app secret is server-side only
|
|
85
119
|
|
|
86
120
|
`appSecret` authorizes minting an identity for **any user of your app**. If it reaches a
|
|
@@ -237,12 +271,12 @@ id, an editable email) silently orphans all of it and the user reappears as a st
|
|
|
237
271
|
|
|
238
272
|
**Returns `WidgetToken`**
|
|
239
273
|
|
|
240
|
-
| Field | Type |
|
|
241
|
-
| ---------------- | -------- |
|
|
242
|
-
| `token` | `string` | The signed JWT
|
|
243
|
-
| `expiresAtEpoch` | `number` | Unix epoch seconds. Use it to drive your cache.
|
|
244
|
-
| `issuer` | `string` | The issuer that signed it.
|
|
245
|
-
| `kid` | `string` | The signing key's id.
|
|
274
|
+
| Field | Type | |
|
|
275
|
+
| ---------------- | -------- | ------------------------------------------------------------------------ |
|
|
276
|
+
| `token` | `string` | The signed JWT — for the widget, or your own surface's `getAccessToken`. |
|
|
277
|
+
| `expiresAtEpoch` | `number` | Unix epoch seconds. Use it to drive your cache. |
|
|
278
|
+
| `issuer` | `string` | The issuer that signed it. |
|
|
279
|
+
| `kid` | `string` | The signing key's id. |
|
|
246
280
|
|
|
247
281
|
## License
|
|
248
282
|
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
* );
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
|
+
* ## One token, every surface
|
|
15
|
+
*
|
|
16
|
+
* The token is a plain RS256 JWT bound to your app's own issuer and audience —
|
|
17
|
+
* `iss`, `sub` (= `userId`), `aud`, `iat`/`nbf`/`exp`, optional `name`/`email` —
|
|
18
|
+
* with nothing widget-specific in it. Every guuey consumer verifies it the same
|
|
19
|
+
* way and derives the same end-user identity from `userId`, so the widget
|
|
20
|
+
* embed, a standalone agent page and **your own page built on
|
|
21
|
+
* `@guuey/agent-client` / `@guuey/chat`** (`createWebAdapters({ getAccessToken })`)
|
|
22
|
+
* all see one user with one history, memory and profile. "widget" in this
|
|
23
|
+
* package's name is the name of the app's per-app issuer, not a limit on where
|
|
24
|
+
* the token may be presented (guuey#206).
|
|
25
|
+
*
|
|
14
26
|
* ## What this package does NOT do, and why that matters
|
|
15
27
|
*
|
|
16
28
|
* It holds no key material and assembles no claims. The app's RSA private key
|
|
@@ -93,9 +105,13 @@ export interface WidgetAuthConfig {
|
|
|
93
105
|
/** Override the HTTP client. Intended for tests. */
|
|
94
106
|
fetch?: FetchLike;
|
|
95
107
|
}
|
|
96
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* A minted token, exactly as the mint route returns it — a hand mirror of
|
|
110
|
+
* `@guuey-private/cli-wire`'s `AppUserTokenMintResponse`, pinned by
|
|
111
|
+
* `wire-sync.test.ts`.
|
|
112
|
+
*/
|
|
97
113
|
export interface WidgetToken {
|
|
98
|
-
/** The signed JWT
|
|
114
|
+
/** The signed JWT — hand it to the widget, or to your own surface's `getAccessToken`. */
|
|
99
115
|
token: string;
|
|
100
116
|
/** Unix epoch seconds at which `token` stops verifying. */
|
|
101
117
|
expiresAtEpoch: number;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,OAAO,EAGL,+BAA+B,EAC/B,qBAAqB,EACrB,yBAAyB,EACzB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,+BAA+B,EAC/B,qBAAqB,EACrB,yBAAyB,EACzB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,GACvB,CAAC;AA4BF,gDAAgD;AAChD,MAAM,WAAW,UAAU;IACzB;;;;;;;;OAQG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,kCAAkC;AAClC,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,oDAAoD;IACpD,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,4CAA4C;AAC5C,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,yDAAyD;AACzD,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,qBAAqB,KACxB,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAgBtC;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,WAAW,CAAC,CAmEtB"}
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
* );
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
|
+
* ## One token, every surface
|
|
15
|
+
*
|
|
16
|
+
* The token is a plain RS256 JWT bound to your app's own issuer and audience —
|
|
17
|
+
* `iss`, `sub` (= `userId`), `aud`, `iat`/`nbf`/`exp`, optional `name`/`email` —
|
|
18
|
+
* with nothing widget-specific in it. Every guuey consumer verifies it the same
|
|
19
|
+
* way and derives the same end-user identity from `userId`, so the widget
|
|
20
|
+
* embed, a standalone agent page and **your own page built on
|
|
21
|
+
* `@guuey/agent-client` / `@guuey/chat`** (`createWebAdapters({ getAccessToken })`)
|
|
22
|
+
* all see one user with one history, memory and profile. "widget" in this
|
|
23
|
+
* package's name is the name of the app's per-app issuer, not a limit on where
|
|
24
|
+
* the token may be presented (guuey#206).
|
|
25
|
+
*
|
|
14
26
|
* ## What this package does NOT do, and why that matters
|
|
15
27
|
*
|
|
16
28
|
* It holds no key material and assembles no claims. The app's RSA private key
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/widget-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Mint end-user identity tokens for a guuey embeddable widget from your own backend. One call, zero runtime dependencies — your app secret stays on your server and the platform holds the signing key.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|