@tempoxyz/auth 0.0.0-pr-28.sha-72f7afa → 0.0.0-pr-31.sha-03ddfa6
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 +32 -31
- package/dist/Actions.d.ts +4 -4
- package/dist/Actions.js +2 -2
- package/dist/Auth.js +4 -7
- package/dist/Permissions.d.ts +6 -13
- package/dist/Permissions.js +2 -2
- package/dist/actions/device.d.ts +3 -3
- package/dist/actions/device.js +1 -1
- package/dist/actions/email.d.ts +3 -3
- package/dist/actions/email.js +1 -1
- package/dist/actions/redirect.d.ts +9 -8
- package/dist/actions/redirect.js +5 -4
- package/dist/internal/api.js +1 -4
- package/dist/internal/request.d.ts +2 -2
- package/dist/internal/request.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,12 +6,8 @@ Every sign-in returns the same `Authorization`. Send transactions with its `acco
|
|
|
6
6
|
|
|
7
7
|
```ts
|
|
8
8
|
import { Actions, Auth } from '@tempoxyz/auth'
|
|
9
|
-
import { createClient, Expiry, Scopes } from 'viem/tempo'
|
|
10
|
-
import {
|
|
11
|
-
import * as Tokens from 'viem/tokens'
|
|
12
|
-
|
|
13
|
-
// OUSD has its mainnet address on every Tempo chain.
|
|
14
|
-
const ousd = Tokens.ousd(tempo.id).address
|
|
9
|
+
import { Addresses, createClient, Expiry, Scopes } from 'viem/tempo'
|
|
10
|
+
import { tempoTestnet } from 'viem/tempo/chains'
|
|
15
11
|
|
|
16
12
|
const auth = Auth.create({
|
|
17
13
|
chainId: tempoTestnet.id,
|
|
@@ -20,14 +16,14 @@ const auth = Auth.create({
|
|
|
20
16
|
})
|
|
21
17
|
const client = createClient({
|
|
22
18
|
chain: tempoTestnet,
|
|
23
|
-
feeToken:
|
|
19
|
+
feeToken: Addresses.pathUsd,
|
|
24
20
|
})
|
|
25
21
|
|
|
26
22
|
const authorization = await Actions.authorize(auth, {
|
|
27
23
|
permissions: {
|
|
28
24
|
expiry: Expiry.days(1),
|
|
29
|
-
limits: [{ limit: 10_000_000n, token:
|
|
30
|
-
scopes: [Scopes.tip20(
|
|
25
|
+
limits: [{ limit: 10_000_000n, token: Addresses.pathUsd }],
|
|
26
|
+
scopes: [Scopes.tip20(Addresses.pathUsd).transfer()],
|
|
31
27
|
},
|
|
32
28
|
})
|
|
33
29
|
|
|
@@ -35,7 +31,7 @@ await client.token.transferSync({
|
|
|
35
31
|
account: authorization!.account,
|
|
36
32
|
amount: 10_000n,
|
|
37
33
|
to: '0x…',
|
|
38
|
-
token:
|
|
34
|
+
token: Addresses.pathUsd,
|
|
39
35
|
})
|
|
40
36
|
```
|
|
41
37
|
|
|
@@ -54,14 +50,14 @@ The CLI device grant needs neither. It signs in as Tempo Auth's own `tempo-cli`
|
|
|
54
50
|
|
|
55
51
|
## Access keys
|
|
56
52
|
|
|
57
|
-
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:
|
|
58
54
|
|
|
59
|
-
| Field | Meaning
|
|
60
|
-
| --------- |
|
|
61
|
-
| `chainId` |
|
|
62
|
-
| `expiry` | When the key expires, in Unix seconds, such as `Expiry.days(1)
|
|
63
|
-
| `limits` | One-time spending limits per token, such as `[{ limit: 10_000_000n, token }]
|
|
64
|
-
| `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()]` |
|
|
65
61
|
|
|
66
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.
|
|
67
63
|
|
|
@@ -69,10 +65,10 @@ To authorize a key the app already holds, pass it as `accessKey`, a viem account
|
|
|
69
65
|
|
|
70
66
|
```ts
|
|
71
67
|
const accessKey = Account.fromWebCryptoP256(keyPair, { access: tempoAccount })
|
|
72
|
-
await Actions.authorize(auth, { accessKey })
|
|
68
|
+
await Actions.authorize(auth, { accessKey, permissions })
|
|
73
69
|
```
|
|
74
70
|
|
|
75
|
-
Flows without a Tempo Auth page (`authorize`, `email.signIn`) must stay within Tempo Auth's ceiling
|
|
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.
|
|
76
72
|
|
|
77
73
|
The returned `account` attaches the key's authorization to its first transaction, which registers the key on chain.
|
|
78
74
|
|
|
@@ -84,11 +80,11 @@ For a browser app that renders its own email form. The page calls Tempo Auth wit
|
|
|
84
80
|
|
|
85
81
|
```ts
|
|
86
82
|
// A user already signed in to Tempo Auth, from any app, needs no form.
|
|
87
|
-
const authorization = await Actions.authorize(auth)
|
|
83
|
+
const authorization = await Actions.authorize(auth, { permissions })
|
|
88
84
|
|
|
89
85
|
// Otherwise, sign in with an emailed code.
|
|
90
86
|
await Actions.email.sendCode(auth, { email })
|
|
91
|
-
const result = await Actions.email.signIn(auth, { code, email })
|
|
87
|
+
const result = await Actions.email.signIn(auth, { code, email, permissions })
|
|
92
88
|
|
|
93
89
|
// An address that requires SSO continues at its connection, and returns to this page.
|
|
94
90
|
if ('step' in result) Actions.provider.signIn(auth, { url: result.step.url })
|
|
@@ -106,7 +102,7 @@ Actions.provider.signIn(auth, { provider: 'google' })
|
|
|
106
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.
|
|
107
103
|
|
|
108
104
|
```ts
|
|
109
|
-
await Actions.redirect.start(auth)
|
|
105
|
+
await Actions.redirect.start(auth, { permissions })
|
|
110
106
|
|
|
111
107
|
// On the page the browser returns to, and on every load:
|
|
112
108
|
const authorization = await Actions.redirect.complete(auth)
|
|
@@ -129,10 +125,12 @@ const auth = Auth.create({
|
|
|
129
125
|
|
|
130
126
|
// Your own sign-in UI, as in a browser.
|
|
131
127
|
await Actions.email.sendCode(auth, { email })
|
|
132
|
-
const result = await Actions.email.signIn(auth, { code, email })
|
|
128
|
+
const result = await Actions.email.signIn(auth, { code, email, permissions })
|
|
133
129
|
|
|
134
130
|
// Or Tempo Auth's pages, which also offer Google and SSO.
|
|
135
|
-
const { pending, url } = await Actions.redirect.createUrl(auth
|
|
131
|
+
const { pending, url } = await Actions.redirect.createUrl(auth, {
|
|
132
|
+
permissions,
|
|
133
|
+
})
|
|
136
134
|
const session = await WebBrowser.openAuthSessionAsync(url, auth.redirectUri)
|
|
137
135
|
if (session.type === 'success')
|
|
138
136
|
authorization = await Actions.redirect.handleCallback(auth, {
|
|
@@ -152,6 +150,7 @@ const auth = Auth.create({ clientId, clientSecret, url })
|
|
|
152
150
|
|
|
153
151
|
// GET /auth/start
|
|
154
152
|
const { pending, url } = await Actions.redirect.createUrl(auth, {
|
|
153
|
+
permissions,
|
|
155
154
|
redirectUri: 'https://app.example/auth/callback',
|
|
156
155
|
})
|
|
157
156
|
// Keep `pending` in an encrypted, HttpOnly cookie, then redirect to `url`.
|
|
@@ -170,6 +169,7 @@ For a command-line tool. The user approves a code in any browser, and the CLI wa
|
|
|
170
169
|
```ts
|
|
171
170
|
const device = await Actions.device.authorize(auth, {
|
|
172
171
|
device: os.hostname(),
|
|
172
|
+
permissions,
|
|
173
173
|
})
|
|
174
174
|
console.log(
|
|
175
175
|
`Open ${device.verificationUriComplete} and confirm ${device.userCode}.`,
|
|
@@ -189,6 +189,7 @@ await Actions.authorize(auth, {
|
|
|
189
189
|
accessKey: Account.fromWebCryptoP256(keyPair, {
|
|
190
190
|
access: tempoAccount.address,
|
|
191
191
|
}),
|
|
192
|
+
permissions,
|
|
192
193
|
})
|
|
193
194
|
```
|
|
194
195
|
|
|
@@ -219,7 +220,7 @@ A request Tempo Auth refuses throws `Auth.RequestError`, with its `status` and `
|
|
|
219
220
|
|
|
220
221
|
```ts
|
|
221
222
|
try {
|
|
222
|
-
await Actions.email.signIn(auth, { code, email })
|
|
223
|
+
await Actions.email.signIn(auth, { code, email, permissions })
|
|
223
224
|
} catch (error) {
|
|
224
225
|
if (error instanceof Auth.RequestError && error.status === 401)
|
|
225
226
|
showWrongCode()
|
|
@@ -243,22 +244,22 @@ try {
|
|
|
243
244
|
|
|
244
245
|
### `Actions`
|
|
245
246
|
|
|
246
|
-
Each sign-in flow has its own namespace. The actions every flow shares sit at the top level. Every action that
|
|
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`.
|
|
247
248
|
|
|
248
249
|
| Action | Returns |
|
|
249
250
|
| -------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
250
|
-
| `authorize(auth)`
|
|
251
|
+
| `authorize(auth, { permissions })` | An `Authorization` for a user already signed in, or `undefined` |
|
|
251
252
|
| `refresh(auth, { refreshToken })` | New `Tokens` |
|
|
252
253
|
| `signOut(auth)` | Nothing. The user's Tempo Auth session ends |
|
|
253
|
-
| `device.authorize(auth, { device })`
|
|
254
|
+
| `device.authorize(auth, { device, permissions })` | The code to show and a `wait()` that resolves with an `Authorization` |
|
|
254
255
|
| `email.sendCode(auth, { email })` | Nothing. Tempo Auth emails a code |
|
|
255
|
-
| `email.signIn(auth, { code, email })`
|
|
256
|
+
| `email.signIn(auth, { code, email, permissions })` | An `Authorization`, or the `step` the address requires first |
|
|
256
257
|
| `provider.list(auth)` | The OAuth providers Tempo Auth offers, as `{ id, name }` |
|
|
257
258
|
| `provider.signIn(auth, { provider } \| { url })` | Nothing. The browser leaves for the provider or SSO connection |
|
|
258
259
|
| `redirect.complete(auth, { accessKey })` | The `Authorization` when the page is a redirect's callback, or `undefined` |
|
|
259
|
-
| `redirect.createUrl(auth, { redirectUri })`
|
|
260
|
+
| `redirect.createUrl(auth, { permissions, redirectUri })` | The `url` to send the browser to, and the `pending` state to keep |
|
|
260
261
|
| `redirect.handleCallback(auth, { pending, url })` | The `Authorization` for a redirect's callback |
|
|
261
|
-
| `redirect.start(auth)`
|
|
262
|
+
| `redirect.start(auth, { permissions })` | Nothing. The browser leaves for Tempo Auth's pages |
|
|
262
263
|
| `tempoAccount.create(auth)` | Another Tempo Account for the signed-in user |
|
|
263
264
|
| `tempoAccount.list(auth)` | The signed-in user's Tempo Accounts, the default first |
|
|
264
265
|
|
package/dist/Actions.d.ts
CHANGED
|
@@ -20,11 +20,11 @@ export * as tempoAccount from './actions/tempoAccount.ts';
|
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* ```ts
|
|
23
|
-
* const authorization = await Actions.authorize(auth)
|
|
23
|
+
* const authorization = await Actions.authorize(auth, { permissions })
|
|
24
24
|
* if (!authorization) showSignIn()
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
|
-
export declare function authorize(auth: Auth, options
|
|
27
|
+
export declare function authorize(auth: Auth, options: authorize.Options): Promise<authorize.ReturnType>;
|
|
28
28
|
export declare namespace authorize {
|
|
29
29
|
type Options = {
|
|
30
30
|
/**
|
|
@@ -32,8 +32,8 @@ export declare namespace authorize {
|
|
|
32
32
|
* defaults to the user's first. Defaults to a new key.
|
|
33
33
|
*/
|
|
34
34
|
accessKey?: Account.Account | undefined;
|
|
35
|
-
/** What the key may do. It must fit the headless ceiling
|
|
36
|
-
permissions
|
|
35
|
+
/** What the key may do. It must fit the headless ceiling. */
|
|
36
|
+
permissions: Permissions;
|
|
37
37
|
};
|
|
38
38
|
/** The authorization, or `undefined` without a session. */
|
|
39
39
|
type ReturnType = Authorization | undefined;
|
package/dist/Actions.js
CHANGED
|
@@ -13,11 +13,11 @@ export * as tempoAccount from './actions/tempoAccount.js';
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* ```ts
|
|
16
|
-
* const authorization = await Actions.authorize(auth)
|
|
16
|
+
* const authorization = await Actions.authorize(auth, { permissions })
|
|
17
17
|
* if (!authorization) showSignIn()
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
|
-
export async function authorize(auth, options
|
|
20
|
+
export async function authorize(auth, options) {
|
|
21
21
|
// Checking the session first answers a visitor without one with no failed request.
|
|
22
22
|
const session = await Api.json(await (auth.fetch ?? fetch)(new URL('/api/auth/session', auth.url), {
|
|
23
23
|
credentials: 'include',
|
package/dist/Auth.js
CHANGED
|
@@ -6,11 +6,8 @@
|
|
|
6
6
|
* @example
|
|
7
7
|
* ```ts
|
|
8
8
|
* import { Actions, Auth } from '@tempoxyz/auth'
|
|
9
|
-
* import { Expiry, Scopes } from 'viem/tempo'
|
|
10
|
-
* import {
|
|
11
|
-
* import * as Tokens from 'viem/tokens'
|
|
12
|
-
*
|
|
13
|
-
* const ousd = Tokens.ousd(tempo.id).address
|
|
9
|
+
* import { Addresses, Expiry, Scopes } from 'viem/tempo'
|
|
10
|
+
* import { tempoTestnet } from 'viem/tempo/chains'
|
|
14
11
|
*
|
|
15
12
|
* const auth = Auth.create({
|
|
16
13
|
* chainId: tempoTestnet.id,
|
|
@@ -21,8 +18,8 @@
|
|
|
21
18
|
* const authorization = await Actions.authorize(auth, {
|
|
22
19
|
* permissions: {
|
|
23
20
|
* expiry: Expiry.days(1),
|
|
24
|
-
* limits: [{ limit: 10_000_000n, token:
|
|
25
|
-
* scopes: [Scopes.tip20(
|
|
21
|
+
* limits: [{ limit: 10_000_000n, token: Addresses.pathUsd }],
|
|
22
|
+
* scopes: [Scopes.tip20(Addresses.pathUsd).transfer()],
|
|
26
23
|
* },
|
|
27
24
|
* })
|
|
28
25
|
* ```
|
package/dist/Permissions.d.ts
CHANGED
|
@@ -3,19 +3,12 @@
|
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
5
|
import type { KeyAuthorization } from 'ox/tempo';
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
* it leaves out with the headless ceiling.
|
|
9
|
-
*/
|
|
10
|
-
export type Permissions = {
|
|
6
|
+
/** What an app's access key may do, as viem's `accessKey.authorize` takes it. */
|
|
7
|
+
export type Permissions = Pick<KeyAuthorization.KeyAuthorization, 'limits' | 'scopes'> & {
|
|
11
8
|
/** The chain the key acts on, such as `tempoTestnet.id`. Defaults to the instance's `chainId`. */
|
|
12
9
|
chainId?: number | undefined;
|
|
13
|
-
/** Unix seconds. viem's `Expiry` builds one, such as `Expiry.days(1)`.
|
|
14
|
-
expiry
|
|
15
|
-
/** How much of each token the key may spend. Defaults to about $1,000 of each token it calls, or of OUSD. */
|
|
16
|
-
limits?: KeyAuthorization.KeyAuthorization['limits'];
|
|
17
|
-
/** The calls the key may make. Defaults to transfers of each token it limits. */
|
|
18
|
-
scopes?: KeyAuthorization.KeyAuthorization['scopes'];
|
|
10
|
+
/** Unix seconds. viem's `Expiry` builds one, such as `Expiry.days(1)`. */
|
|
11
|
+
expiry: number;
|
|
19
12
|
};
|
|
20
13
|
/**
|
|
21
14
|
* Instantiates a {@link Permissions}.
|
|
@@ -24,8 +17,8 @@ export type Permissions = {
|
|
|
24
17
|
* ```ts
|
|
25
18
|
* const permissions = Permissions.from({
|
|
26
19
|
* expiry: Expiry.days(1),
|
|
27
|
-
* limits: [{ limit: 10_000_000n, token:
|
|
28
|
-
* scopes: [Scopes.tip20(
|
|
20
|
+
* limits: [{ limit: 10_000_000n, token: Addresses.pathUsd }],
|
|
21
|
+
* scopes: [Scopes.tip20(Addresses.pathUsd).transfer()],
|
|
29
22
|
* })
|
|
30
23
|
* ```
|
|
31
24
|
*/
|
package/dist/Permissions.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* ```ts
|
|
6
6
|
* const permissions = Permissions.from({
|
|
7
7
|
* expiry: Expiry.days(1),
|
|
8
|
-
* limits: [{ limit: 10_000_000n, token:
|
|
9
|
-
* scopes: [Scopes.tip20(
|
|
8
|
+
* limits: [{ limit: 10_000_000n, token: Addresses.pathUsd }],
|
|
9
|
+
* scopes: [Scopes.tip20(Addresses.pathUsd).transfer()],
|
|
10
10
|
* })
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
package/dist/actions/device.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { Permissions } from '../Permissions.ts';
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```ts
|
|
11
|
-
* const device = await Actions.device.authorize(auth, { device: Os.hostname() })
|
|
11
|
+
* const device = await Actions.device.authorize(auth, { device: Os.hostname(), permissions })
|
|
12
12
|
* console.log(`Open ${device.verificationUriComplete}`)
|
|
13
13
|
* const authorization = await device.wait()
|
|
14
14
|
* ```
|
|
@@ -23,8 +23,8 @@ export declare namespace authorize {
|
|
|
23
23
|
accessKey?: Account.Account | undefined;
|
|
24
24
|
/** The name the approval page shows, such as the machine's hostname. */
|
|
25
25
|
device: string;
|
|
26
|
-
/** What the CLI's key may do. The approval page shows it beside the device
|
|
27
|
-
permissions
|
|
26
|
+
/** What the CLI's key may do. The approval page shows it beside the device. */
|
|
27
|
+
permissions: Permissions;
|
|
28
28
|
};
|
|
29
29
|
type ReturnType = {
|
|
30
30
|
/** Seconds until the code expires. */
|
package/dist/actions/device.js
CHANGED
|
@@ -8,7 +8,7 @@ import { request } from '../internal/request.js';
|
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* ```ts
|
|
11
|
-
* const device = await Actions.device.authorize(auth, { device: Os.hostname() })
|
|
11
|
+
* const device = await Actions.device.authorize(auth, { device: Os.hostname(), permissions })
|
|
12
12
|
* console.log(`Open ${device.verificationUriComplete}`)
|
|
13
13
|
* const authorization = await device.wait()
|
|
14
14
|
* ```
|
package/dist/actions/email.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export declare namespace sendCode {
|
|
|
28
28
|
*
|
|
29
29
|
* @example
|
|
30
30
|
* ```ts
|
|
31
|
-
* const result = await Actions.email.signIn(auth, { code, email })
|
|
31
|
+
* const result = await Actions.email.signIn(auth, { code, email, permissions })
|
|
32
32
|
* if ('step' in result) Actions.provider.signIn(auth, { url: result.step.url })
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
@@ -44,8 +44,8 @@ export declare namespace signIn {
|
|
|
44
44
|
code: string;
|
|
45
45
|
/** The address the code was sent to. */
|
|
46
46
|
email: string;
|
|
47
|
-
/** What the key may do. It must fit the headless ceiling
|
|
48
|
-
permissions
|
|
47
|
+
/** What the key may do. It must fit the headless ceiling. */
|
|
48
|
+
permissions: Permissions;
|
|
49
49
|
};
|
|
50
50
|
/** The authorization, or the step the address requires first. */
|
|
51
51
|
type ReturnType = Authorization | {
|
package/dist/actions/email.js
CHANGED
|
@@ -18,7 +18,7 @@ export async function sendCode(auth, options) {
|
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* ```ts
|
|
21
|
-
* const result = await Actions.email.signIn(auth, { code, email })
|
|
21
|
+
* const result = await Actions.email.signIn(auth, { code, email, permissions })
|
|
22
22
|
* if ('step' in result) Actions.provider.signIn(auth, { url: result.step.url })
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
@@ -11,7 +11,7 @@ import type { Permissions } from '../Permissions.ts';
|
|
|
11
11
|
* ```ts
|
|
12
12
|
* const authorization =
|
|
13
13
|
* (await Actions.redirect.complete(auth)) ??
|
|
14
|
-
* (await Actions.authorize(auth))
|
|
14
|
+
* (await Actions.authorize(auth, { permissions }))
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
17
|
export declare function complete(auth: Auth, options?: complete.Options): Promise<complete.ReturnType>;
|
|
@@ -31,13 +31,14 @@ export declare namespace complete {
|
|
|
31
31
|
* @example
|
|
32
32
|
* ```ts
|
|
33
33
|
* const { pending, url } = await Actions.redirect.createUrl(auth, {
|
|
34
|
+
* permissions,
|
|
34
35
|
* redirectUri: 'https://app.example/auth/callback',
|
|
35
36
|
* })
|
|
36
37
|
* await seal(c, 'oauth', pending)
|
|
37
38
|
* return c.redirect(url)
|
|
38
39
|
* ```
|
|
39
40
|
*/
|
|
40
|
-
export declare function createUrl(auth: Auth, options
|
|
41
|
+
export declare function createUrl(auth: Auth, options: createUrl.Options): Promise<createUrl.ReturnType>;
|
|
41
42
|
export declare namespace createUrl {
|
|
42
43
|
type Options = {
|
|
43
44
|
/**
|
|
@@ -45,8 +46,8 @@ export declare namespace createUrl {
|
|
|
45
46
|
* defaults to the user's first. Defaults to a new key, whose material `pending` keeps.
|
|
46
47
|
*/
|
|
47
48
|
accessKey?: Account.Account | undefined;
|
|
48
|
-
/** What the key may do. Tempo Auth's pages show it, and the
|
|
49
|
-
permissions
|
|
49
|
+
/** What the key may do. Tempo Auth's pages show it, and the user approves it. */
|
|
50
|
+
permissions: Permissions;
|
|
50
51
|
/** Where Tempo Auth redirects back to. Defaults to the instance's `redirectUri`. */
|
|
51
52
|
redirectUri?: string | undefined;
|
|
52
53
|
};
|
|
@@ -86,10 +87,10 @@ export declare namespace handleCallback {
|
|
|
86
87
|
*
|
|
87
88
|
* @example
|
|
88
89
|
* ```ts
|
|
89
|
-
* await Actions.redirect.start(auth)
|
|
90
|
+
* await Actions.redirect.start(auth, { permissions })
|
|
90
91
|
* ```
|
|
91
92
|
*/
|
|
92
|
-
export declare function start(auth: Auth, options
|
|
93
|
+
export declare function start(auth: Auth, options: start.Options): Promise<void>;
|
|
93
94
|
export declare namespace start {
|
|
94
95
|
type Options = {
|
|
95
96
|
/**
|
|
@@ -97,7 +98,7 @@ export declare namespace start {
|
|
|
97
98
|
* key, which `storage` keeps until the browser returns.
|
|
98
99
|
*/
|
|
99
100
|
accessKey?: Account.Account | undefined;
|
|
100
|
-
/** What the key may do. Tempo Auth's pages show it, and the
|
|
101
|
-
permissions
|
|
101
|
+
/** What the key may do. Tempo Auth's pages show it, and the user approves it. */
|
|
102
|
+
permissions: Permissions;
|
|
102
103
|
};
|
|
103
104
|
}
|
package/dist/actions/redirect.js
CHANGED
|
@@ -19,7 +19,7 @@ import * as Pending from '../Pending.js';
|
|
|
19
19
|
* ```ts
|
|
20
20
|
* const authorization =
|
|
21
21
|
* (await Actions.redirect.complete(auth)) ??
|
|
22
|
-
* (await Actions.authorize(auth))
|
|
22
|
+
* (await Actions.authorize(auth, { permissions }))
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
export function complete(auth, options = {}) {
|
|
@@ -53,13 +53,14 @@ export function complete(auth, options = {}) {
|
|
|
53
53
|
* @example
|
|
54
54
|
* ```ts
|
|
55
55
|
* const { pending, url } = await Actions.redirect.createUrl(auth, {
|
|
56
|
+
* permissions,
|
|
56
57
|
* redirectUri: 'https://app.example/auth/callback',
|
|
57
58
|
* })
|
|
58
59
|
* await seal(c, 'oauth', pending)
|
|
59
60
|
* return c.redirect(url)
|
|
60
61
|
* ```
|
|
61
62
|
*/
|
|
62
|
-
export async function createUrl(auth, options
|
|
63
|
+
export async function createUrl(auth, options) {
|
|
63
64
|
const redirectUri = options.redirectUri ?? auth.redirectUri ?? `${window.location.origin}/`;
|
|
64
65
|
const key = await AccessKey.resolve(options.accessKey);
|
|
65
66
|
const pending = Pending.from({
|
|
@@ -128,10 +129,10 @@ export async function handleCallback(auth, options) {
|
|
|
128
129
|
*
|
|
129
130
|
* @example
|
|
130
131
|
* ```ts
|
|
131
|
-
* await Actions.redirect.start(auth)
|
|
132
|
+
* await Actions.redirect.start(auth, { permissions })
|
|
132
133
|
* ```
|
|
133
134
|
*/
|
|
134
|
-
export async function start(auth, options
|
|
135
|
+
export async function start(auth, options) {
|
|
135
136
|
const { pending, url } = await createUrl(auth, options);
|
|
136
137
|
await storage(auth).setItem(storageKey, pending);
|
|
137
138
|
window.location.assign(url);
|
package/dist/internal/api.js
CHANGED
|
@@ -29,12 +29,9 @@ export function authorization(body, options) {
|
|
|
29
29
|
export async function json(response) {
|
|
30
30
|
// Some refusals, such as the CSRF check's, answer plain text.
|
|
31
31
|
const body = (await response.json().catch(() => ({})));
|
|
32
|
-
// OAuth-style refusals, such as the device grant's, put the explanation beside a code.
|
|
33
32
|
if (!response.ok)
|
|
34
33
|
throw new RequestError({
|
|
35
|
-
message: body.
|
|
36
|
-
body.error ??
|
|
37
|
-
`Request failed with status ${response.status}.`,
|
|
34
|
+
message: body.error ?? 'Something went wrong.',
|
|
38
35
|
status: response.status,
|
|
39
36
|
});
|
|
40
37
|
return body;
|
|
@@ -7,14 +7,14 @@ import type { Permissions } from '../Permissions.ts';
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function request(auth: Auth, options: {
|
|
9
9
|
accessKey: Account.Account;
|
|
10
|
-
permissions
|
|
10
|
+
permissions: Permissions;
|
|
11
11
|
}): {
|
|
12
12
|
client_id: string;
|
|
13
13
|
keyAuthorization: {
|
|
14
14
|
account?: `0x${string}`;
|
|
15
15
|
address: `0x${string}`;
|
|
16
16
|
chainId: `0x${string}`;
|
|
17
|
-
expiry: number
|
|
17
|
+
expiry: number;
|
|
18
18
|
keyType: "p256" | "secp256k1" | "webAuthn";
|
|
19
19
|
limits: {
|
|
20
20
|
limit: `0x${string}`;
|
package/dist/internal/request.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Hex } from 'ox';
|
|
|
9
9
|
* key account names its Tempo Account through `access`, and a plain key leaves it to Tempo Auth.
|
|
10
10
|
*/
|
|
11
11
|
export function request(auth, options) {
|
|
12
|
-
const { accessKey, permissions
|
|
12
|
+
const { accessKey, permissions } = options;
|
|
13
13
|
return {
|
|
14
14
|
client_id: auth.clientId,
|
|
15
15
|
keyAuthorization: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tempoxyz/auth",
|
|
3
|
-
"version": "0.0.0-pr-
|
|
3
|
+
"version": "0.0.0-pr-31.sha-03ddfa6",
|
|
4
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": {
|