@soulcode/bexio-oauth 0.2.0 → 0.3.1

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 CHANGED
@@ -11,12 +11,14 @@ It is **not** an auth framework: your app keeps its own login. For "Sign in with
11
11
 
12
12
  ```bash
13
13
  npm install @soulcode/bexio-oauth pg
14
- npx @soulcode/bexio-oauth sql > migrations/0001_bexio_grants.sql # then apply it
14
+ npx @soulcode/bexio-oauth sql > migrations/0001_bexio_oauth.sql # then apply it
15
15
  npx @soulcode/bexio-oauth keygen # encryption key
16
16
  ```
17
17
 
18
18
  Requires Node ≥ 24 and PostgreSQL.
19
19
 
20
+ Use one Bexio OAuth client per app: Bexio keeps one refresh token chain per user, company and client, so apps sharing a client id invalidate each other's grants. Owners of your app that connect the same Bexio user and company share one connection, refreshed once for all of them ([guide §2](https://github.com/SoulcodeAgency/bexio-oauth/blob/main/docs/integration.md#why-owners-of-the-same-identity-share-a-connection)).
21
+
20
22
  ## Quickstart
21
23
 
22
24
  ```ts
@@ -37,14 +39,16 @@ export const bexio = createBexioOAuth({
37
39
  ```
38
40
 
39
41
  ```ts
40
- // GET /api/bexio/connect
42
+ // app/api/bexio/connect/route.ts
41
43
  export const GET = async (req: Request) =>
42
44
  bexio.start({
43
45
  ownerId: await currentWorkspaceId(req),
44
46
  returnTo: "/settings",
45
47
  });
48
+ ```
46
49
 
47
- // GET /api/bexio/callback (your redirectUri)
50
+ ```ts
51
+ // app/api/bexio/callback/route.ts (your redirectUri)
48
52
  export const GET = async (req: Request) =>
49
53
  bexio.callback(req, { ownerId: await currentWorkspaceId(req) });
50
54
  ```
@@ -60,7 +64,7 @@ await fetch("https://api.bexio.com/2.0/contact", {
60
64
  });
