@tempoxyz/auth 0.0.0-pr-6.sha-17bb901 → 0.0.0-pr-6.sha-fe206c7
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 +217 -0
- package/dist/Actions.d.ts +15 -15
- package/dist/Actions.js +8 -8
- package/dist/Auth.d.ts +7 -7
- package/dist/Auth.js +1 -1
- package/dist/Key.d.ts +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# @tempoxyz/auth
|
|
2
|
+
|
|
3
|
+
Sign users in to Tempo through Tempo Auth, and get back their tokens for Tempo APIs and a [viem](https://viem.sh) access key account on their Tempo Account.
|
|
4
|
+
|
|
5
|
+
Every sign-in returns the same `Authorization`. Send transactions with its `account` through viem, and call Tempo APIs with its `tokens.accessToken`.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { Actions, Auth } from '@tempoxyz/auth'
|
|
9
|
+
import { Addresses, createClient, Expiry, Scopes } from 'viem/tempo'
|
|
10
|
+
import { tempoTestnet } from 'viem/tempo/chains'
|
|
11
|
+
|
|
12
|
+
const auth = Auth.create({
|
|
13
|
+
clientId: 'client_…',
|
|
14
|
+
url: 'https://auth.tempo.xyz',
|
|
15
|
+
})
|
|
16
|
+
const client = createClient({
|
|
17
|
+
chain: tempoTestnet,
|
|
18
|
+
feeToken: Addresses.pathUsd,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const authorization = await Actions.authorize(auth, {
|
|
22
|
+
accessKey: {
|
|
23
|
+
chainId: tempoTestnet.id,
|
|
24
|
+
expiry: Expiry.days(1),
|
|
25
|
+
limits: [{ limit: 10_000_000n, token: Addresses.pathUsd }],
|
|
26
|
+
scopes: [Scopes.tip20(Addresses.pathUsd).transfer()],
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
await client.token.transferSync({
|
|
31
|
+
account: authorization!.account,
|
|
32
|
+
amount: 10_000n,
|
|
33
|
+
to: '0x…',
|
|
34
|
+
token: Addresses.pathUsd,
|
|
35
|
+
})
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pnpm add @tempoxyz/auth viem
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
viem is a peer dependency.
|
|
45
|
+
|
|
46
|
+
## Before you start
|
|
47
|
+
|
|
48
|
+
- **Register the app.** Create a WorkOS Connect app in the Tempo Issuer environment, and register every redirect URI it uses. Its `client_id` is the `clientId` you pass to `Auth.create`. An app with a backend also gets a client secret.
|
|
49
|
+
- **Allow the app's origin.** Apps that call Tempo Auth from their own page need their origin in Tempo Auth's `INTERNAL_ORIGINS`.
|
|
50
|
+
|
|
51
|
+
The CLI device grant needs neither. It signs in as Tempo Auth's own `tempo-cli` app.
|
|
52
|
+
|
|
53
|
+
## Access keys
|
|
54
|
+
|
|
55
|
+
Each sign-in creates a key for the app and asks Tempo Auth to authorize it on the user's Tempo Account. The `accessKey` option says what the key may do, with viem's `Expiry` and `Scopes` helpers:
|
|
56
|
+
|
|
57
|
+
| Field | Meaning |
|
|
58
|
+
| --------- | ----------------------------------------------------------------------------- |
|
|
59
|
+
| `chainId` | The chain the key acts on, such as `tempoTestnet.id` |
|
|
60
|
+
| `expiry` | When the key expires, in Unix seconds, such as `Expiry.days(1)` |
|
|
61
|
+
| `limits` | One-time spending limits per token, such as `[{ limit: 10_000_000n, token }]` |
|
|
62
|
+
| `scopes` | The calls the key may make, such as `[Scopes.tip20(token).transfer()]` |
|
|
63
|
+
|
|
64
|
+
Flows without a Tempo Auth page (`authorize`, `verifyCode`) must stay within Tempo Auth's ceiling, about $1,000 per token. Flows with a page (`redirect`, `createAuthorizationUrl`, `authorizeDevice`) show the limits to the user, who approves them, so they may go beyond it.
|
|
65
|
+
|
|
66
|
+
The returned `account` attaches the key's authorization to its first transaction, which registers the key on chain.
|
|
67
|
+
|
|
68
|
+
## Flows
|
|
69
|
+
|
|
70
|
+
### Your own sign-in UI
|
|
71
|
+
|
|
72
|
+
For a browser app that renders its own email form. The page calls Tempo Auth with the user's Tempo Auth session, so it works across every app on the same site.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
// A user already signed in to Tempo Auth, from any app, needs no form.
|
|
76
|
+
const authorization = await Actions.authorize(auth, { accessKey })
|
|
77
|
+
|
|
78
|
+
// Otherwise, sign in with an emailed code.
|
|
79
|
+
await Actions.sendCode(auth, { email })
|
|
80
|
+
const result = await Actions.verifyCode(auth, { accessKey, code, email })
|
|
81
|
+
|
|
82
|
+
// An address that requires SSO continues at its connection, and returns to this page.
|
|
83
|
+
if ('step' in result) Actions.signIn(auth, { url: result.step.url })
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
To offer OAuth providers such as Google, list the ones Tempo Auth enables and send the browser to one. It returns to the current page signed in, where `authorize` finishes.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const providers = await Actions.getProviders(auth) // [{ id: 'google', name: 'Google' }]
|
|
90
|
+
Actions.signIn(auth, { provider: 'google' })
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Tempo Auth's pages
|
|
94
|
+
|
|
95
|
+
For a browser app without its own sign-in UI. The browser leaves for Tempo Auth's sign-in page, which shows the key's limits, and returns with a code.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
await Actions.redirect(auth, { accessKey })
|
|
99
|
+
|
|
100
|
+
// On the page the browser returns to, and on every load:
|
|
101
|
+
const authorization = await Actions.handleRedirect(auth)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`redirect` keeps its state in session storage until the browser returns. Pass `storage` to `Auth.create` to keep it elsewhere.
|
|
105
|
+
|
|
106
|
+
### A backend
|
|
107
|
+
|
|
108
|
+
For an app whose server holds a client secret. The server builds the URL, keeps the pending state until the callback, and redeems the code itself.
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
const auth = Auth.create({ clientId, clientSecret, url })
|
|
112
|
+
|
|
113
|
+
// GET /auth/start
|
|
114
|
+
const { pending, url } = await Actions.createAuthorizationUrl(auth, {
|
|
115
|
+
accessKey,
|
|
116
|
+
redirectUri: 'https://app.example/auth/callback',
|
|
117
|
+
})
|
|
118
|
+
// Keep `pending` in an encrypted, HttpOnly cookie, then redirect to `url`.
|
|
119
|
+
|
|
120
|
+
// GET /auth/callback
|
|
121
|
+
const authorization = await Actions.handleCallback(auth, {
|
|
122
|
+
pending,
|
|
123
|
+
url: request.url,
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### A CLI
|
|
128
|
+
|
|
129
|
+
For a command-line tool. The user approves a code in any browser, and the CLI waits.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const device = await Actions.authorizeDevice(auth, {
|
|
133
|
+
accessKey,
|
|
134
|
+
device: os.hostname(),
|
|
135
|
+
})
|
|
136
|
+
console.log(
|
|
137
|
+
`Open ${device.verificationUriComplete} and confirm ${device.userCode}.`,
|
|
138
|
+
)
|
|
139
|
+
const authorization = await device.wait()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Keep a sign-in
|
|
143
|
+
|
|
144
|
+
`Authorization.key` is the app's key as JSON: the Tempo Account, the signed authorization, and the private key. Store it with the tokens, as securely as a session, and rebuild the account later with `Key.toAccount`.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { Actions, Key } from '@tempoxyz/auth'
|
|
148
|
+
|
|
149
|
+
if (Key.expired(saved.key)) signInAgain()
|
|
150
|
+
|
|
151
|
+
const account = Key.toAccount(saved.key)
|
|
152
|
+
const tokens = await Actions.refresh(auth, {
|
|
153
|
+
refreshToken: saved.tokens.refreshToken,
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Refresh tokens rotate, so store the new `tokens` after each refresh.
|
|
158
|
+
|
|
159
|
+
## Errors
|
|
160
|
+
|
|
161
|
+
A request Tempo Auth refuses throws `Auth.RequestError`, with its `status` and `message`.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
try {
|
|
165
|
+
await Actions.verifyCode(auth, { accessKey, code, email })
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (error instanceof Auth.RequestError && error.status === 401)
|
|
168
|
+
showWrongCode()
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Reference
|
|
173
|
+
|
|
174
|
+
### `Auth.create(options)`
|
|
175
|
+
|
|
176
|
+
| Option | Meaning |
|
|
177
|
+
| -------------- | ----------------------------------------------------------------------------------------------- |
|
|
178
|
+
| `clientId` | The app's Connect client ID. Required |
|
|
179
|
+
| `url` | Where Tempo Auth runs, such as `https://auth.tempo.xyz`. Required |
|
|
180
|
+
| `clientSecret` | The app's client secret. Only a backend holds one |
|
|
181
|
+
| `redirectUri` | Where Tempo Auth redirects back to. Defaults to the page's origin |
|
|
182
|
+
| `scope` | Scopes beyond `openid` and `email`, which every instance includes. Defaults to `offline_access` |
|
|
183
|
+
| `storage` | Where `redirect` keeps its state. Defaults to session storage |
|
|
184
|
+
| `fetch` | Calls Tempo Auth. Defaults to the global `fetch` |
|
|
185
|
+
|
|
186
|
+
### `Actions`
|
|
187
|
+
|
|
188
|
+
| Action | Returns |
|
|
189
|
+
| ---------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
190
|
+
| `authorize(auth, { accessKey })` | An `Authorization` for a user already signed in, or `undefined` |
|
|
191
|
+
| `authorizeDevice(auth, { accessKey, device })` | The code to show and a `wait()` that resolves with an `Authorization` |
|
|
192
|
+
| `createAuthorizationUrl(auth, { accessKey, redirectUri })` | The `url` to send the browser to, and the `pending` state to keep |
|
|
193
|
+
| `getProviders(auth)` | The OAuth providers Tempo Auth offers, as `{ id, name }` |
|
|
194
|
+
| `handleCallback(auth, { pending, url })` | The `Authorization` for a redirect's callback |
|
|
195
|
+
| `handleRedirect(auth)` | The `Authorization` when the page is a redirect's callback, or `undefined` |
|
|
196
|
+
| `redirect(auth, { accessKey })` | Nothing. The browser leaves for Tempo Auth's pages |
|
|
197
|
+
| `refresh(auth, { refreshToken })` | New `Tokens` |
|
|
198
|
+
| `sendCode(auth, { email })` | Nothing. Tempo Auth emails a code |
|
|
199
|
+
| `signIn(auth, { provider } \| { url })` | Nothing. The browser leaves for the provider or SSO connection |
|
|
200
|
+
| `signOut(auth)` | Nothing. The user's Tempo Auth session ends |
|
|
201
|
+
| `verifyCode(auth, { accessKey, code, email })` | An `Authorization`, or the `step` the address requires first |
|
|
202
|
+
|
|
203
|
+
### `Authorization`
|
|
204
|
+
|
|
205
|
+
| Field | Meaning |
|
|
206
|
+
| --------- | ------------------------------------------------------------------------------- |
|
|
207
|
+
| `account` | The app's key as a viem access key account, acting for the user's Tempo Account |
|
|
208
|
+
| `key` | The same key as JSON, for `Key.toAccount` |
|
|
209
|
+
| `tokens` | `accessToken`, `expiresAt`, and the optional `idToken` and `refreshToken` |
|
|
210
|
+
| `user` | The user's `email` and `id`, the `sub` of every token |
|
|
211
|
+
|
|
212
|
+
### `Key`
|
|
213
|
+
|
|
214
|
+
| Function | Returns |
|
|
215
|
+
| ---------------- | ------------------------------------------- |
|
|
216
|
+
| `toAccount(key)` | The key as a viem access key account |
|
|
217
|
+
| `expired(key)` | Whether the key's authorization has expired |
|
package/dist/Actions.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type AccessKey, type Auth, type Authorization, type Pending, type Provider, type Step, type Tokens } from './Auth.ts';
|
|
2
2
|
/**
|
|
3
|
-
* Authorizes the app for a
|
|
3
|
+
* Authorizes the app for a user already signed in to Tempo Auth, from any app. Returns
|
|
4
4
|
* `undefined` without a session, so the app shows sign-in. The key must fit Tempo Auth's headless
|
|
5
5
|
* ceiling.
|
|
6
6
|
*
|
|
@@ -20,7 +20,7 @@ export declare namespace authorize {
|
|
|
20
20
|
type ReturnType = Authorization | undefined;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* Starts the device grant for a CLI: the
|
|
23
|
+
* Starts the device grant for a CLI: the user approves `userCode` at `verificationUri` from any
|
|
24
24
|
* browser, and `wait` resolves once they do.
|
|
25
25
|
*
|
|
26
26
|
* @example
|
|
@@ -41,18 +41,18 @@ export declare namespace authorizeDevice {
|
|
|
41
41
|
type ReturnType = {
|
|
42
42
|
/** Seconds until the code expires. */
|
|
43
43
|
expiresIn: number;
|
|
44
|
-
/** The code the
|
|
44
|
+
/** The code the user confirms in the browser. */
|
|
45
45
|
userCode: string;
|
|
46
|
-
/** Where the
|
|
46
|
+
/** Where the user enters the code. */
|
|
47
47
|
verificationUri: string;
|
|
48
|
-
/** Where the
|
|
48
|
+
/** Where the user approves the code, with it already filled in. */
|
|
49
49
|
verificationUriComplete: string;
|
|
50
|
-
/** Resolves with the authorization once the
|
|
50
|
+
/** Resolves with the authorization once the user approves. */
|
|
51
51
|
wait: () => Promise<Authorization>;
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
* Returns the URL that signs the
|
|
55
|
+
* Returns the URL that signs the user in on Tempo Auth's pages and redirects back with a code
|
|
56
56
|
* and the key authorization, and the {@link Pending} state to keep until then, such as in a
|
|
57
57
|
* sealed cookie. {@link handleCallback} finishes it.
|
|
58
58
|
*
|
|
@@ -69,7 +69,7 @@ export declare namespace authorizeDevice {
|
|
|
69
69
|
export declare function createAuthorizationUrl(auth: Auth, options: createAuthorizationUrl.Options): Promise<createAuthorizationUrl.ReturnType>;
|
|
70
70
|
export declare namespace createAuthorizationUrl {
|
|
71
71
|
type Options = {
|
|
72
|
-
/** What the app's key may do. Tempo Auth's pages show it, and the
|
|
72
|
+
/** What the app's key may do. Tempo Auth's pages show it, and the user approves it. */
|
|
73
73
|
accessKey: AccessKey;
|
|
74
74
|
/** Where Tempo Auth redirects back to. Defaults to the instance's `redirectUri`. */
|
|
75
75
|
redirectUri?: string | undefined;
|
|
@@ -147,7 +147,7 @@ export declare namespace handleRedirect {
|
|
|
147
147
|
export declare function redirect(auth: Auth, options: redirect.Options): Promise<void>;
|
|
148
148
|
export declare namespace redirect {
|
|
149
149
|
type Options = {
|
|
150
|
-
/** What the app's key may do. Tempo Auth's pages show it, and the
|
|
150
|
+
/** What the app's key may do. Tempo Auth's pages show it, and the user approves it. */
|
|
151
151
|
accessKey: AccessKey;
|
|
152
152
|
};
|
|
153
153
|
}
|
|
@@ -169,17 +169,17 @@ export declare namespace refresh {
|
|
|
169
169
|
};
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
172
|
-
* Emails the
|
|
172
|
+
* Emails the user a sign-in code. The response is the same for every address.
|
|
173
173
|
*
|
|
174
174
|
* @example
|
|
175
175
|
* ```ts
|
|
176
|
-
* await Actions.sendCode(auth, { email: '
|
|
176
|
+
* await Actions.sendCode(auth, { email: 'user@example.com' })
|
|
177
177
|
* ```
|
|
178
178
|
*/
|
|
179
179
|
export declare function sendCode(auth: Auth, options: sendCode.Options): Promise<void>;
|
|
180
180
|
export declare namespace sendCode {
|
|
181
181
|
type Options = {
|
|
182
|
-
/** The
|
|
182
|
+
/** The user's email address. */
|
|
183
183
|
email: string;
|
|
184
184
|
};
|
|
185
185
|
}
|
|
@@ -206,7 +206,7 @@ export declare namespace signIn {
|
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
208
|
/**
|
|
209
|
-
* Ends the
|
|
209
|
+
* Ends the user's Tempo Auth session, which signs them out of every app that relies on it.
|
|
210
210
|
*
|
|
211
211
|
* @example
|
|
212
212
|
* ```ts
|
|
@@ -215,7 +215,7 @@ export declare namespace signIn {
|
|
|
215
215
|
*/
|
|
216
216
|
export declare function signOut(auth: Auth): Promise<void>;
|
|
217
217
|
/**
|
|
218
|
-
* Signs the
|
|
218
|
+
* Signs the user in with the code they were emailed, and authorizes the app in the same call.
|
|
219
219
|
* Returns a {@link Step} when the address requires SSO, which {@link signIn} continues.
|
|
220
220
|
*
|
|
221
221
|
* @example
|
|
@@ -229,7 +229,7 @@ export declare namespace verifyCode {
|
|
|
229
229
|
type Options = {
|
|
230
230
|
/** What the app's key may do. It must fit the headless ceiling. */
|
|
231
231
|
accessKey: AccessKey;
|
|
232
|
-
/** The 6-digit code the
|
|
232
|
+
/** The 6-digit code the user was emailed. */
|
|
233
233
|
code: string;
|
|
234
234
|
/** The address the code was sent to. */
|
|
235
235
|
email: string;
|
package/dist/Actions.js
CHANGED
|
@@ -8,7 +8,7 @@ import { RequestError, } from './Auth.js';
|
|
|
8
8
|
import * as Key from './Key.js';
|
|
9
9
|
import { request } from './internal/request.js';
|
|
10
10
|
/**
|
|
11
|
-
* Authorizes the app for a
|
|
11
|
+
* Authorizes the app for a user already signed in to Tempo Auth, from any app. Returns
|
|
12
12
|
* `undefined` without a session, so the app shows sign-in. The key must fit Tempo Auth's headless
|
|
13
13
|
* ceiling.
|
|
14
14
|
*
|
|
@@ -34,7 +34,7 @@ export async function authorize(auth, options) {
|
|
|
34
34
|
return authorization(await json(response), { privateKey });
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Starts the device grant for a CLI: the
|
|
37
|
+
* Starts the device grant for a CLI: the user approves `userCode` at `verificationUri` from any
|
|
38
38
|
* browser, and `wait` resolves once they do.
|
|
39
39
|
*
|
|
40
40
|
* @example
|
|
@@ -53,7 +53,7 @@ export async function authorizeDevice(auth, options) {
|
|
|
53
53
|
.keyAuthorization,
|
|
54
54
|
},
|
|
55
55
|
}));
|
|
56
|
-
/** Polls until the
|
|
56
|
+
/** Polls until the user approves or denies the code, or it expires. */
|
|
57
57
|
async function wait() {
|
|
58
58
|
let interval = code.interval;
|
|
59
59
|
const deadline = Date.now() + code.expires_in * 1000;
|
|
@@ -89,7 +89,7 @@ export async function authorizeDevice(auth, options) {
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
* Returns the URL that signs the
|
|
92
|
+
* Returns the URL that signs the user in on Tempo Auth's pages and redirects back with a code
|
|
93
93
|
* and the key authorization, and the {@link Pending} state to keep until then, such as in a
|
|
94
94
|
* sealed cookie. {@link handleCallback} finishes it.
|
|
95
95
|
*
|
|
@@ -233,11 +233,11 @@ export function refresh(auth, options) {
|
|
|
233
233
|
});
|
|
234
234
|
}
|
|
235
235
|
/**
|
|
236
|
-
* Emails the
|
|
236
|
+
* Emails the user a sign-in code. The response is the same for every address.
|
|
237
237
|
*
|
|
238
238
|
* @example
|
|
239
239
|
* ```ts
|
|
240
|
-
* await Actions.sendCode(auth, { email: '
|
|
240
|
+
* await Actions.sendCode(auth, { email: 'user@example.com' })
|
|
241
241
|
* ```
|
|
242
242
|
*/
|
|
243
243
|
export async function sendCode(auth, options) {
|
|
@@ -260,7 +260,7 @@ export function signIn(auth, options) {
|
|
|
260
260
|
window.location.assign(url);
|
|
261
261
|
}
|
|
262
262
|
/**
|
|
263
|
-
* Ends the
|
|
263
|
+
* Ends the user's Tempo Auth session, which signs them out of every app that relies on it.
|
|
264
264
|
*
|
|
265
265
|
* @example
|
|
266
266
|
* ```ts
|
|
@@ -272,7 +272,7 @@ export async function signOut(auth) {
|
|
|
272
272
|
await json(await post(auth, '/api/auth/logout', { json: {} }));
|
|
273
273
|
}
|
|
274
274
|
/**
|
|
275
|
-
* Signs the
|
|
275
|
+
* Signs the user in with the code they were emailed, and authorizes the app in the same call.
|
|
276
276
|
* Returns a {@link Step} when the address requires SSO, which {@link signIn} continues.
|
|
277
277
|
*
|
|
278
278
|
* @example
|
package/dist/Auth.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A Tempo Auth instance, and the types its actions take and return. Create one with
|
|
3
3
|
* {@link create}, then pass it to each action in `Actions`. Every sign-in returns an
|
|
4
|
-
* {@link Authorization}: the
|
|
4
|
+
* {@link Authorization}: the user's tokens, and a viem access key account.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```ts
|
|
@@ -51,13 +51,13 @@ export type AccessKey = Pick<KeyAuthorization.KeyAuthorization, 'limits' | 'scop
|
|
|
51
51
|
};
|
|
52
52
|
/** What every sign-in returns. */
|
|
53
53
|
export type Authorization = {
|
|
54
|
-
/** The app's access key, as a viem account acting for the
|
|
54
|
+
/** The app's access key, as a viem account acting for the user's Tempo Account. */
|
|
55
55
|
account: ReturnType<typeof Key.toAccount>;
|
|
56
56
|
/** The same key as JSON, for apps that store it and rebuild it with `Key.toAccount`. */
|
|
57
57
|
key: Key.Key;
|
|
58
58
|
/** The app's tokens for Tempo APIs. */
|
|
59
59
|
tokens: Tokens;
|
|
60
|
-
/** The signed-in
|
|
60
|
+
/** The signed-in user, from the ID token. */
|
|
61
61
|
user: User;
|
|
62
62
|
};
|
|
63
63
|
/** The app's tokens for Tempo APIs. */
|
|
@@ -66,16 +66,16 @@ export type Tokens = {
|
|
|
66
66
|
accessToken: string;
|
|
67
67
|
/** When the access token expires, in milliseconds. */
|
|
68
68
|
expiresAt: number;
|
|
69
|
-
/** The OIDC ID token, which names the
|
|
69
|
+
/** The OIDC ID token, which names the user. A refresh may omit it. */
|
|
70
70
|
idToken?: string | undefined;
|
|
71
71
|
/** Exchanges for new tokens through `Actions.refresh`. It rotates on every refresh. */
|
|
72
72
|
refreshToken?: string | undefined;
|
|
73
73
|
};
|
|
74
|
-
/** The signed-in
|
|
74
|
+
/** The signed-in user. */
|
|
75
75
|
export type User = {
|
|
76
|
-
/** The
|
|
76
|
+
/** The user's verified email address. */
|
|
77
77
|
email: string;
|
|
78
|
-
/** The
|
|
78
|
+
/** The user's ID, the `sub` of every token. */
|
|
79
79
|
id: string;
|
|
80
80
|
};
|
|
81
81
|
/** An OAuth provider's short name, as `Actions.getProviders` lists them. */
|
package/dist/Auth.js
CHANGED
|
@@ -17,7 +17,7 @@ export class RequestError extends Error {
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
export function create(options) {
|
|
20
|
-
// Every authorization reads the
|
|
20
|
+
// Every authorization reads the user from the ID token, which needs `openid` and `email`.
|
|
21
21
|
const scopes = (options.scope ?? 'offline_access').split(' ').filter(Boolean);
|
|
22
22
|
return {
|
|
23
23
|
...options,
|
package/dist/Key.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* An app's access key on a
|
|
2
|
+
* An app's access key on a user's Tempo Account, as the app stores it: the key, the account it
|
|
3
3
|
* acts for, and the authorization Tempo Auth signed for it.
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tempoxyz/auth",
|
|
3
|
-
"version": "0.0.0-pr-6.sha-
|
|
4
|
-
"description": "Signs
|
|
3
|
+
"version": "0.0.0-pr-6.sha-fe206c7",
|
|
4
|
+
"description": "Signs users in to Tempo through Tempo Auth, and returns viem access key accounts on their Tempo Accounts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|