@tempoxyz/auth 0.0.0-pr-87.sha-bc40370 → 0.0.0-pr-87.sha-226d5ea
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/dist/Actions.d.ts +15 -2
- package/dist/Actions.js +32 -9
- package/dist/Decorator.d.ts +0 -5
- package/dist/Decorator.js +0 -7
- package/dist/actions/account.d.ts +4 -24
- package/dist/actions/account.js +3 -21
- package/package.json +1 -1
package/dist/Actions.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* every flow shares sit at the top level.
|
|
5
5
|
* @module
|
|
6
6
|
*/
|
|
7
|
+
import { Authentication } from 'ox/webauthn';
|
|
7
8
|
import type { Account } from 'viem/tempo';
|
|
8
9
|
import type { Auth } from './Auth.ts';
|
|
9
10
|
import type { Authorization } from './Authorization.ts';
|
|
@@ -20,7 +21,12 @@ export * as redirect from './actions/redirect.ts';
|
|
|
20
21
|
/**
|
|
21
22
|
* Authorizes the app for a user already signed in to Tempo Auth, from any app. Returns
|
|
22
23
|
* `undefined` without a session, so the app shows sign-in. The key must fit Tempo Auth's headless
|
|
23
|
-
* ceiling.
|
|
24
|
+
* ceiling. An `account` the call names becomes the app's account for its later requests, such as
|
|
25
|
+
* the one the user chose from a sign-in's account step.
|
|
26
|
+
*
|
|
27
|
+
* A passkey-owned account signs the key with a passkey prompt on the page, when the page is the
|
|
28
|
+
* app's own on Tempo's domain. Elsewhere the call throws a `RequestError` with reason
|
|
29
|
+
* `webauthn_required`, and `Actions.redirect.start` authorizes the key on Tempo Auth's pages.
|
|
24
30
|
*
|
|
25
31
|
* @example
|
|
26
32
|
* ```ts
|
|
@@ -38,7 +44,8 @@ export declare namespace authorize {
|
|
|
38
44
|
accessKey?: Account.Account | undefined;
|
|
39
45
|
/**
|
|
40
46
|
* The address of the user's Tempo Account the key acts for, such as the one the user chose from
|
|
41
|
-
* a sign-in's account step. Takes the place of `accessKey`'s `access
|
|
47
|
+
* a sign-in's account step. Takes the place of `accessKey`'s `access`, and becomes the app's
|
|
48
|
+
* account for its later requests that name none.
|
|
42
49
|
*/
|
|
43
50
|
account?: `0x${string}` | undefined;
|
|
44
51
|
/**
|
|
@@ -47,6 +54,12 @@ export declare namespace authorize {
|
|
|
47
54
|
* `tempo-auth:sign` scope may send one.
|
|
48
55
|
*/
|
|
49
56
|
challenge?: string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Runs the WebAuthn ceremony in place of `navigator.credentials.get`, for a passkey-owned
|
|
59
|
+
* account, such as a native passkey module. Its assertion must report a web origin on the
|
|
60
|
+
* relying party's domain that the app registered.
|
|
61
|
+
*/
|
|
62
|
+
getFn?: Authentication.sign.Options['getFn'] | undefined;
|
|
50
63
|
/** What the key may do. It must fit the headless ceiling, which fills what it leaves out. */
|
|
51
64
|
permissions?: Permissions<chainId> | undefined;
|
|
52
65
|
};
|
package/dist/Actions.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tempo Auth's actions. Each takes an instance from `Auth.create`. Each sign-in flow has its own
|
|
3
|
+
* namespace, `oauth` holds the standard OAuth endpoints for tokens an app holds, and the actions
|
|
4
|
+
* every flow shares sit at the top level.
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { Authentication } from 'ox/webauthn';
|
|
1
8
|
import * as AccessKey from './internal/accessKey.js';
|
|
2
9
|
import * as Api from './internal/api.js';
|
|
3
10
|
import { request } from './internal/request.js';
|
|
@@ -12,7 +19,12 @@ export * as redirect from './actions/redirect.js';
|
|
|
12
19
|
/**
|
|
13
20
|
* Authorizes the app for a user already signed in to Tempo Auth, from any app. Returns
|
|
14
21
|
* `undefined` without a session, so the app shows sign-in. The key must fit Tempo Auth's headless
|
|
15
|
-
* ceiling.
|
|
22
|
+
* ceiling. An `account` the call names becomes the app's account for its later requests, such as
|
|
23
|
+
* the one the user chose from a sign-in's account step.
|
|
24
|
+
*
|
|
25
|
+
* A passkey-owned account signs the key with a passkey prompt on the page, when the page is the
|
|
26
|
+
* app's own on Tempo's domain. Elsewhere the call throws a `RequestError` with reason
|
|
27
|
+
* `webauthn_required`, and `Actions.redirect.start` authorizes the key on Tempo Auth's pages.
|
|
16
28
|
*
|
|
17
29
|
* @example
|
|
18
30
|
* ```ts
|
|
@@ -28,17 +40,28 @@ export async function authorize(auth, options = {}) {
|
|
|
28
40
|
if (!session.user)
|
|
29
41
|
return undefined;
|
|
30
42
|
const key = await AccessKey.resolve(options.accessKey);
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
permissions: options.permissions,
|
|
37
|
-
}),
|
|
43
|
+
const json = request(auth, {
|
|
44
|
+
accessKey: key.accessKey,
|
|
45
|
+
account: options.account,
|
|
46
|
+
challenge: options.challenge,
|
|
47
|
+
permissions: options.permissions,
|
|
38
48
|
});
|
|
49
|
+
const response = await Api.post(auth, '/v1/authorize', { json });
|
|
39
50
|
if (response.status === 401)
|
|
40
51
|
return undefined;
|
|
41
|
-
|
|
52
|
+
const body = await Api.json(response);
|
|
53
|
+
if (!('step' in body))
|
|
54
|
+
return Api.authorization(body, key);
|
|
55
|
+
// The step's challenge is the key's digest, so the repeated request carries the signature.
|
|
56
|
+
const deserialized = Authentication.deserializeOptions(body.step.options);
|
|
57
|
+
const assertion = Authentication.serializeResponse(await Authentication.sign(
|
|
58
|
+
// ox reads `getFn` beside request options at runtime, which its types admit only beside a challenge.
|
|
59
|
+
options.getFn
|
|
60
|
+
? { ...deserialized, getFn: options.getFn }
|
|
61
|
+
: deserialized));
|
|
62
|
+
return Api.authorization(await Api.json(await Api.post(auth, '/v1/authorize', {
|
|
63
|
+
json: { ...json, passkey: { assertion } },
|
|
64
|
+
})), key);
|
|
42
65
|
}
|
|
43
66
|
/**
|
|
44
67
|
* Exchanges a refresh token for new tokens. Refresh tokens rotate, so store the new one.
|
package/dist/Decorator.d.ts
CHANGED
|
@@ -73,11 +73,6 @@ export declare namespace tempoAuth {
|
|
|
73
73
|
account: {
|
|
74
74
|
/** `Actions.account.get`. */
|
|
75
75
|
get: () => Promise<Actions.account.get.ReturnType>;
|
|
76
|
-
/**
|
|
77
|
-
* `Actions.account.select`, which empties the client's account until the app authorizes
|
|
78
|
-
* the selected one.
|
|
79
|
-
*/
|
|
80
|
-
select: (options: Actions.account.select.Options) => Promise<void>;
|
|
81
76
|
};
|
|
82
77
|
/**
|
|
83
78
|
* `Actions.authorize`, which sets the client's account, or empties it when the user has no
|
package/dist/Decorator.js
CHANGED
|
@@ -100,13 +100,6 @@ export function tempoAuth(options) {
|
|
|
100
100
|
auth: {
|
|
101
101
|
account: {
|
|
102
102
|
get: () => Actions.account.get(auth),
|
|
103
|
-
// The client stops signing as the previous account, which the app reauthorizes for the
|
|
104
|
-
// selected one.
|
|
105
|
-
async select(options) {
|
|
106
|
-
const change = begin();
|
|
107
|
-
await Actions.account.select(auth, options).catch(change.fail);
|
|
108
|
-
await change.apply(undefined);
|
|
109
|
-
},
|
|
110
103
|
},
|
|
111
104
|
async authorize(options = {}) {
|
|
112
105
|
const change = begin();
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Reads
|
|
2
|
+
* Reads the signed-in user's Tempo Account for the app, with its realm.
|
|
3
3
|
* @module
|
|
4
4
|
*/
|
|
5
5
|
import type { Auth } from '../Auth.ts';
|
|
6
6
|
import type { TempoAccount } from '../TempoAccount.ts';
|
|
7
7
|
/**
|
|
8
|
-
* Returns the signed-in user's Tempo Account for the app
|
|
9
|
-
*
|
|
10
|
-
* receives one in its first.
|
|
8
|
+
* Returns the signed-in user's Tempo Account for the app, with its `realm`: the one selected at
|
|
9
|
+
* sign-in or last named in `Actions.authorize`, or else their oldest in the app's realms. A user
|
|
10
|
+
* with no account in the app's realms receives one in its first.
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```ts
|
|
@@ -20,23 +20,3 @@ export declare namespace get {
|
|
|
20
20
|
/** The user's Tempo Account for the app. */
|
|
21
21
|
type ReturnType = TempoAccount;
|
|
22
22
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Selects one of the signed-in user's Tempo Accounts as the app's, after a sign-in's account step.
|
|
25
|
-
* The app's requests that name no account use it until sign-out or the app's next sign-in.
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```ts
|
|
29
|
-
* const result = await Actions.email.signIn(auth, { code, email })
|
|
30
|
-
* if ('step' in result && result.step.type === 'account') {
|
|
31
|
-
* const [chosen] = result.step.accounts
|
|
32
|
-
* await Actions.account.select(auth, { address: chosen!.address })
|
|
33
|
-
* }
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
export declare function select(auth: Auth, options: select.Options): Promise<void>;
|
|
37
|
-
export declare namespace select {
|
|
38
|
-
type Options = {
|
|
39
|
-
/** The address of one of the user's accounts, as the account step lists it. */
|
|
40
|
-
address: `0x${string}`;
|
|
41
|
-
};
|
|
42
|
-
}
|
package/dist/actions/account.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as Api from '../internal/api.js';
|
|
2
2
|
/**
|
|
3
|
-
* Returns the signed-in user's Tempo Account for the app
|
|
4
|
-
*
|
|
5
|
-
* receives one in its first.
|
|
3
|
+
* Returns the signed-in user's Tempo Account for the app, with its `realm`: the one selected at
|
|
4
|
+
* sign-in or last named in `Actions.authorize`, or else their oldest in the app's realms. A user
|
|
5
|
+
* with no account in the app's realms receives one in its first.
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
8
|
* ```ts
|
|
@@ -15,21 +15,3 @@ export async function get(auth) {
|
|
|
15
15
|
// Tempo Auth lists the account the app uses first, and always lists one.
|
|
16
16
|
return Api.tempoAccount(tempo[0]);
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Selects one of the signed-in user's Tempo Accounts as the app's, after a sign-in's account step.
|
|
20
|
-
* The app's requests that name no account use it until sign-out or the app's next sign-in.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```ts
|
|
24
|
-
* const result = await Actions.email.signIn(auth, { code, email })
|
|
25
|
-
* if ('step' in result && result.step.type === 'account') {
|
|
26
|
-
* const [chosen] = result.step.accounts
|
|
27
|
-
* await Actions.account.select(auth, { address: chosen!.address })
|
|
28
|
-
* }
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
export async function select(auth, options) {
|
|
32
|
-
await Api.json(await Api.post(auth, '/v1/auth/account', {
|
|
33
|
-
json: { account: options.address, client_id: auth.clientId },
|
|
34
|
-
}));
|
|
35
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tempoxyz/auth",
|
|
3
|
-
"version": "0.0.0-pr-87.sha-
|
|
3
|
+
"version": "0.0.0-pr-87.sha-226d5ea",
|
|
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": {
|