@tempoxyz/auth 0.0.0-pr-66.sha-278d6ea → 0.0.0-pr-66.sha-8d0e9ba
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/Decorator.d.ts +7 -3
- package/dist/Decorator.js +52 -32
- package/dist/actions/oauth.d.ts +3 -1
- package/dist/actions/oauth.js +3 -1
- package/package.json +1 -1
package/dist/Decorator.d.ts
CHANGED
|
@@ -38,7 +38,8 @@ export declare class ChainRequiredError extends Error {
|
|
|
38
38
|
/**
|
|
39
39
|
* Returns a Viem client extension that adds Tempo Auth's actions as `client.auth`. Each member calls
|
|
40
40
|
* the action of the same name in `Actions` with one instance, whose `chainId` is the client's chain.
|
|
41
|
-
* Each sign-in sets the client's account to the authorization's,
|
|
41
|
+
* Each sign-in sets the client's account to the authorization's, unless another sign-in or a
|
|
42
|
+
* sign-out completed after it began, and `signOut` empties it at once. Throws
|
|
42
43
|
* {@link ChainRequiredError} for a client without a chain, and {@link AccountRequiredError} for one
|
|
43
44
|
* whose account is not an `Auth.account()`.
|
|
44
45
|
*
|
|
@@ -63,7 +64,7 @@ export declare namespace tempoAuth {
|
|
|
63
64
|
auth: {
|
|
64
65
|
/**
|
|
65
66
|
* `Actions.authorize`, which sets the client's account, or empties it when the user has no
|
|
66
|
-
* session.
|
|
67
|
+
* session.
|
|
67
68
|
*/
|
|
68
69
|
authorize: <const id extends number = chainId>(options?: Actions.authorize.Options<id>) => Promise<Actions.authorize.ReturnType<id>>;
|
|
69
70
|
device: {
|
|
@@ -114,7 +115,10 @@ export declare namespace tempoAuth {
|
|
|
114
115
|
/** The stored key, with or without its `chainId`. */
|
|
115
116
|
key: Key.from.Value<id>;
|
|
116
117
|
}, options?: Key.toAccount.Options) => Authorization<id>;
|
|
117
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* `Actions.signOut`, which empties the client's account before the request, even when it
|
|
120
|
+
* fails, and discards any sign-in still pending.
|
|
121
|
+
*/
|
|
118
122
|
signOut: () => Promise<void>;
|
|
119
123
|
tempoAccount: {
|
|
120
124
|
/** `Actions.tempoAccount.create`. */
|
package/dist/Decorator.js
CHANGED
|
@@ -19,7 +19,8 @@ export class ChainRequiredError extends Error {
|
|
|
19
19
|
/**
|
|
20
20
|
* Returns a Viem client extension that adds Tempo Auth's actions as `client.auth`. Each member calls
|
|
21
21
|
* the action of the same name in `Actions` with one instance, whose `chainId` is the client's chain.
|
|
22
|
-
* Each sign-in sets the client's account to the authorization's,
|
|
22
|
+
* Each sign-in sets the client's account to the authorization's, unless another sign-in or a
|
|
23
|
+
* sign-out completed after it began, and `signOut` empties it at once. Throws
|
|
23
24
|
* {@link ChainRequiredError} for a client without a chain, and {@link AccountRequiredError} for one
|
|
24
25
|
* whose account is not an `Auth.account()`.
|
|
25
26
|
*
|
|
@@ -39,41 +40,53 @@ export function tempoAuth(options) {
|
|
|
39
40
|
if (!state)
|
|
40
41
|
throw new AccountRequiredError();
|
|
41
42
|
const auth = Auth.create({ ...options, chainId: client.chain.id });
|
|
42
|
-
// Counts changes to the client's account
|
|
43
|
-
//
|
|
43
|
+
// Counts changes to the client's account. Each sign-in applies its result only when no other
|
|
44
|
+
// sign-in or sign-out completed after it began, so a stale result never replaces a newer one,
|
|
45
|
+
// and a sign-in still pending at sign-out never signs the client back in.
|
|
44
46
|
let version = 0;
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Begins an operation that changes the client's account, and returns the function that applies
|
|
49
|
+
* its result: the account to sign with, or `undefined` to stop signing.
|
|
50
|
+
*/
|
|
51
|
+
const begin = () => {
|
|
52
|
+
const started = version;
|
|
53
|
+
return (account) => {
|
|
54
|
+
if (version !== started)
|
|
55
|
+
return;
|
|
56
|
+
state.account = account;
|
|
49
57
|
version++;
|
|
50
|
-
}
|
|
51
|
-
return authorization;
|
|
58
|
+
};
|
|
52
59
|
};
|
|
53
60
|
return {
|
|
54
61
|
auth: {
|
|
55
62
|
async authorize(options = {}) {
|
|
56
|
-
const
|
|
63
|
+
const apply = begin();
|
|
57
64
|
const authorization = await Actions.authorize(auth, options);
|
|
58
|
-
if (version !== started)
|
|
59
|
-
return authorization;
|
|
60
65
|
// Without a session, the client stops signing as the user it last authorized.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return set(authorization);
|
|
66
|
+
apply(authorization?.account);
|
|
67
|
+
return authorization;
|
|
64
68
|
},
|
|
65
69
|
device: {
|
|
66
70
|
async authorize(options = {}) {
|
|
71
|
+
const apply = begin();
|
|
67
72
|
const device = await Actions.device.authorize(auth, options);
|
|
68
|
-
return {
|
|
73
|
+
return {
|
|
74
|
+
...device,
|
|
75
|
+
async wait() {
|
|
76
|
+
const authorization = await device.wait();
|
|
77
|
+
apply(authorization.account);
|
|
78
|
+
return authorization;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
69
81
|
},
|
|
70
82
|
},
|
|
71
83
|
email: {
|
|
72
84
|
sendCode: (options) => Actions.email.sendCode(auth, options),
|
|
73
85
|
async signIn(options) {
|
|
86
|
+
const apply = begin();
|
|
74
87
|
const result = await Actions.email.signIn(auth, options);
|
|
75
88
|
if (!('step' in result))
|
|
76
|
-
|
|
89
|
+
apply(result.account);
|
|
77
90
|
return result;
|
|
78
91
|
},
|
|
79
92
|
},
|
|
@@ -88,30 +101,37 @@ export function tempoAuth(options) {
|
|
|
88
101
|
signIn: (options) => Actions.provider.signIn(auth, options),
|
|
89
102
|
},
|
|
90
103
|
redirect: {
|
|
91
|
-
|
|
104
|
+
async complete(options = {}) {
|
|
105
|
+
const apply = begin();
|
|
106
|
+
const authorization = await Actions.redirect.complete(auth, options);
|
|
107
|
+
// `undefined` means the page is not a callback, which says nothing about the session.
|
|
108
|
+
if (authorization)
|
|
109
|
+
apply(authorization.account);
|
|
110
|
+
return authorization;
|
|
111
|
+
},
|
|
92
112
|
createUrl: (options = {}) => Actions.redirect.createUrl(auth, options),
|
|
93
|
-
|
|
113
|
+
async handleCallback(options) {
|
|
114
|
+
const apply = begin();
|
|
115
|
+
const authorization = await Actions.redirect.handleCallback(auth, options);
|
|
116
|
+
apply(authorization.account);
|
|
117
|
+
return authorization;
|
|
118
|
+
},
|
|
94
119
|
start: (options = {}) => Actions.redirect.start(auth, options),
|
|
95
120
|
},
|
|
96
121
|
refresh: (options) => Actions.refresh(auth, options),
|
|
97
122
|
restore: (authorization, options = {}) => {
|
|
98
123
|
// A sign-in stored before `Key.chainId` existed gains it here.
|
|
99
124
|
const key = Key.from(authorization.key);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
key,
|
|
104
|
-
});
|
|
125
|
+
const account = Key.toAccount(key, options);
|
|
126
|
+
begin()(account);
|
|
127
|
+
return { ...authorization, account, key };
|
|
105
128
|
},
|
|
106
129
|
async signOut() {
|
|
107
|
-
// The client stops signing even when the request fails,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
state.account = undefined;
|
|
113
|
-
version++;
|
|
114
|
-
}
|
|
130
|
+
// The client stops signing at once, even when the request fails, and any sign-in still
|
|
131
|
+
// pending is discarded, since the user asked to leave.
|
|
132
|
+
state.account = undefined;
|
|
133
|
+
version++;
|
|
134
|
+
await Actions.signOut(auth);
|
|
115
135
|
},
|
|
116
136
|
tempoAccount: {
|
|
117
137
|
create: () => Actions.tempoAccount.create(auth),
|
package/dist/actions/oauth.d.ts
CHANGED
|
@@ -53,7 +53,9 @@ export declare namespace introspect {
|
|
|
53
53
|
* import { createLocalJWKSet, jwtVerify } from 'jose'
|
|
54
54
|
*
|
|
55
55
|
* const keys = createLocalJWKSet(await Actions.oauth.jwks(auth))
|
|
56
|
-
* const { payload } = await jwtVerify(accessToken, keys, { issuer })
|
|
56
|
+
* const { payload } = await jwtVerify(accessToken, keys, { audience, issuer })
|
|
57
|
+
* // Every app's token carries the same audience, so an API also allows each app by `client_id`.
|
|
58
|
+
* if (!allowedClientIds.includes(String(payload.client_id))) throw forbidden()
|
|
57
59
|
* ```
|
|
58
60
|
*/
|
|
59
61
|
export declare function jwks(auth: Auth): Promise<jwks.ReturnType>;
|
package/dist/actions/oauth.js
CHANGED
|
@@ -43,7 +43,9 @@ export async function introspect(auth, options) {
|
|
|
43
43
|
* import { createLocalJWKSet, jwtVerify } from 'jose'
|
|
44
44
|
*
|
|
45
45
|
* const keys = createLocalJWKSet(await Actions.oauth.jwks(auth))
|
|
46
|
-
* const { payload } = await jwtVerify(accessToken, keys, { issuer })
|
|
46
|
+
* const { payload } = await jwtVerify(accessToken, keys, { audience, issuer })
|
|
47
|
+
* // Every app's token carries the same audience, so an API also allows each app by `client_id`.
|
|
48
|
+
* if (!allowedClientIds.includes(String(payload.client_id))) throw forbidden()
|
|
47
49
|
* ```
|
|
48
50
|
*/
|
|
49
51
|
export async function jwks(auth) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tempoxyz/auth",
|
|
3
|
-
"version": "0.0.0-pr-66.sha-
|
|
3
|
+
"version": "0.0.0-pr-66.sha-8d0e9ba",
|
|
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": {
|