@tempoxyz/auth 0.0.0-pr-73.sha-5d2ffa4 → 0.0.0-pr-84.sha-d9e4bad

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 CHANGED
@@ -12,7 +12,6 @@ import type { Tokens } from './Tokens.ts';
12
12
  export * as device from './actions/device.ts';
13
13
  export * as email from './actions/email.ts';
14
14
  export * as oauth from './actions/oauth.ts';
15
- export * as passkey from './actions/passkey.ts';
16
15
  export * as provider from './actions/provider.ts';
17
16
  export * as redirect from './actions/redirect.ts';
18
17
  export * as tempoAccount from './actions/tempoAccount.ts';
@@ -35,12 +34,6 @@ export declare namespace authorize {
35
34
  * defaults to the user's first. Defaults to a new key.
36
35
  */
37
36
  accessKey?: Account.Account | undefined;
38
- /**
39
- * A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
40
- * Tempo Auth binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
41
- * `tempo-auth:sign` scope may send one.
42
- */
43
- challenge?: string | undefined;
44
37
  /** What the key may do. It must fit the headless ceiling, which fills what it leaves out. */
45
38
  permissions?: Permissions<chainId> | undefined;
46
39
  };
package/dist/Actions.js CHANGED
@@ -4,7 +4,6 @@ import { request } from './internal/request.js';
4
4
  export * as device from './actions/device.js';
5
5
  export * as email from './actions/email.js';
6
6
  export * as oauth from './actions/oauth.js';
7
- export * as passkey from './actions/passkey.js';
8
7
  export * as provider from './actions/provider.js';
9
8
  export * as redirect from './actions/redirect.js';
10
9
  export * as tempoAccount from './actions/tempoAccount.js';
@@ -30,7 +29,6 @@ export async function authorize(auth, options = {}) {
30
29
  const response = await Api.post(auth, '/v1/authorize', {
31
30
  json: request(auth, {
32
31
  accessKey: key.accessKey,
33
- challenge: options.challenge,
34
32
  permissions: options.permissions,
35
33
  }),
36
34
  });
package/dist/Auth.d.ts CHANGED
@@ -86,7 +86,7 @@ export declare namespace RequestError {
86
86
  uri?: string | undefined;
87
87
  };
88
88
  /** Each refusal's stable name. `docs/errors.md` explains each one. */
89
- type Reason = 'already_decided' | 'approval_pending' | 'body_too_large' | 'challenge_not_permitted' | 'cross_site_request' | 'device_code_expired' | 'duplicate_limit' | 'empty_limits' | 'empty_scopes' | 'expiry_exceeds_maximum' | 'expiry_passed' | 'foreign_account' | 'foreign_origin' | 'invalid_chain' | 'invalid_code' | 'invalid_expiry' | 'invalid_field' | 'invalid_origin' | 'invalid_period' | 'invalid_public_key' | 'limit_exceeds_maximum' | 'malformed_body' | 'missing_code_challenge' | 'missing_key' | 'missing_recipients' | 'polling_too_fast' | 'rate_limited' | 'rejected' | 'request_denied' | 'scope_without_limit' | 'session_required' | 'unexpected' | 'unknown_code' | 'unknown_endpoint' | 'unsupported_call' | 'unsupported_step' | 'unsupported_token' | 'upstream_unavailable' | 'webauthn_rejected' | 'webauthn_required';
89
+ type Reason = 'already_decided' | 'approval_pending' | 'body_too_large' | 'cross_site_request' | 'device_code_expired' | 'duplicate_limit' | 'empty_limits' | 'empty_scopes' | 'expiry_exceeds_maximum' | 'expiry_passed' | 'foreign_account' | 'foreign_origin' | 'invalid_chain' | 'invalid_code' | 'invalid_expiry' | 'invalid_field' | 'invalid_origin' | 'invalid_period' | 'invalid_public_key' | 'limit_exceeds_maximum' | 'malformed_body' | 'missing_code_challenge' | 'missing_key' | 'missing_recipients' | 'polling_too_fast' | 'rate_limited' | 'rejected' | 'request_denied' | 'scope_without_limit' | 'session_required' | 'unexpected' | 'unknown_code' | 'unknown_endpoint' | 'unsupported_call' | 'unsupported_step' | 'unsupported_token' | 'upstream_unavailable';
90
90
  }
91
91
  /** A client's {@link Account} read before a sign-in set it, or after sign-out emptied it. */