61
65
  ```
62
66
 
63
- Also: `listGrants`, `disconnect`, `refreshIdle` (keep idle grants alive), `saveGrant` (tokens from your auth framework). Every error is a `BexioOAuthError` with a stable `code`.
67
+ Also: `listGrants`, `disconnect`, `refreshIdle` (keep idle connections alive), `saveGrant` (tokens from your auth framework). Every error is a `BexioOAuthError` with a stable `code`.
64
68
 
65
69
  ## License
66
70
 
package/dist/claims.d.ts CHANGED
@@ -26,6 +26,6 @@ export interface BexioIdentity {
26
26
  * missing.
27
27
  */
28
28
  export declare function mapClaims(claims: ClaimBag): BexioIdentity;
29
- /** The value a grant's ciphertext is bound to (see `TokenCipher`). */
30
- export declare function grantBinding(ownerId: string, companyId: string, userId: string): string;
29
+ /** The value a connection's ciphertext is bound to (see `TokenCipher`). */
30
+ export declare function connectionBinding(companyId: string, userId: string): string;
31
31
  //# sourceMappingURL=claims.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAEA,uDAAuD;AACvD,eAAO,MAAM,YAAY,wCAAwC,CAAC;AAClE,uCAAuC;AACvC,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAC1D;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAMvC,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/C,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0EAA0E;IAC1E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAaD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,aAAa,CAwBzD;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,MAAM,CAER"}
1
+ {"version":3,"file":"claims.d.ts","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAEA,uDAAuD;AACvD,eAAO,MAAM,YAAY,wCAAwC,CAAC;AAClE,uCAAuC;AACvC,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAC1D;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAMvC,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/C,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0EAA0E;IAC1E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAaD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,aAAa,CAwBzD;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3E"}
package/dist/claims.js CHANGED
@@ -51,8 +51,8 @@ export function mapClaims(claims) {
51
51
  userEmail: text(claims.email),
52
52
  };
53
53
  }
54
- /** The value a grant's ciphertext is bound to (see `TokenCipher`). */
55
- export function grantBinding(ownerId, companyId, userId) {
56
- return `${ownerId}\u0000${companyId}\u0000${userId}`;
54
+ /** The value a connection's ciphertext is bound to (see `TokenCipher`). */
55
+ export function connectionBinding(companyId, userId) {
56
+ return `${companyId}\u0000${userId}`;
57
57
  }
58
58
  //# sourceMappingURL=claims.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,uDAAuD;AACvD,MAAM,CAAC,MAAM,YAAY,GAAG,qCAAqC,CAAC;AAClE,uCAAuC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAC1D;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC1D,QAAQ;IACR,SAAS;IACT,OAAO;IACP,iBAAiB;IACjB,gBAAgB;CACjB,CAAC,CAAC;AAiBH,SAAS,IAAI,CAAC,KAAc;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9E,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAAgB;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM;QACT,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CACvB,kBAAkB,EAClB,oEAAoE,CACrE,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO;QACL,MAAM;QACN,SAAS;QACT,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;QACtC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC;QAC9C,QAAQ,EACN,KAAK,IAAI,MAAM;YACb,CAAC,CAAC,GAAG,KAAK,IAAI,MAAM,EAAE;YACtB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC;QAC5C,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,SAAiB,EACjB,MAAc;IAEd,OAAO,GAAG,OAAO,SAAS,SAAS,SAAS,MAAM,EAAE,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,uDAAuD;AACvD,MAAM,CAAC,MAAM,YAAY,GAAG,qCAAqC,CAAC;AAClE,uCAAuC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAC1D;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC1D,QAAQ;IACR,SAAS;IACT,OAAO;IACP,iBAAiB;IACjB,gBAAgB;CACjB,CAAC,CAAC;AAiBH,SAAS,IAAI,CAAC,KAAc;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9E,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,MAAgB;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM;QACT,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CACvB,kBAAkB,EAClB,oEAAoE,CACrE,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO;QACL,MAAM;QACN,SAAS;QACT,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;QACtC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC;QAC9C,QAAQ,EACN,KAAK,IAAI,MAAM;YACb,CAAC,CAAC,GAAG,KAAK,IAAI,MAAM,EAAE;YACtB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC;QAC5C,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAAC,SAAiB,EAAE,MAAc;IACjE,OAAO,GAAG,SAAS,SAAS,MAAM,EAAE,CAAC;AACvC,CAAC"}
package/dist/crypto.d.ts CHANGED
@@ -12,8 +12,8 @@ export interface Keyring {
12
12
  export declare function generateKey(): string;
13
13
  /**
14
14
  * Encrypts tokens at rest as compact JWE (`dir` + `A256GCM`) and seals the
15
- * short-lived flow cookie. The `bxg` protected header binds a token to the
16
- * grant it belongs to, so ciphertext copied to another row fails to decrypt.
15
+ * short-lived flow cookie. The `bxc` protected header binds a token to the
16
+ * connection it belongs to, so ciphertext copied to another row fails to decrypt.
17
17
  */
18
18
  export declare class TokenCipher {
19
19
  #private;
package/dist/crypto.js CHANGED
@@ -16,8 +16,8 @@ function hash(value) {
16
16
  }
17
17
  /**
18
18
  * Encrypts tokens at rest as compact JWE (`dir` + `A256GCM`) and seals the
19
- * short-lived flow cookie. The `bxg` protected header binds a token to the
20
- * grant it belongs to, so ciphertext copied to another row fails to decrypt.
19
+ * short-lived flow cookie. The `bxc` protected header binds a token to the
20
+ * connection it belongs to, so ciphertext copied to another row fails to decrypt.
21
21
  */
22
22
  export class TokenCipher {
23
23
  #current;
@@ -48,20 +48,20 @@ export class TokenCipher {
48
48
  alg: "dir",
49
49
  enc: "A256GCM",
50
50
  kid: this.#current,
51
- bxg: hash(binding),
51
+ bxc: hash(binding),
52
52
  })
53
53
  .encrypt(this.#key(this.#current).key);
54
54
  }
55
55
  async decrypt(jwe, binding) {
56
56
  try {
57
57
  const { plaintext, protectedHeader } = await compactDecrypt(jwe, (header) => this.#key(header.kid).key, JWE_ALGORITHMS);
58
- if (protectedHeader.bxg !== hash(binding)) {
58
+ if (protectedHeader.bxc !== hash(binding)) {
59
59
  throw new Error("binding mismatch");
60
60
  }
61
61
  return new TextDecoder().decode(plaintext);
62
62
  }
63
63
  catch {
64
- throw new BexioOAuthError("decryption_failed", "stored token could not be decrypted (unknown key id, or it belongs to another grant)");
64
+ throw new BexioOAuthError("decryption_failed", "stored token could not be decrypted (unknown key id, or it belongs to another connection)");
65
65
  }
66
66
  }
67
67
  async seal(payload, ttlSeconds, now) {
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
package/dist/errors.d.ts CHANGED
@@ -20,7 +20,7 @@ export type BexioOAuthErrorCode =
20
20
  | "ambiguous_grant"
21
21
  /** The refresh token is dead; the user has to reconnect. */
22
22
  | "reauth_required"
23
- /** A stored token can't be decrypted (unknown key id, or it belongs to another grant). */
23
+ /** A stored token can't be decrypted (unknown key id, or it belongs to another connection). */
24
24
  | "decryption_failed"
25
25
  /** The library was configured incorrectly. */
26
26
  | "invalid_config";
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,mBAAmB;AAC7B,+DAA+D;AAC7D,gBAAgB;AAClB,wEAAwE;GACtE,gBAAgB;AAClB,mCAAmC;GACjC,eAAe;AACjB,2EAA2E;GACzE,kBAAkB;AACpB,6DAA6D;GAC3D,WAAW;AACb,4DAA4D;GAC1D,eAAe;AACjB,mEAAmE;GACjE,iBAAiB;AACnB,4DAA4D;GAC1D,iBAAiB;AACnB,0FAA0F;GACxF,mBAAmB;AACrB,8CAA8C;GAC5C,gBAAgB,CAAC;AAErB,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;gBAGjC,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;CAM1E;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,IAAI,CAAC,EAAE,mBAAmB,GACzB,KAAK,IAAI,eAAe,CAK1B"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,mBAAmB;AAC7B,+DAA+D;AAC7D,gBAAgB;AAClB,wEAAwE;GACtE,gBAAgB;AAClB,mCAAmC;GACjC,eAAe;AACjB,2EAA2E;GACzE,kBAAkB;AACpB,6DAA6D;GAC3D,WAAW;AACb,4DAA4D;GAC1D,eAAe;AACjB,mEAAmE;GACjE,iBAAiB;AACnB,4DAA4D;GAC1D,iBAAiB;AACnB,+FAA+F;GAC7F,mBAAmB;AACrB,8CAA8C;GAC5C,gBAAgB,CAAC;AAErB,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;gBAGjC,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;CAM1E;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,IAAI,CAAC,EAAE,mBAAmB,GACzB,KAAK,IAAI,eAAe,CAK1B"}
package/dist/grants.d.ts CHANGED
@@ -1,25 +1,34 @@
1
1
  import { type ClaimBag } from "./claims.js";
2
2
  import type { ClientContext } from "./config.js";
3
3
  import type { TokenCipher } from "./crypto.js";
4
- import type { GrantRecord, GrantStore } from "./store/types.js";
4
+ import type { ConnectionRecord, GrantRecord, GrantStore } from "./store/types.js";
5
5
  import type { AccessToken, Grant, GrantSelector } from "./types.js";
6
- /** The app-facing view of a stored grant: no token material. */
7
- export declare function toGrant(r: GrantRecord): Grant;
8
- /** The binding a grant's ciphertexts are encrypted under. */
9
- export declare function bindingOf(record: GrantRecord): string;
10
- export declare function decryptFor(cipher: TokenCipher, record: GrantRecord, value: string): Promise<string>;
11
- /** Decrypts the grant's access token for the caller. */
12
- export declare function issue(cipher: TokenCipher, record: GrantRecord): Promise<AccessToken>;
6
+ /**
7
+ * The app-facing view of a stored grant, with `c` (default: the grant's own)
8
+ * as its connection: no token material.
9
+ */
10
+ export declare function toGrant(grant: GrantRecord, c?: ConnectionRecord): Grant;
11
+ /** The binding a connection's ciphertexts are encrypted under. */
12
+ export declare function bindingOf(connection: ConnectionRecord): string;
13
+ export declare function decryptFor(cipher: TokenCipher, connection: ConnectionRecord, value: string): Promise<string>;
14
+ /** Decrypts the connection's access token for the owner of `grant`. */
15
+ export declare function issue(cipher: TokenCipher, grant: GrantRecord, connection: ConnectionRecord): Promise<AccessToken>;
13
16
  /** Exactly one grant of the owner, or `not_connected` / `ambiguous_grant`. */
14
17
  export declare function resolveGrant(store: GrantStore, selector: GrantSelector): Promise<GrantRecord>;
15
18
  /** The token's claims if it is a JWT, else none (Bexio access tokens usually are). */
16
19
  export declare function decodeIfJwt(token: string): ClaimBag;
17
20
  /**
18
- * Adds userinfo claims, only when the tokens lack the company claims. Token
19
- * claims win over userinfo; a userinfo failure keeps the token claims.
21
+ * Adds userinfo claims when the tokens lack the profile claims. Bexio's access
22
+ * token carries `company_id` but no company name, email or person name; the
23
+ * ID token has them, so the extra call only happens without one (`saveGrant`
24
+ * with an access token alone). Token claims win over userinfo; a userinfo
25
+ * failure keeps the token claims.
20
26
  */
21
27
  export declare function withUserInfo(ctx: ClientContext, claims: ClaimBag, accessToken: string): Promise<ClaimBag>;
22
- /** Encrypts the tokens, reads the role and upserts the grant for the identity in `claims`. */
28
+ /**
29
+ * Encrypts the tokens, reads the role, and upserts the connection for the
30
+ * identity in `claims` and the owner's grant on it.
31
+ */
23
32
  export declare function saveTokens(ctx: ClientContext, input: {
24
33
  ownerId: string;
25
34
  claims: ClaimBag;
@@ -1 +1 @@
1
- {"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,CAAC,EAAE,WAAW,GAAG,KAAK,CAkB7C;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAErD;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED,wDAAwD;AACxD,wBAAsB,KAAK,CACzB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,WAAW,CAAC,CAMtB;AAED,8EAA8E;AAC9E,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,WAAW,CAAC,CAatB;AAED,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAMnD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,CAAC,CAYnB;AAED,8FAA8F;AAC9F,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE;IACL,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,GACA,OAAO,CAAC,WAAW,CAAC,CAuBtB;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACzB,OAAO,CAAC,KAAK,EAAE,CAAC,CAIlB;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CAef"}
1
+ {"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE;;;GAGG;AACH,wBAAgB,OAAO,CACrB,KAAK,EAAE,WAAW,EAClB,CAAC,GAAE,gBAAmC,GACrC,KAAK,CAmBP;AAED,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,UAAU,EAAE,gBAAgB,GAAG,MAAM,CAE9D;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,gBAAgB,EAC5B,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED,uEAAuE;AACvE,wBAAsB,KAAK,CACzB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,gBAAgB,GAC3B,OAAO,CAAC,WAAW,CAAC,CAMtB;AAED,8EAA8E;AAC9E,wBAAsB,YAAY,CAChC,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,WAAW,CAAC,CAatB;AAED,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAMnD;AAKD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,aAAa,EAClB,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,CAAC,CAanB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE;IACL,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,IAAI,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,GACA,OAAO,CAAC,WAAW,CAAC,CAsBtB;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACzB,OAAO,CAAC,KAAK,EAAE,CAAC,CAMlB;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
package/dist/grants.js CHANGED
@@ -1,41 +1,45 @@
1
1
  import * as oidc from "openid-client";
2
2
  import { decodeJwt } from "jose";
3
- import { grantBinding, mapClaims } from "./claims.js";
3
+ import { connectionBinding, mapClaims } from "./claims.js";
4
4
  import { BexioOAuthError } from "./errors.js";
5
5
  import { fetchRole } from "./permissions.js";
6
- /** The app-facing view of a stored grant: no token material. */
7
- export function toGrant(r) {
6
+ /**
7
+ * The app-facing view of a stored grant, with `c` (default: the grant's own)
8
+ * as its connection: no token material.
9
+ */
10
+ export function toGrant(grant, c = grant.connection) {
8
11
  return {
9
- id: r.id,
10
- ownerId: r.ownerId,
11
- companyId: r.companyId,
12
- companyName: r.companyName,
13
- userId: r.userId,
14
- userName: r.userName,
15
- userEmail: r.userEmail,
16
- companyUserId: r.companyUserId,
17
- role: r.role,
18
- status: r.status,
19
- scope: r.scope,
20
- accessExpiresAt: r.accessExpiresAt,
21
- lastRefreshedAt: r.lastRefreshedAt,
22
- createdAt: r.createdAt,
23
- updatedAt: r.updatedAt,
12
+ id: grant.id,
13
+ ownerId: grant.ownerId,
14
+ connectionId: c.id,
15
+ companyId: c.companyId,
16
+ companyName: c.companyName,
17
+ userId: c.userId,
18
+ userName: c.userName,
19
+ userEmail: c.userEmail,
20
+ companyUserId: c.companyUserId,
21
+ role: c.role,
22
+ status: c.status,
23
+ scope: c.scope,
24
+ accessExpiresAt: c.accessExpiresAt,
25
+ lastRefreshedAt: c.lastRefreshedAt,
26
+ createdAt: grant.createdAt,
27
+ updatedAt: c.updatedAt,
24
28
  };
25
29
  }
26
- /** The binding a grant's ciphertexts are encrypted under. */
27
- export function bindingOf(record) {
28
- return grantBinding(record.ownerId, record.companyId, record.userId);
30
+ /** The binding a connection's ciphertexts are encrypted under. */
31
+ export function bindingOf(connection) {
32
+ return connectionBinding(connection.companyId, connection.userId);
29
33
  }
30
- export function decryptFor(cipher, record, value) {
31
- return cipher.decrypt(value, bindingOf(record));
34
+ export function decryptFor(cipher, connection, value) {
35
+ return cipher.decrypt(value, bindingOf(connection));
32
36
  }
33
- /** Decrypts the grant's access token for the caller. */
34
- export async function issue(cipher, record) {
37
+ /** Decrypts the connection's access token for the owner of `grant`. */
38
+ export async function issue(cipher, grant, connection) {
35
39
  return {
36
- accessToken: await decryptFor(cipher, record, record.accessToken),
37
- expiresAt: record.accessExpiresAt,
38
- grant: toGrant(record),
40
+ accessToken: await decryptFor(cipher, connection, connection.accessToken),
41
+ expiresAt: connection.accessExpiresAt,
42
+ grant: toGrant(grant, connection),
39
43
  };
40
44
  }
41
45
  /** Exactly one grant of the owner, or `not_connected` / `ambiguous_grant`. */
@@ -59,12 +63,17 @@ export function decodeIfJwt(token) {
59
63
  return {};
60
64
  }
61
65
  }
66
+ /** Claims a connection needs beyond the ids (see `mapClaims`). */
67
+ const PROFILE_CLAIMS = ["company_id", "company_name", "email"];
62
68
  /**
63
- * Adds userinfo claims, only when the tokens lack the company claims. Token
64
- * claims win over userinfo; a userinfo failure keeps the token claims.
69
+ * Adds userinfo claims when the tokens lack the profile claims. Bexio's access
70
+ * token carries `company_id` but no company name, email or person name; the
71
+ * ID token has them, so the extra call only happens without one (`saveGrant`
72
+ * with an access token alone). Token claims win over userinfo; a userinfo
73
+ * failure keeps the token claims.
65
74
  */
66
75
  export async function withUserInfo(ctx, claims, accessToken) {
67
- if (claims.company_id !== undefined)
76
+ if (PROFILE_CLAIMS.every((claim) => claims[claim] !== undefined))
68
77
  return claims;
69
78
  try {
70
79
  const info = await oidc.fetchUserInfo(await ctx.oidc.config(), accessToken, typeof claims.sub === "string" ? claims.sub : oidc.skipSubjectCheck);
@@ -74,12 +83,16 @@ export async function withUserInfo(ctx, claims, accessToken) {
74
83
  return claims;
75
84
  }
76
85
  }
77
- /** Encrypts the tokens, reads the role and upserts the grant for the identity in `claims`. */
86
+ /**
87
+ * Encrypts the tokens, reads the role, and upserts the connection for the
88
+ * identity in `claims` and the owner's grant on it.
89
+ */
78
90
  export async function saveTokens(ctx, input) {
79
91
  const identity = mapClaims(input.claims);
80
- const binding = grantBinding(input.ownerId, identity.companyId, identity.userId);
92
+ const binding = connectionBinding(identity.companyId, identity.userId);
81
93
  const role = (await fetchRole(ctx.fetchImpl, ctx.apiBaseUrl, input.accessToken)) ??
82
94
  "member";
95
+ const issuedAt = decodeIfJwt(input.accessToken).iat;
83
96
  return ctx.store.upsertGrant({
84
97
  ownerId: input.ownerId,
85
98
  ...identity,
@@ -91,25 +104,40 @@ export async function saveTokens(ctx, input) {
91
104
  accessExpiresAt: input.accessExpiresAt,
92
105
  refreshExpiresAt: input.refreshExpiresAt,
93
106
  scope: input.scope,
107
+ authorizedAt: typeof issuedAt === "number" ? new Date(issuedAt * 1000) : ctx.clock(),
94
108
  now: ctx.clock(),
95
109
  });
96
110
  }
97
111
  export async function listGrants(store, query) {
98
112
  if (!query?.ownerId)
99
113
  throw new BexioOAuthError("invalid_config", "ownerId is required");
100
- return (await store.findGrants({ ownerId: query.ownerId })).map(toGrant);
114
+ return (await store.findGrants({ ownerId: query.ownerId })).map((g) => toGrant(g));
101
115
  }
102
116
  export async function disconnect(ctx, selector) {
103
- const record = await resolveGrant(ctx.store, selector);
117
+ const grant = await resolveGrant(ctx.store, selector);
118
+ // Delete first, revoke after: revoking ends the one refresh token chain
119
+ // all owners of this identity share, so it may only happen once the store
120
+ // has confirmed that no grant (not even a concurrent one) uses it.
121
+ await ctx.store.deleteGrant(grant.id);
122
+ const deleted = await ctx.store.deleteUnusedConnection(grant.connection.id);
123
+ if (!deleted)
124
+ return;
125
+ const { connection, userHasOtherConnections } = deleted;
126
+ // Revoking ends all of the user's chains at Bexio, whichever token it
127
+ // names: a stale (reauth_required) token would still end the chain the user
128
+ // authorized since, and any token the user's other company's connection.
129
+ if (!connection.refreshToken ||
130
+ connection.status !== "active" ||
131
+ userHasOtherConnections)
132
+ return;
104
133
  try {
105
134
  const c = await ctx.oidc.config();
106
- if (record.refreshToken && c.serverMetadata().revocation_endpoint) {
107
- await oidc.tokenRevocation(c, await decryptFor(ctx.cipher, record, record.refreshToken), { token_type_hint: "refresh_token" });
135
+ if (c.serverMetadata().revocation_endpoint) {
136
+ await oidc.tokenRevocation(c, await decryptFor(ctx.cipher, connection, connection.refreshToken), { token_type_hint: "refresh_token" });
108
137
  }
109
138
  }
110
139
  catch {
111
- // Revocation is best effort; the grant is deleted either way.
140
+ // Revocation is best effort; the connection is deleted either way.
112
141
  }
113
- await ctx.store.deleteGrant(record.id);
114
142
  }
115
143
  //# sourceMappingURL=grants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grants.js","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grants.js","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import type { ClientContext } from "./config.js";
2
2
  import { type Duration } from "./duration.js";
3
3
  import type { RefreshIdleResult } from "./types.js";
4
4
  export declare const DEFAULT_IDLE_LIMIT = 100;
5
- /** `BexioOAuth.refreshIdle`: refreshes idle grants one after another. */
5
+ /** `BexioOAuth.refreshIdle`: refreshes idle connections one after another. */
6
6
  export declare function refreshIdle(ctx: ClientContext, options: {
7
7
  idleFor: Duration;
8
8
  limit?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"idle-sweep.d.ts","sourceRoot":"","sources":["../src/idle-sweep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,yEAAyE;AACzE,wBAAsB,WAAW,CAC/B,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,QAAQ,CAAA;CAAE,GACpE,OAAO,CAAC,iBAAiB,CAAC,CA2D5B"}
1
+ {"version":3,"file":"idle-sweep.d.ts","sourceRoot":"","sources":["../src/idle-sweep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,8EAA8E;AAC9E,wBAAsB,WAAW,CAC/B,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,QAAQ,CAAA;CAAE,GACpE,OAAO,CAAC,iBAAiB,CAAC,CA2D5B"}
@@ -2,7 +2,7 @@ import { toMs } from "./duration.js";
2
2
  import { isBexioOAuthError } from "./errors.js";
3
3
  import { lockWindow, refreshLocked } from "./refresh.js";
4
4
  export const DEFAULT_IDLE_LIMIT = 100;
5
- /** `BexioOAuth.refreshIdle`: refreshes idle grants one after another. */
5
+ /** `BexioOAuth.refreshIdle`: refreshes idle connections one after another. */
6
6
  export async function refreshIdle(ctx, options) {
7
7
  const { store, clock } = ctx;
8
8
  const idleMs = toMs(options?.idleFor, "idleFor");
@@ -18,7 +18,7 @@ export async function refreshIdle(ctx, options) {
18
18
  remaining: 0,
19
19
  };
20
20
  const refreshedBefore = new Date(startedAt - idleMs);
21
- const idle = await store.listIdleGrants({
21
+ const idle = await store.listIdleConnections({
22
22
  refreshedBefore,
23
23
  limit: options.limit ?? DEFAULT_IDLE_LIMIT,
24
24
  });
@@ -32,9 +32,9 @@ export async function refreshIdle(ctx, options) {
32
32
  result.failed = idle.length;
33
33
  return result;
34
34
  }
35
- for (const [index, grant] of idle.entries()) {
35
+ for (const [index, connection] of idle.entries()) {
36
36
  // Stop before taking the next lock, so a function timeout can't cut a
37
- // refresh in half. The oldest grants come first, so the next run
37
+ // refresh in half. The oldest connections come first, so the next run
38
38
  // continues where this one stopped.
39
39
  if (clock().getTime() - startedAt >= budgetMs) {
40
40
  result.remaining = idle.length - index;
@@ -42,7 +42,7 @@ export async function refreshIdle(ctx, options) {
42
42
  }
43
43
  const window = lockWindow(ctx, clock());
44
44
  const locked = await store.acquireRefreshLock({
45
- id: grant.id,
45
+ id: connection.id,
46
46
  ...window,
47
47
  refreshedBefore,
48
48
  });
@@ -1 +1 @@
1
- {"version":3,"file":"idle-sweep.js","sourceRoot":"","sources":["../src/idle-sweep.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAiB,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAkB,EAClB,OAAqE;IAErE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,QAAQ,GACZ,OAAO,CAAC,UAAU,KAAK,SAAS;QAC9B,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC;IACpC,MAAM,MAAM,GAAsB;QAChC,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;QACV,cAAc,EAAE,CAAC;QACjB,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;KACb,CAAC;IACF,MAAM,eAAe,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC;QACtC,eAAe;QACf,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,kBAAkB;KAC3C,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;QAChE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,sEAAsE;QACtE,iEAAiE;QACjE,oCAAoC;QACpC,IAAI,KAAK,EAAE,CAAC,OAAO,EAAE,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC;YAC9C,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACvC,MAAM;QACR,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,kBAAkB,CAAC;YAC5C,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,GAAG,MAAM;YACT,eAAe;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,IAAI,MAAM,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC;gBACpD,MAAM,CAAC,SAAS,EAAE,CAAC;;gBAChB,MAAM,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,CAAC,EAAE,CAAC;gBAChD,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"idle-sweep.js","sourceRoot":"","sources":["../src/idle-sweep.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAiB,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGzD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAkB,EAClB,OAAqE;IAErE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,QAAQ,GACZ,OAAO,CAAC,UAAU,KAAK,SAAS;QAC9B,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC;IACpC,MAAM,MAAM,GAAsB;QAChC,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;QACV,cAAc,EAAE,CAAC;QACjB,MAAM,EAAE,CAAC;QACT,SAAS,EAAE,CAAC;KACb,CAAC;IACF,MAAM,eAAe,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,mBAAmB,CAAC;QAC3C,eAAe;QACf,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,kBAAkB;KAC3C,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;QAChE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QACjD,sEAAsE;QACtE,sEAAsE;QACtE,oCAAoC;QACpC,IAAI,KAAK,EAAE,CAAC,OAAO,EAAE,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC;YAC9C,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACvC,MAAM;QACR,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,kBAAkB,CAAC;YAC5C,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,GAAG,MAAM;YACT,eAAe;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,IAAI,MAAM,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC;gBACpD,MAAM,CAAC,SAAS,EAAE,CAAC;;gBAChB,MAAM,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,CAAC,EAAE,CAAC;gBAChD,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -8,5 +8,5 @@ export { roleFromPermissions, type Role } from "./permissions.js";
8
8
  export { migrations, type Migration } from "./sql.js";
9
9
  export { memoryStore } from "./store/memory.js";
10
10
  export { postgresStore, type SqlClient } from "./store/postgres.js";
11
- export type { GrantRecord, GrantRefresh, GrantStatus, GrantStore, GrantUpsert, LockRequest, } from "./store/types.js";
11
+ export type { ConnectionRecord, ConnectionRefresh, GrantRecord, GrantStatus, GrantStore, GrantUpsert, LockRequest, } from "./store/types.js";
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,KAAK,EACL,aAAa,EACb,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,KAAK,EACL,aAAa,EACb,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.generated.d.ts","sourceRoot":"","sources":["../src/migrations.generated.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EAsC1C,CAAC"}
1
+ {"version":3,"file":"migrations.generated.d.ts","sourceRoot":"","sources":["../src/migrations.generated.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EAsD1C,CAAC"}
@@ -1,14 +1,15 @@
1
1
  export const MIGRATIONS = [
2
2
  {
3
3
  number: 1,
4
- name: "0001_bexio_grants.sql",
5
- sql: `-- @soulcode/bexio-oauth 0001: the grants table.
6
- -- One row per (owner, Bexio company, Bexio user). Token columns hold JWE
7
- -- ciphertext; only your server-side database role should be able to read them.
4
+ name: "0001_bexio_oauth.sql",
5
+ sql: `-- @soulcode/bexio-oauth 0001: connections and grants.
6
+ -- Token columns hold JWE ciphertext; only your server-side database role
7
+ -- should be able to read these tables.
8
8
 
9
- CREATE TABLE IF NOT EXISTS bexio_grants (
9
+ -- One row per Bexio identity (company, user): the tokens of its one refresh
10
+ -- token chain, shared by every owner that connected this identity.
11
+ CREATE TABLE IF NOT EXISTS bexio_connections (
10
12
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
11
- owner_id text NOT NULL,
12
13
  bexio_company_id text NOT NULL,
13
14
  bexio_user_id text NOT NULL,
14
15
  bexio_company_user_id integer,
@@ -24,16 +25,31 @@ CREATE TABLE IF NOT EXISTS bexio_grants (
24
25
  scope text,
25
26
  refresh_locked_until timestamptz,
26
27
  refresh_lock_token text,
28
+ authorized_at timestamptz NOT NULL,
27
29
  last_refreshed_at timestamptz NOT NULL DEFAULT now(),
28
30
  created_at timestamptz NOT NULL DEFAULT now(),
29
31
  updated_at timestamptz NOT NULL DEFAULT now(),
30
- CONSTRAINT bexio_grants_owner_company_user_key UNIQUE (owner_id, bexio_company_id, bexio_user_id)
32
+ CONSTRAINT bexio_connections_company_user_key UNIQUE (bexio_company_id, bexio_user_id)
31
33
  );
32
34
 
33
- -- refreshIdle(): active grants by last refresh.
34
- CREATE INDEX IF NOT EXISTS bexio_grants_idle_idx
35
- ON bexio_grants (last_refreshed_at)
35
+ -- refreshIdle(): active connections by last refresh.
36
+ CREATE INDEX IF NOT EXISTS bexio_connections_idle_idx
37
+ ON bexio_connections (last_refreshed_at)
36
38
  WHERE status = 'active';
39
+
40
+ -- One row per (owner, connection): an owner's access to a connection. A
41
+ -- connection is deleted only once no grant references it (RESTRICT).
42
+ CREATE TABLE IF NOT EXISTS bexio_grants (
43
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
44
+ owner_id text NOT NULL,
45
+ connection_id uuid NOT NULL REFERENCES bexio_connections (id) ON DELETE RESTRICT,
46
+ created_at timestamptz NOT NULL DEFAULT now(),
47
+ CONSTRAINT bexio_grants_owner_connection_key UNIQUE (owner_id, connection_id)
48
+ );
49
+
50
+ -- Disconnect checks whether a connection has grants left.
51
+ CREATE INDEX IF NOT EXISTS bexio_grants_connection_idx
52
+ ON bexio_grants (connection_id);
37
53
  `,
