@cortexkit/common-auth 0.4.4 → 0.4.5
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/store/torn.js +44 -2
- package/package.json +1 -1
package/dist/store/torn.js
CHANGED
|
@@ -30,6 +30,15 @@ import { buildRawRows, CREDENTIAL_STAMP_KEY, credentialDigest, dispatchDigest, e
|
|
|
30
30
|
* store leaves the row as it is on disk (`legacy`, unbound) rather than act
|
|
31
31
|
* on it; a store without the option completes it as before.
|
|
32
32
|
*
|
|
33
|
+
* A strict store also completes a replace only when its stamp describes what
|
|
34
|
+
* the completed row would send: the stamp's dispatch digest must be that of
|
|
35
|
+
* the credential beside it, with an API key moved to the endpoint the binding
|
|
36
|
+
* names. The lineage digest alone covers the refresh token or API key, so
|
|
37
|
+
* without this check another writer that changed only the access token, the
|
|
38
|
+
* expiry or the endpoint would still have the strict store rewrite the row's
|
|
39
|
+
* epoch, identity and quota before refusing the row as unbound. A store
|
|
40
|
+
* without the option never compared dispatch digests here and still does not.
|
|
41
|
+
*
|
|
33
42
|
* A write that gives a row its first identity (`recordIdentity`, or a
|
|
34
43
|
* `rotate` or refresh that learns one) follows the same order: the stamp
|
|
35
44
|
* naming the identity first, then the config recording it. A crash between
|
|
@@ -38,6 +47,26 @@ import { buildRawRows, CREDENTIAL_STAMP_KEY, credentialDigest, dispatchDigest, e
|
|
|
38
47
|
* does not record; that is completed forward the same way, by recording the
|
|
39
48
|
* identity.
|
|
40
49
|
*/
|
|
50
|
+
/**
|
|
51
|
+
* The credential a torn replace leaves once its config write lands: the
|
|
52
|
+
* credential loaded beside the stamp, with the endpoint the stamp's binding
|
|
53
|
+
* names. Only an API key's endpoint lives in the config (an OAuth credential
|
|
54
|
+
* is entirely in the state file, which the replace has already written). A
|
|
55
|
+
* replace that moves a key to a new endpoint leaves the old `baseURL` and
|
|
56
|
+
* `authHeader` in the config until its config write, so the binding's
|
|
57
|
+
* `baseURL` and `authHeader` are the ones the replacement will be sent with.
|
|
58
|
+
*/
|
|
59
|
+
function projectedReplacement(credential, binding) {
|
|
60
|
+
if (credential.type !== 'api')
|
|
61
|
+
return credential;
|
|
62
|
+
return {
|
|
63
|
+
...credential,
|
|
64
|
+
...(binding.baseURL !== undefined ? { baseURL: binding.baseURL } : {}),
|
|
65
|
+
...(binding.authHeader !== undefined
|
|
66
|
+
? { authHeader: binding.authHeader }
|
|
67
|
+
: {}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
41
70
|
/** Whether a well-formed stamp was written by a replace. */
|
|
42
71
|
function isReplaceStamp(stamp) {
|
|
43
72
|
if (!stamp.binding)
|
|
@@ -66,8 +95,21 @@ export function tornStamps(config, state, codec, options = {}) {
|
|
|
66
95
|
if (stamp.credentialEpoch > epoch) {
|
|
67
96
|
if (!isReplaceStamp(stamp))
|
|
68
97
|
continue;
|
|
69
|
-
if (options.requireCredentialStamps
|
|
70
|
-
|
|
98
|
+
if (options.requireCredentialStamps) {
|
|
99
|
+
if (stamp.dispatch === undefined)
|
|
100
|
+
continue;
|
|
101
|
+
// `digest` covers only the refresh token or API key, so another
|
|
102
|
+
// writer may still have changed the access token, the expiry or the
|
|
103
|
+
// endpoint the stamp names. `dispatch` covers all of what a request
|
|
104
|
+
// sends; completing the replace when it disagrees would move the
|
|
105
|
+
// row's epoch, identity and quota on a stamp that does not describe
|
|
106
|
+
// the credential. So the replacement as it would be sent (the loaded
|
|
107
|
+
// credential with the binding's endpoint) must have the stamp's
|
|
108
|
+
// dispatch digest; otherwise the row stays as on disk (unbound).
|
|
109
|
+
if (stamp.dispatch !==
|
|
110
|
+
dispatchDigest(projectedReplacement(row.credential, stamp.binding)))
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
71
113
|
torn.set(row.id, {
|
|
72
114
|
kind: 'replace',
|
|
73
115
|
stamp: { ...stamp, binding: stamp.binding },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/common-auth",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Shared code for the CortexKit auth plugins: account pool, quota and routing, commands and auth menu, OpenCode 2 hooks, Claustrum custody, and plumbing (loopback RPC, file locks, logger, sidebar state, TUI preferences and build).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|