92
92
  export declare class SignedOutError extends Error {
@@ -95,10 +95,6 @@ export declare namespace tempoAuth {
95
95
  /** `Actions.oauth.userInfo`. */
96
96
  userInfo: (options: Actions.oauth.userInfo.Options) => Promise<User>;
97
97
  };
98
- passkey: {
99
- /** `Actions.passkey.signIn`, which sets the client's account unless it returns a step. */
100
- signIn: <const id extends number = chainId>(options?: Actions.passkey.signIn.Options<id>) => Promise<Actions.passkey.signIn.ReturnType<id>>;
101
- };
102
98
  provider: {
103
99
  /** `Actions.provider.list`. */
104
100
  list: () => Promise<Actions.provider.list.ReturnType>;
package/dist/Decorator.js CHANGED
@@ -111,15 +111,6 @@ export function tempoAuth(options) {
111
111
  jwks: () => Actions.oauth.jwks(auth),
112
112
  userInfo: (options) => Actions.oauth.userInfo(auth, options),
113
113
  },
114
- passkey: {
115
- async signIn(options = {}) {
116
- const apply = begin();
117
- const result = await Actions.passkey.signIn(auth, options);
118
- if (!('step' in result))
119
- apply(result.account);
120
- return result;
121
- },
122
- },
123
114
  provider: {
124
115
  list: () => Actions.provider.list(auth),
125
116
  signIn: (options) => Actions.provider.signIn(auth, options),
@@ -6,19 +6,13 @@
6
6
  export type TempoAccount = {
7
7
  /** The account's address, the same on every Tempo chain. */
8
8
  address: `0x${string}`;
9
- /**
10
- * Who holds the account's owner key: a Privy wallet, which Tempo Auth signs with (`privy`), or a
11
- * passkey, which signs only on a Tempo Auth page (`webAuthn`). Treat another value as an owner
12
- * that may refuse a key authorization.
13
- */
14
- owner: 'privy' | 'webAuthn' | (string & {});
15
9
  };
16
10
  /**
17
11
  * Instantiates a {@link TempoAccount}.
18
12
  *
19
13
  * @example
20
14
  * ```ts
21
- * const tempoAccount = TempoAccount.from({ address: '0x…', owner: 'privy' })
15
+ * const tempoAccount = TempoAccount.from({ address: '0x…' })
22
16
  * ```
23
17
  */
24
18
  export declare function from(value: TempoAccount): TempoAccount;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @example
5
5
  * ```ts
6
- * const tempoAccount = TempoAccount.from({ address: '0x…', owner: 'privy' })
6
+ * const tempoAccount = TempoAccount.from({ address: '0x…' })
7
7
  * ```
8
8
  */
9
9
  export function from(value) {
@@ -21,12 +21,6 @@ export declare namespace authorize {
21
21
  * defaults to the user's first. Defaults to a new key.
22
22
  */
23
23
  accessKey?: Account.Account | undefined;
24
- /**
25
- * A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
26
- * Tempo Auth binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
27
- * `tempo-auth:sign` scope may send one.
28
- */
29
- challenge?: string | undefined;
30
24
  /**
31
25
  * The name the approval page shows. Defaults to the machine's hostname in Node, Bun, and Deno,
32
26
  * and to `Unknown device` elsewhere.
@@ -17,9 +17,6 @@ export async function authorize(auth, options = {}) {
17
17
  const key = await AccessKey.resolve(options.accessKey);
18
18
  const code = await Api.json(await Api.post(auth, '/v1/device/authorize', {
19
19
  json: {
20
- ...(options.challenge === undefined
21
- ? {}
22
- : { challenge: options.challenge }),
23
20
  device: options.device ?? hostname(),
24
21
  key_authorization: request(auth, {
25
22
  accessKey: key.accessKey,
@@ -40,21 +40,10 @@ export declare namespace signIn {
40
40
  * defaults to the user's first. Defaults to a new key.
41
41
  */
42
42
  accessKey?: Account.Account | undefined;
43
- /**
44
- * A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
45
- * Tempo Auth binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
46
- * `tempo-auth:sign` scope may send one.
47
- */
48
- challenge?: string | undefined;
49
43
  /** The 6-digit code the user was emailed. */
50
44
  code: string;
51
45
  /** The address the code was sent to. */
52
46
  email: string;
53
- /**
54
- * The `link` from `Actions.passkey.signIn`'s email step, which links that wallet.tempo passkey
55
- * to the user.
56
- */
57
- link?: string | undefined;
58
47
  /** What the key may do. It must fit the headless ceiling, which fills what it leaves out. */
59
48
  permissions?: Permissions<chainId> | undefined;
60
49
  };
@@ -23,18 +23,13 @@ export async function sendCode(auth, options) {
23
23
  * ```
24
24
  */
25
25
  export async function signIn(auth, options) {
26
- const { challenge, code, email, link, permissions } = options;
26
+ const { code, email, permissions } = options;
27
27
  const key = await AccessKey.resolve(options.accessKey);
28
28
  const body = await Api.json(await Api.post(auth, '/v1/auth/code/verify', {
29
29
  json: {
30
- authorize: request(auth, {
31
- accessKey: key.accessKey,
32
- challenge,
33
- permissions,
34
- }),
30
+ authorize: request(auth, { accessKey: key.accessKey, permissions }),
35
31
  code,
36
32
  email,
37
- ...(link ? { link } : {}),
38
33
  },
39
34
  }));
40
35
  if ('step' in body)
@@ -45,12 +45,6 @@ export declare namespace createUrl {
45
45
  * defaults to the user's first. Defaults to a new key, whose material `pending` keeps.
46
46
  */
47
47
  accessKey?: Account.Account | undefined;
48
- /**
49
- * A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
50
- * Tempo Auth binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
51
- * `tempo-auth:sign` scope may send one.
52
- */
53
- challenge?: string | undefined;
54
48
  /** What the key may do. Tempo Auth's pages show it, and the headless ceiling fills what it leaves out. */
55
49
  permissions?: Permissions | undefined;
56
50
  /** Where Tempo Auth redirects back to. Defaults to the instance's `redirectUri`. */
@@ -103,12 +97,6 @@ export declare namespace start {
103
97
  * key, which `storage` keeps until the browser returns.
104
98
  */
105
99
  accessKey?: Account.Account | undefined;
106
- /**
107
- * A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
108
- * Tempo Auth binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
109
- * `tempo-auth:sign` scope may send one.
110
- */
111
- challenge?: string | undefined;
112
100
  /** What the key may do. Tempo Auth's pages show it, and the headless ceiling fills what it leaves out. */
113
101
  permissions?: Permissions | undefined;
114
102
  };
@@ -75,9 +75,6 @@ export async function createUrl(auth, options = {}) {
75
75
  });
76
76
  const url = new URL('/authorize', auth.url);
77
77
  url.search = new URLSearchParams({
78
- ...(options.challenge === undefined
79
- ? {}
80
- : { challenge: options.challenge }),
81
78
  client_id,
82
79
  code_challenge: Base64.fromBytes(Hash.sha256(Bytes.fromString(pending.verifier)), base64url),
83
80
  key_authorization: Base64.fromString(JSON.stringify(key_authorization), base64url),
@@ -12,7 +12,8 @@ import * as Api from '../internal/api.js';
12
12
  * ```
13
13
  */
14
14
  export async function create(auth) {
15
- return toTempoAccount(await Api.json(await Api.post(auth, '/v1/account/tempo', { json: {} })));
15
+ const { address } = await Api.json(await Api.post(auth, '/v1/account/tempo', { json: {} }));
16
+ return { address };
16
17
  }
17
18
  /**
18
19
  * Lists the signed-in user's Tempo Accounts, their default first.
@@ -26,12 +27,5 @@ export async function list(auth) {
26
27
  const { tempo } = await Api.json(await (auth.fetch ?? fetch)(new URL('/v1/account', auth.url), {
27
28
  credentials: 'include',
28
29
  }));
29
- return tempo.map(toTempoAccount);
30
- }
31
- /** Reads the account's address and the type of its owner, which the API lists first. */
32
- function toTempoAccount(account) {
33
- return {
34
- address: account.address,
35
- owner: account.config.owners[0].type,
36
- };
30
+ return tempo.map(({ address }) => ({ address }));
37
31
  }
@@ -7,11 +7,8 @@ import type { Permissions } from '../Permissions.ts';
7
7
  */
8
8
  export declare function request(auth: Auth, options: {
9
9
  accessKey: Account.Account;
10
- /** A message the key's witness binds. */
11
- challenge?: string | undefined;
12
10
  permissions?: Permissions | undefined;
13
11
  }): {
14
- challenge?: string;
15
12
  client_id: string;
16
13
  key_authorization: {
17
14
  account?: `0x${string}`;
@@ -9,9 +9,8 @@ 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, challenge, permissions = {} } = options;
12
+ const { accessKey, permissions = {} } = options;
13
13
  return {
14
- ...(challenge === undefined ? {} : { challenge }),
15
14
  client_id: auth.clientId,
16
15
  key_authorization: {
17
16
  ...(accessKey.accessKeyAddress ? { account: accessKey.address } : {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tempoxyz/auth",
3
- "version": "0.0.0-pr-73.sha-5d2ffa4",
3
+ "version": "0.0.0-pr-84.sha-d9e4bad",
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": {
@@ -1,60 +0,0 @@
1
- /**
2
- * Signs the user in with a passkey from the app's own sign-in form. The browser offers every passkey
3
- * it holds for Tempo's domain, so the app needs no email first.
4
- * @module
5
- */
6
- import { Authentication } from 'ox/webauthn';
7
- import type { Account } from 'viem/tempo';
8
- import type { Auth } from '../Auth.ts';
9
- import type { Authorization } from '../Authorization.ts';
10
- import type { Permissions } from '../Permissions.ts';
11
- /**
12
- * Signs the user in with a passkey, and authorizes the app in the same call. Returns the email step
13
- * for a wallet.tempo passkey whose account has no email: the app signs the user in with
14
- * `Actions.email.signIn`, passing the step's `link`, which links the passkey, and the same
15
- * `accessKey`, `challenge`, and `permissions`, which this call does not authorize. Throws a `RequestError` with reason
16
- * `webauthn_required` when a passkey owns the Tempo Account the key acts for, since a passkey signs a
17
- * key authorization only on Tempo Auth's pages. `Actions.redirect.start` authorizes it there, where
18
- * the user is already signed in.
19
- *
20
- * @example
21
- * ```ts
22
- * const result = await Actions.passkey.signIn(auth)
23
- * if ('step' in result) showEmailForm()
24
- * ```
25
- */
26
- export declare function signIn<const chainId extends number = number>(auth: Auth, options?: signIn.Options<chainId>): Promise<signIn.ReturnType<chainId>>;
27
- export declare namespace signIn {
28
- type Options<chainId extends number = number> = {
29
- /**
30
- * The key to authorize, as a Viem account. Its `access` names the Tempo Account, which
31
- * defaults to the user's first. Defaults to a new key.
32
- */
33
- accessKey?: Account.Account | undefined;
34
- /**
35
- * A message the owner's signature binds, such as a sign-in challenge the app's backend issued.
36
- * Tempo Auth binds its EIP-191 hash as the key authorization's `witness`. Only an app with the
37
- * `tempo-auth:sign` scope may send one.
38
- */
39
- challenge?: string | undefined;
40
- /**
41
- * Runs the WebAuthn ceremony in place of `navigator.credentials.get`, such as a native passkey
42
- * module. Its assertion must report a web origin on the relying party's domain that the app
43
- * registered, so an Android app's facet origin is refused.
44
- */
45
- getFn?: Authentication.sign.Options['getFn'] | undefined;
46
- /** What the key may do. It must fit the headless ceiling, which fills what it leaves out. */
47
- permissions?: Permissions<chainId> | undefined;
48
- };
49
- /** The step a wallet.tempo passkey without an email needs: an emailed code, which links it. */
50
- type EmailStep = {
51
- /** Passed as `link` to `Actions.email.signIn`, which links the passkey to that user. */
52
- link: string;
53
- /** The kind of step. */
54
- type: 'email';
55
- };
56
- /** The authorization, or the email step. */
57
- type ReturnType<chainId extends number = number> = Authorization<chainId> | {
58
- step: EmailStep;
59
- };
60
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * Signs the user in with a passkey from the app's own sign-in form. The browser offers every passkey
3
- * it holds for Tempo's domain, so the app needs no email first.
4
- * @module
5
- */
6
- import { Authentication } from 'ox/webauthn';
7
- import * as AccessKey from '../internal/accessKey.js';
8
- import * as Api from '../internal/api.js';
9
- import { request } from '../internal/request.js';
10
- /**
11
- * Signs the user in with a passkey, and authorizes the app in the same call. Returns the email step
12
- * for a wallet.tempo passkey whose account has no email: the app signs the user in with
13
- * `Actions.email.signIn`, passing the step's `link`, which links the passkey, and the same
14
- * `accessKey`, `challenge`, and `permissions`, which this call does not authorize. Throws a `RequestError` with reason
15
- * `webauthn_required` when a passkey owns the Tempo Account the key acts for, since a passkey signs a
16
- * key authorization only on Tempo Auth's pages. `Actions.redirect.start` authorizes it there, where
17
- * the user is already signed in.
18
- *
19
- * @example
20
- * ```ts
21
- * const result = await Actions.passkey.signIn(auth)
22
- * if ('step' in result) showEmailForm()
23
- * ```
24
- */
25
- export async function signIn(auth, options = {}) {
26
- const { challenge, getFn, permissions } = options;
27
- const key = await AccessKey.resolve(options.accessKey);
28
- const requested = await Api.json(await Api.post(auth, '/v1/auth/passkey/options', { json: {} }));
29
- const deserialized = Authentication.deserializeOptions(requested.options);
30
- const assertion = Authentication.serializeResponse(await Authentication.sign(
31
- // ox reads `getFn` beside request options at runtime, which its types admit only beside a challenge.
32
- getFn ? { ...deserialized, getFn } : deserialized));
33
- const body = await Api.json(await Api.post(auth, '/v1/auth/passkey/verify', {
34
- json: {
35
- assertion,
36
- authorize: request(auth, {
37
- accessKey: key.accessKey,
38
- challenge,
39
- permissions,
40
- }),
41
- },
42
- }));
43
- if ('step' in body)
44
- return { step: body.step };
45
- return Api.authorization(body.authorization, key);
46
- }