38
54
  },
39
55
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.generated.js","sourceRoot":"","sources":["../src/migrations.generated.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,UAAU,GAAyB;IAC9C;QACE,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,uBAAuB;QAC7B,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCR;KACE;CACF,CAAC"}
1
+ {"version":3,"file":"migrations.generated.js","sourceRoot":"","sources":["../src/migrations.generated.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,UAAU,GAAyB;IAC9C;QACE,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,sBAAsB;QAC5B,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDR;KACE;CACF,CAAC"}
package/dist/refresh.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as oidc from "openid-client";
2
2
  import type { ClientContext } from "./config.js";
3
- import type { GrantRecord } from "./store/types.js";
3
+ import type { ConnectionRecord } from "./store/types.js";
4
4
  import type { AccessToken, GrantSelector } from "./types.js";
5
5
  /** Refresh a little before the access token really expires. */
6
6
  export declare const EXPIRY_SKEW_MS = 30000;
@@ -11,7 +11,7 @@ export declare function tokenExpiry(tokens: TokenResponse, now: Date): {
11
11
  refreshExpiresAt: Date | null;
12
12
  };
13
13
  /** True while the access token is valid for longer than the skew. */
14
- export declare function isFresh(record: GrantRecord, now: Date): boolean;
14
+ export declare function isFresh(connection: ConnectionRecord, now: Date): boolean;
15
15
  /** A new lock holder's token and lease, starting at `now`. */
16
16
  export declare function lockWindow(ctx: ClientContext, now: Date): {
17
17
  now: Date;
@@ -19,12 +19,12 @@ export declare function lockWindow(ctx: ClientContext, now: Date): {
19
19
  lockToken: `${string}-${string}-${string}-${string}-${string}`;
20
20
  };
21
21
  /**
22
- * Refreshes a grant whose lock the caller holds (`lockToken`). Every write
23
- * is fenced by the token: if the lock was lost (expired and taken over, or
24
- * the grant was reconnected meanwhile), the write changes nothing and this
25
- * returns `null`: the caller re-reads the grant.
22
+ * Refreshes a connection whose lock the caller holds (`lockToken`). Every
23
+ * write is fenced by the token: if the lock was lost (expired and taken over,
24
+ * or the connection was reconnected meanwhile), the write changes nothing and
25
+ * this returns `null`: the caller re-reads the connection.
26
26
  */
27
- export declare function refreshLocked(ctx: ClientContext, record: GrantRecord, lockToken: string): Promise<GrantRecord | null>;
27
+ export declare function refreshLocked(ctx: ClientContext, connection: ConnectionRecord, lockToken: string): Promise<ConnectionRecord | null>;
28
28
  /** `BexioOAuth.getAccessToken`. */
29
29
  export declare function getAccessToken(ctx: ClientContext, selector: GrantSelector): Promise<AccessToken>;
30
30
  //# sourceMappingURL=refresh.d.ts.map