@tempoxyz/auth 0.0.0-pr-19.sha-2c8fa8e → 0.0.0-pr-24.sha-354b14f
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 +86 -58
- package/dist/Actions.d.ts +23 -228
- package/dist/Actions.js +18 -360
- package/dist/Auth.d.ts +11 -91
- package/dist/Auth.js +29 -0
- package/dist/Authorization.d.ts +25 -0
- package/dist/Authorization.js +11 -0
- package/dist/Key.d.ts +40 -8
- package/dist/Key.js +41 -5
- package/dist/Pending.d.ts +26 -0
- package/dist/Pending.js +11 -0
- package/dist/Permissions.d.ts +25 -0
- package/dist/Permissions.js +15 -0
- package/dist/Provider.d.ts +15 -0
- package/dist/Provider.js +11 -0
- package/dist/Step.d.ts +20 -0
- package/dist/Step.js +11 -0
- package/dist/Storage.d.ts +26 -0
- package/dist/Storage.js +15 -0
- package/dist/TempoAccount.d.ts +18 -0
- package/dist/TempoAccount.js +11 -0
- package/dist/Tokens.d.ts +24 -0
- package/dist/Tokens.js +11 -0
- package/dist/User.d.ts +20 -0
- package/dist/User.js +11 -0
- package/dist/actions/device.d.ts +41 -0
- package/dist/actions/device.js +61 -0
- package/dist/actions/email.d.ts +54 -0
- package/dist/actions/email.js +40 -0
- package/dist/actions/provider.d.ts +48 -0
- package/dist/actions/provider.js +31 -0
- package/dist/actions/redirect.d.ts +104 -0
- package/dist/actions/redirect.js +151 -0
- package/dist/actions/tempoAccount.d.ts +36 -0
- package/dist/actions/tempoAccount.js +31 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/internal/accessKey.d.ts +15 -0
- package/dist/internal/accessKey.js +26 -0
- package/dist/internal/api.d.ts +42 -0
- package/dist/internal/api.js +74 -0
- package/dist/internal/indexedDb.d.ts +8 -0
- package/dist/internal/indexedDb.js +31 -0
- package/dist/internal/request.d.ts +8 -10
- package/dist/internal/request.js +12 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ import { Addresses, createClient, Expiry, Scopes } from 'viem/tempo'
|
|
|
10
10
|
import { tempoTestnet } from 'viem/tempo/chains'
|
|
11
11
|
|
|
12
12
|
const auth = Auth.create({
|
|
13
|
+
chainId: tempoTestnet.id,
|
|
13
14
|
clientId: 'client_…',
|
|
14
15
|
url: 'https://auth.tempo.xyz',
|
|
15
16
|
})
|
|
@@ -19,8 +20,7 @@ const client = createClient({
|
|
|
19
20
|
})
|
|
20
21
|
|
|
21
22
|
const authorization = await Actions.authorize(auth, {
|
|
22
|
-
|
|
23
|
-
chainId: tempoTestnet.id,
|
|
23
|
+
permissions: {
|
|
24
24
|
expiry: Expiry.days(1),
|
|
25
25
|
limits: [{ limit: 10_000_000n, token: Addresses.pathUsd }],
|
|
26
26
|
scopes: [Scopes.tip20(Addresses.pathUsd).transfer()],
|
|
@@ -50,17 +50,25 @@ The CLI device grant needs neither. It signs in as Tempo Auth's own `tempo-cli`
|
|
|
50
50
|
|
|
51
51
|
## Access keys
|
|
52
52
|
|
|
53
|
-
Each sign-in creates a key for the app and asks Tempo Auth to authorize it on the user's Tempo Account. The `
|
|
53
|
+
Each sign-in creates a key for the app and asks Tempo Auth to authorize it on the user's Tempo Account. The `permissions` option says what the key may do, with viem's `Expiry` and `Scopes` helpers:
|
|
54
54
|
|
|
55
|
-
| Field | Meaning
|
|
56
|
-
| --------- |
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `scopes` | The calls the key may make, such as `[Scopes.tip20(token).transfer()]` |
|
|
55
|
+
| Field | Meaning |
|
|
56
|
+
| --------- | ----------------------------------------------------------------------------- |
|
|
57
|
+
| `chainId` | Optional: the chain the key acts on. Defaults to the instance's `chainId` |
|
|
58
|
+
| `expiry` | When the key expires, in Unix seconds, such as `Expiry.days(1)` |
|
|
59
|
+
| `limits` | One-time spending limits per token, such as `[{ limit: 10_000_000n, token }]` |
|
|
60
|
+
| `scopes` | The calls the key may make, such as `[Scopes.tip20(token).transfer()]` |
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
In a browser, the key is a non-extractable WebCrypto P256 key, so no script can read its private key. A CLI, a native app, or a backend gets a secp256k1 key, which it stores as a string.
|
|
63
|
+
|
|
64
|
+
To authorize a key the app already holds, pass it as `accessKey`, a viem account. The library never sees its private key. Its `access` names the Tempo Account, which defaults to the user's first:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const accessKey = Account.fromWebCryptoP256(keyPair, { access: tempoAccount })
|
|
68
|
+
await Actions.authorize(auth, { accessKey, permissions })
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Flows without a Tempo Auth page (`authorize`, `email.signIn`) must stay within Tempo Auth's ceiling, about $1,000 per token. Flows with a page (`redirect.start`, `redirect.createUrl`, `device.authorize`) show the limits to the user, who approves them, so they may go beyond it.
|
|
64
72
|
|
|
65
73
|
The returned `account` attaches the key's authorization to its first transaction, which registers the key on chain.
|
|
66
74
|
|
|
@@ -72,21 +80,21 @@ For a browser app that renders its own email form. The page calls Tempo Auth wit
|
|
|
72
80
|
|
|
73
81
|
```ts
|
|
74
82
|
// A user already signed in to Tempo Auth, from any app, needs no form.
|
|
75
|
-
const authorization = await Actions.authorize(auth, {
|
|
83
|
+
const authorization = await Actions.authorize(auth, { permissions })
|
|
76
84
|
|
|
77
85
|
// Otherwise, sign in with an emailed code.
|
|
78
|
-
await Actions.sendCode(auth, { email })
|
|
79
|
-
const result = await Actions.
|
|
86
|
+
await Actions.email.sendCode(auth, { email })
|
|
87
|
+
const result = await Actions.email.signIn(auth, { code, email, permissions })
|
|
80
88
|
|
|
81
89
|
// An address that requires SSO continues at its connection, and returns to this page.
|
|
82
|
-
if ('step' in result) Actions.signIn(auth, { url: result.step.url })
|
|
90
|
+
if ('step' in result) Actions.provider.signIn(auth, { url: result.step.url })
|
|
83
91
|
```
|
|
84
92
|
|
|
85
93
|
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.
|
|
86
94
|
|
|
87
95
|
```ts
|
|
88
|
-
const providers = await Actions.
|
|
89
|
-
Actions.signIn(auth, { provider: 'google' })
|
|
96
|
+
const providers = await Actions.provider.list(auth) // [{ id: 'google', name: 'Google' }]
|
|
97
|
+
Actions.provider.signIn(auth, { provider: 'google' })
|
|
90
98
|
```
|
|
91
99
|
|
|
92
100
|
### Tempo Auth's pages
|
|
@@ -94,13 +102,13 @@ Actions.signIn(auth, { provider: 'google' })
|
|
|
94
102
|
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.
|
|
95
103
|
|
|
96
104
|
```ts
|
|
97
|
-
await Actions.redirect(auth, {
|
|
105
|
+
await Actions.redirect.start(auth, { permissions })
|
|
98
106
|
|
|
99
107
|
// On the page the browser returns to, and on every load:
|
|
100
|
-
const authorization = await Actions.
|
|
108
|
+
const authorization = await Actions.redirect.complete(auth)
|
|
101
109
|
```
|
|
102
110
|
|
|
103
|
-
`redirect` keeps its state in
|
|
111
|
+
`redirect.start` keeps its state, with the new key, in IndexedDB until the browser returns. Pass `storage` to `Auth.create` to keep it elsewhere. An app that supplies `accessKey` passes it to `redirect.complete` too.
|
|
104
112
|
|
|
105
113
|
### A mobile app
|
|
106
114
|
|
|
@@ -116,16 +124,16 @@ const auth = Auth.create({
|
|
|
116
124
|
})
|
|
117
125
|
|
|
118
126
|
// Your own sign-in UI, as in a browser.
|
|
119
|
-
await Actions.sendCode(auth, { email })
|
|
120
|
-
const result = await Actions.
|
|
127
|
+
await Actions.email.sendCode(auth, { email })
|
|
128
|
+
const result = await Actions.email.signIn(auth, { code, email, permissions })
|
|
121
129
|
|
|
122
130
|
// Or Tempo Auth's pages, which also offer Google and SSO.
|
|
123
|
-
const { pending, url } = await Actions.
|
|
124
|
-
|
|
131
|
+
const { pending, url } = await Actions.redirect.createUrl(auth, {
|
|
132
|
+
permissions,
|
|
125
133
|
})
|
|
126
134
|
const session = await WebBrowser.openAuthSessionAsync(url, auth.redirectUri)
|
|
127
135
|
if (session.type === 'success')
|
|
128
|
-
authorization = await Actions.handleCallback(auth, {
|
|
136
|
+
authorization = await Actions.redirect.handleCallback(auth, {
|
|
129
137
|
pending,
|
|
130
138
|
url: session.url,
|
|
131
139
|
})
|
|
@@ -141,14 +149,14 @@ For an app whose server holds a client secret. The server builds the URL, keeps
|
|
|
141
149
|
const auth = Auth.create({ clientId, clientSecret, url })
|
|
142
150
|
|
|
143
151
|
// GET /auth/start
|
|
144
|
-
const { pending, url } = await Actions.
|
|
145
|
-
|
|
152
|
+
const { pending, url } = await Actions.redirect.createUrl(auth, {
|
|
153
|
+
permissions,
|
|
146
154
|
redirectUri: 'https://app.example/auth/callback',
|
|
147
155
|
})
|
|
148
156
|
// Keep `pending` in an encrypted, HttpOnly cookie, then redirect to `url`.
|
|
149
157
|
|
|
150
158
|
// GET /auth/callback
|
|
151
|
-
const authorization = await Actions.handleCallback(auth, {
|
|
159
|
+
const authorization = await Actions.redirect.handleCallback(auth, {
|
|
152
160
|
pending,
|
|
153
161
|
url: request.url,
|
|
154
162
|
})
|
|
@@ -159,9 +167,9 @@ const authorization = await Actions.handleCallback(auth, {
|
|
|
159
167
|
For a command-line tool. The user approves a code in any browser, and the CLI waits.
|
|
160
168
|
|
|
161
169
|
```ts
|
|
162
|
-
const device = await Actions.
|
|
163
|
-
accessKey,
|
|
170
|
+
const device = await Actions.device.authorize(auth, {
|
|
164
171
|
device: os.hostname(),
|
|
172
|
+
permissions,
|
|
165
173
|
})
|
|
166
174
|
console.log(
|
|
167
175
|
`Open ${device.verificationUriComplete} and confirm ${device.userCode}.`,
|
|
@@ -171,20 +179,27 @@ const authorization = await device.wait()
|
|
|
171
179
|
|
|
172
180
|
## More Tempo Accounts
|
|
173
181
|
|
|
174
|
-
A user starts with one Tempo Account and can have more. Add one, then name it in
|
|
182
|
+
A user starts with one Tempo Account and can have more. Add one, then name it in the `access` of the key the app authorizes:
|
|
175
183
|
|
|
176
184
|
```ts
|
|
177
|
-
const tempoAccount = await Actions.
|
|
178
|
-
const accounts = await Actions.
|
|
185
|
+
const tempoAccount = await Actions.tempoAccount.create(auth)
|
|
186
|
+
const accounts = await Actions.tempoAccount.list(auth) // the default first
|
|
179
187
|
|
|
180
188
|
await Actions.authorize(auth, {
|
|
181
|
-
accessKey:
|
|
189
|
+
accessKey: Account.fromWebCryptoP256(keyPair, {
|
|
190
|
+
access: tempoAccount.address,
|
|
191
|
+
}),
|
|
192
|
+
permissions,
|
|
182
193
|
})
|
|
183
194
|
```
|
|
184
195
|
|
|
185
196
|
## Keep a sign-in
|
|
186
197
|
|
|
187
|
-
`Authorization.key` is the app's key as
|
|
198
|
+
`Authorization.key` is the app's key as data: the Tempo Account, the signed authorization, and the key the library created. Store it with the tokens, and rebuild the account later with `Key.toAccount`.
|
|
199
|
+
|
|
200
|
+
- **Browser:** the key is a `CryptoKey` pair, which IndexedDB stores without exporting it.
|
|
201
|
+
- **Elsewhere:** the key is a secp256k1 private key, as JSON. Store it as securely as a session.
|
|
202
|
+
- **Supplied key:** the key holds no material. Pass the `accessKey` again, as `Key.toAccount(saved.key, { accessKey })`.
|
|
188
203
|
|
|
189
204
|
```ts
|
|
190
205
|
import { Actions, Key } from '@tempoxyz/auth'
|
|
@@ -205,7 +220,7 @@ A request Tempo Auth refuses throws `Auth.RequestError`, with its `status` and `
|
|
|
205
220
|
|
|
206
221
|
```ts
|
|
207
222
|
try {
|
|
208
|
-
await Actions.
|
|
223
|
+
await Actions.email.signIn(auth, { code, email, permissions })
|
|
209
224
|
} catch (error) {
|
|
210
225
|
if (error instanceof Auth.RequestError && error.status === 401)
|
|
211
226
|
showWrongCode()
|
|
@@ -219,47 +234,60 @@ try {
|
|
|
219
234
|
| Option | Meaning |
|
|
220
235
|
| -------------- | ----------------------------------------------------------------------------------------------- |
|
|
221
236
|
| `clientId` | The app's Connect client ID. Required |
|
|
237
|
+
| `chainId` | The chain the app's keys act on, such as `tempoTestnet.id`. Defaults to Tempo mainnet |
|
|
222
238
|
| `url` | Where Tempo Auth runs, such as `https://auth.tempo.xyz`. Required |
|
|
223
239
|
| `clientSecret` | The app's client secret. Only a backend holds one |
|
|
224
240
|
| `redirectUri` | Where Tempo Auth redirects back to. Defaults to the page's origin |
|
|
225
241
|
| `scope` | Scopes beyond `openid` and `email`, which every instance includes. Defaults to `offline_access` |
|
|
226
|
-
| `storage` | Where `redirect` keeps its state. Defaults to
|
|
242
|
+
| `storage` | Where `redirect.start` keeps its state, without serializing it. Defaults to IndexedDB |
|
|
227
243
|
| `fetch` | Calls Tempo Auth. Defaults to the global `fetch` |
|
|
228
244
|
|
|
229
245
|
### `Actions`
|
|
230
246
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
|
234
|
-
|
|
|
235
|
-
| `
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
239
|
-
| `
|
|
240
|
-
| `
|
|
241
|
-
| `
|
|
242
|
-
| `
|
|
243
|
-
| `
|
|
244
|
-
| `
|
|
245
|
-
| `
|
|
246
|
-
| `
|
|
247
|
+
Each sign-in flow has its own namespace. The actions every flow shares sit at the top level. Every action that takes `permissions` also takes an optional `accessKey`.
|
|
248
|
+
|
|
249
|
+
| Action | Returns |
|
|
250
|
+
| -------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
251
|
+
| `authorize(auth, { permissions })` | An `Authorization` for a user already signed in, or `undefined` |
|
|
252
|
+
| `refresh(auth, { refreshToken })` | New `Tokens` |
|
|
253
|
+
| `signOut(auth)` | Nothing. The user's Tempo Auth session ends |
|
|
254
|
+
| `device.authorize(auth, { device, permissions })` | The code to show and a `wait()` that resolves with an `Authorization` |
|
|
255
|
+
| `email.sendCode(auth, { email })` | Nothing. Tempo Auth emails a code |
|
|
256
|
+
| `email.signIn(auth, { code, email, permissions })` | An `Authorization`, or the `step` the address requires first |
|
|
257
|
+
| `provider.list(auth)` | The OAuth providers Tempo Auth offers, as `{ id, name }` |
|
|
258
|
+
| `provider.signIn(auth, { provider } \| { url })` | Nothing. The browser leaves for the provider or SSO connection |
|
|
259
|
+
| `redirect.complete(auth, { accessKey })` | The `Authorization` when the page is a redirect's callback, or `undefined` |
|
|
260
|
+
| `redirect.createUrl(auth, { permissions, redirectUri })` | The `url` to send the browser to, and the `pending` state to keep |
|
|
261
|
+
| `redirect.handleCallback(auth, { pending, url })` | The `Authorization` for a redirect's callback |
|
|
262
|
+
| `redirect.start(auth, { permissions })` | Nothing. The browser leaves for Tempo Auth's pages |
|
|
263
|
+
| `tempoAccount.create(auth)` | Another Tempo Account for the signed-in user |
|
|
264
|
+
| `tempoAccount.list(auth)` | The signed-in user's Tempo Accounts, the default first |
|
|
247
265
|
|
|
248
266
|
### `Authorization`
|
|
249
267
|
|
|
250
268
|
| Field | Meaning |
|
|
251
269
|
| -------------- | -------------------------------------------------------------------------------- |
|
|
252
270
|
| `account` | The user's Tempo Account, as a viem account that signs with the app's access key |
|
|
253
|
-
| `key` | The same key as
|
|
271
|
+
| `key` | The same key as data, for `Key.toAccount` |
|
|
254
272
|
| `accessToken` | The Bearer token Tempo APIs accept |
|
|
255
273
|
| `expiresAt` | When the access token expires, in milliseconds |
|
|
256
274
|
| `idToken` | Optional: the OIDC ID token, which names the user |
|
|
257
275
|
| `refreshToken` | Optional: exchanges for new tokens through `refresh`. It rotates each time |
|
|
258
276
|
| `user` | The user's `email` and `id`, the `sub` of every token |
|
|
259
277
|
|
|
278
|
+
### Types
|
|
279
|
+
|
|
280
|
+
Each type an action takes or returns lives in its own module, exported beside `Actions`: `Authorization`, `Key`, `Pending`, `Permissions`, `Provider`, `Step`, `Storage`, `TempoAccount`, `Tokens`, and `User`. Each module's `from` builds a value of its type:
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
import { Permissions } from '@tempoxyz/auth'
|
|
284
|
+
|
|
285
|
+
const permissions = Permissions.from({ expiry: Expiry.days(1), limits, scopes })
|
|
286
|
+
```
|
|
287
|
+
|
|
260
288
|
### `Key`
|
|
261
289
|
|
|
262
|
-
| Function
|
|
263
|
-
|
|
|
264
|
-
| `toAccount(key)` | The key as a viem access key account
|
|
265
|
-
| `expired(key)`
|
|
290
|
+
| Function | Returns |
|
|
291
|
+
| ------------------------------- | ------------------------------------------------------------------------------- |
|
|
292
|
+
| `toAccount(key, { accessKey })` | The key as a viem access key account. `accessKey` is for a key the app supplied |
|
|
293
|
+
| `expired(key)` | Whether the key's authorization has expired |
|
package/dist/Actions.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Tempo Auth's actions. Each takes an instance from `Auth.create`. Each sign-in flow has its own
|
|
3
|
+
* namespace, and the actions every flow shares sit at the top level.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { Account } from 'viem/tempo';
|
|
7
|
+
import type { Auth } from './Auth.ts';
|
|
8
|
+
import type { Authorization } from './Authorization.ts';
|
|
9
|
+
import type { Permissions } from './Permissions.ts';
|
|
10
|
+
import type { Tokens } from './Tokens.ts';
|
|
11
|
+
export * as device from './actions/device.ts';
|
|
12
|
+
export * as email from './actions/email.ts';
|
|
13
|
+
export * as provider from './actions/provider.ts';
|
|
14
|
+
export * as redirect from './actions/redirect.ts';
|
|
15
|
+
export * as tempoAccount from './actions/tempoAccount.ts';
|
|
2
16
|
/**
|
|
3
17
|
* Authorizes the app for a user already signed in to Tempo Auth, from any app. Returns
|
|
4
18
|
* `undefined` without a session, so the app shows sign-in. The key must fit Tempo Auth's headless
|
|
@@ -6,181 +20,24 @@ import { type AccessKey, type Auth, type Authorization, type Pending, type Provi
|
|
|
6
20
|
*
|
|
7
21
|
* @example
|
|
8
22
|
* ```ts
|
|
9
|
-
* const authorization = await Actions.authorize(auth, {
|
|
23
|
+
* const authorization = await Actions.authorize(auth, { permissions })
|
|
10
24
|
* if (!authorization) showSignIn()
|
|
11
25
|
* ```
|
|
12
26
|
*/
|
|
13
27
|
export declare function authorize(auth: Auth, options: authorize.Options): Promise<authorize.ReturnType>;
|
|
14
28
|
export declare namespace authorize {
|
|
15
29
|
type Options = {
|
|
16
|
-
/**
|
|
17
|
-
|
|
30
|
+
/**
|
|
31
|
+
* The key to authorize, as a viem account. Its `access` names the Tempo Account, which
|
|
32
|
+
* defaults to the user's first. Defaults to a new key.
|
|
33
|
+
*/
|
|
34
|
+
accessKey?: Account.Account | undefined;
|
|
35
|
+
/** What the key may do. It must fit the headless ceiling. */
|
|
36
|
+
permissions: Permissions;
|
|
18
37
|
};
|
|
19
38
|
/** The authorization, or `undefined` without a session. */
|
|
20
39
|
type ReturnType = Authorization | undefined;
|
|
21
40
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Starts the device grant for a CLI: the user approves `userCode` at `verificationUri` from any
|
|
24
|
-
* browser, and `wait` resolves once they do.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* const device = await Actions.authorizeDevice(auth, { accessKey, device: Os.hostname() })
|
|
29
|
-
* console.log(`Open ${device.verificationUriComplete}`)
|
|
30
|
-
* const authorization = await device.wait()
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
export declare function authorizeDevice(auth: Auth, options: authorizeDevice.Options): Promise<authorizeDevice.ReturnType>;
|
|
34
|
-
export declare namespace authorizeDevice {
|
|
35
|
-
type Options = {
|
|
36
|
-
/** What the CLI's key may do. The approval page shows it beside the device. */
|
|
37
|
-
accessKey: AccessKey;
|
|
38
|
-
/** The name the approval page shows, such as the machine's hostname. */
|
|
39
|
-
device: string;
|
|
40
|
-
};
|
|
41
|
-
type ReturnType = {
|
|
42
|
-
/** Seconds until the code expires. */
|
|
43
|
-
expiresIn: number;
|
|
44
|
-
/** The code the user confirms in the browser. */
|
|
45
|
-
userCode: string;
|
|
46
|
-
/** Where the user enters the code. */
|
|
47
|
-
verificationUri: string;
|
|
48
|
-
/** Where the user approves the code, with it already filled in. */
|
|
49
|
-
verificationUriComplete: string;
|
|
50
|
-
/** Resolves with the authorization once the user approves. */
|
|
51
|
-
wait: () => Promise<Authorization>;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Returns the URL that signs the user in on Tempo Auth's pages and redirects back with a code,
|
|
56
|
-
* and the {@link Pending} state to keep until then, such as in a sealed cookie.
|
|
57
|
-
* {@link handleCallback} redeems the code for the tokens and the key authorization.
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* ```ts
|
|
61
|
-
* const { pending, url } = await Actions.createAuthorizationUrl(auth, {
|
|
62
|
-
* accessKey,
|
|
63
|
-
* redirectUri: 'https://app.example/auth/callback',
|
|
64
|
-
* })
|
|
65
|
-
* await seal(c, 'oauth', pending)
|
|
66
|
-
* return c.redirect(url)
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export declare function createAuthorizationUrl(auth: Auth, options: createAuthorizationUrl.Options): Promise<createAuthorizationUrl.ReturnType>;
|
|
70
|
-
export declare namespace createAuthorizationUrl {
|
|
71
|
-
type Options = {
|
|
72
|
-
/** What the app's key may do. Tempo Auth's pages show it, and the user approves it. */
|
|
73
|
-
accessKey: AccessKey;
|
|
74
|
-
/** Where Tempo Auth redirects back to. Defaults to the instance's `redirectUri`. */
|
|
75
|
-
redirectUri?: string | undefined;
|
|
76
|
-
};
|
|
77
|
-
type ReturnType = {
|
|
78
|
-
/** What to keep until the callback, such as in a sealed cookie. */
|
|
79
|
-
pending: Pending;
|
|
80
|
-
/** Where to send the browser. */
|
|
81
|
-
url: string;
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Creates another Tempo Account for the signed-in user, and returns it. Pass its `address` as an
|
|
86
|
-
* access key's `account` to authorize keys on it.
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* ```ts
|
|
90
|
-
* const tempoAccount = await Actions.createTempoAccount(auth)
|
|
91
|
-
* await Actions.authorize(auth, {
|
|
92
|
-
* accessKey: { ...accessKey, account: tempoAccount.address },
|
|
93
|
-
* })
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
export declare function createTempoAccount(auth: Auth): Promise<createTempoAccount.ReturnType>;
|
|
97
|
-
export declare namespace createTempoAccount {
|
|
98
|
-
/** The new account. */
|
|
99
|
-
type ReturnType = TempoAccount;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Lists the OAuth providers Tempo Auth offers, for an app that shows its own sign-in buttons.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```ts
|
|
106
|
-
* const providers = await Actions.getProviders(auth)
|
|
107
|
-
* // [{ id: 'google', name: 'Google' }]
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
export declare function getProviders(auth: Auth): Promise<getProviders.ReturnType>;
|
|
111
|
-
export declare namespace getProviders {
|
|
112
|
-
type ReturnType = readonly {
|
|
113
|
-
/** The provider's short name, which `signIn` takes. */
|
|
114
|
-
id: Provider;
|
|
115
|
-
/** The name to show, such as `Google`. */
|
|
116
|
-
name: string;
|
|
117
|
-
}[];
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Lists the signed-in user's Tempo Accounts, their default first.
|
|
121
|
-
*
|
|
122
|
-
* @example
|
|
123
|
-
* ```ts
|
|
124
|
-
* const [account, ...others] = await Actions.getTempoAccounts(auth)
|
|
125
|
-
* ```
|
|
126
|
-
*/
|
|
127
|
-
export declare function getTempoAccounts(auth: Auth): Promise<getTempoAccounts.ReturnType>;
|
|
128
|
-
export declare namespace getTempoAccounts {
|
|
129
|
-
/** The user's accounts, their default first. */
|
|
130
|
-
type ReturnType = readonly TempoAccount[];
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Finishes a sign-in redirect: checks its state, and redeems the code with the PKCE verifier (and
|
|
134
|
-
* the client secret, for a backend) for the tokens and the key authorization.
|
|
135
|
-
*
|
|
136
|
-
* @example
|
|
137
|
-
* ```ts
|
|
138
|
-
* const authorization = await Actions.handleCallback(auth, {
|
|
139
|
-
* pending: await unseal(c, 'oauth'),
|
|
140
|
-
* url: c.req.url,
|
|
141
|
-
* })
|
|
142
|
-
* ```
|
|
143
|
-
*/
|
|
144
|
-
export declare function handleCallback(auth: Auth, options: handleCallback.Options): Promise<Authorization>;
|
|
145
|
-
export declare namespace handleCallback {
|
|
146
|
-
type Options = {
|
|
147
|
-
/** What `createAuthorizationUrl` returned to keep. */
|
|
148
|
-
pending: Pending;
|
|
149
|
-
/** The callback URL Tempo Auth redirected to. */
|
|
150
|
-
url: string | URL;
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Finishes a {@link redirect} when the page loads with Tempo Auth's callback, and returns
|
|
155
|
-
* `undefined` otherwise. The code is redeemed once, however often the page calls this.
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* ```ts
|
|
159
|
-
* const authorization =
|
|
160
|
-
* (await Actions.handleRedirect(auth)) ??
|
|
161
|
-
* (await Actions.authorize(auth, { accessKey }))
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
|
-
export declare function handleRedirect(auth: Auth): Promise<handleRedirect.ReturnType>;
|
|
165
|
-
export declare namespace handleRedirect {
|
|
166
|
-
/** The authorization, or `undefined` when the page is not a redirect's callback. */
|
|
167
|
-
type ReturnType = Authorization | undefined;
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Sends the browser to Tempo Auth's pages to sign in, keeping the redirect's state in `storage`.
|
|
171
|
-
*
|
|
172
|
-
* @example
|
|
173
|
-
* ```ts
|
|
174
|
-
* await Actions.redirect(auth, { accessKey })
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
export declare function redirect(auth: Auth, options: redirect.Options): Promise<void>;
|
|
178
|
-
export declare namespace redirect {
|
|
179
|
-
type Options = {
|
|
180
|
-
/** What the app's key may do. Tempo Auth's pages show it, and the user approves it. */
|
|
181
|
-
accessKey: AccessKey;
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
41
|
/**
|
|
185
42
|
* Exchanges a refresh token for new tokens. Refresh tokens rotate, so store the new one.
|
|
186
43
|
*
|
|
@@ -198,43 +55,6 @@ export declare namespace refresh {
|
|
|
198
55
|
refreshToken: string;
|
|
199
56
|
};
|
|
200
57
|
}
|
|
201
|
-
/**
|
|
202
|
-
* Emails the user a sign-in code. The response is the same for every address.
|
|
203
|
-
*
|
|
204
|
-
* @example
|
|
205
|
-
* ```ts
|
|
206
|
-
* await Actions.sendCode(auth, { email: 'user@example.com' })
|
|
207
|
-
* ```
|
|
208
|
-
*/
|
|
209
|
-
export declare function sendCode(auth: Auth, options: sendCode.Options): Promise<void>;
|
|
210
|
-
export declare namespace sendCode {
|
|
211
|
-
type Options = {
|
|
212
|
-
/** The user's email address. */
|
|
213
|
-
email: string;
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Sends the browser to an OAuth provider, or to the SSO connection a {@link Step} names, and back to
|
|
218
|
-
* `returnTo` signed in to Tempo Auth. The app then calls {@link authorize}.
|
|
219
|
-
*
|
|
220
|
-
* @example
|
|
221
|
-
* ```ts
|
|
222
|
-
* Actions.signIn(auth, { provider: 'google' })
|
|
223
|
-
* ```
|
|
224
|
-
*/
|
|
225
|
-
export declare function signIn(auth: Auth, options: signIn.Options): void;
|
|
226
|
-
export declare namespace signIn {
|
|
227
|
-
type Options = ({
|
|
228
|
-
/** The OAuth provider to sign in with, from `getProviders`. */
|
|
229
|
-
provider: Provider;
|
|
230
|
-
} | {
|
|
231
|
-
/** The URL of a `Step`, such as the SSO connection an address requires. */
|
|
232
|
-
url: string;
|
|
233
|
-
}) & {
|
|
234
|
-
/** Where to return. Defaults to the current page. It must be on an internal origin. */
|
|
235
|
-
returnTo?: string | undefined;
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
58
|
/**
|
|
239
59
|
* Ends the user's Tempo Auth session, which signs them out of every app that relies on it.
|
|
240
60
|
*
|
|
@@ -244,28 +64,3 @@ export declare namespace signIn {
|
|
|
244
64
|
* ```
|
|
245
65
|
*/
|
|
246
66
|
export declare function signOut(auth: Auth): Promise<void>;
|
|
247
|
-
/**
|
|
248
|
-
* Signs the user in with the code they were emailed, and authorizes the app in the same call.
|
|
249
|
-
* Returns a {@link Step} when the address requires SSO, which {@link signIn} continues.
|
|
250
|
-
*
|
|
251
|
-
* @example
|
|
252
|
-
* ```ts
|
|
253
|
-
* const result = await Actions.verifyCode(auth, { accessKey, code, email })
|
|
254
|
-
* if ('step' in result) Actions.signIn(auth, { url: result.step.url })
|
|
255
|
-
* ```
|
|
256
|
-
*/
|
|
257
|
-
export declare function verifyCode(auth: Auth, options: verifyCode.Options): Promise<verifyCode.ReturnType>;
|
|
258
|
-
export declare namespace verifyCode {
|
|
259
|
-
type Options = {
|
|
260
|
-
/** What the app's key may do. It must fit the headless ceiling. */
|
|
261
|
-
accessKey: AccessKey;
|
|
262
|
-
/** The 6-digit code the user was emailed. */
|
|
263
|
-
code: string;
|
|
264
|
-
/** The address the code was sent to. */
|
|
265
|
-
email: string;
|
|
266
|
-
};
|
|
267
|
-
/** The authorization, or the step the address requires first. */
|
|
268
|
-
type ReturnType = Authorization | {
|
|
269
|
-
step: Step;
|
|
270
|
-
};
|
|
271
|
-
}
|