@owlmeans/server-auth-token 0.1.18-rc.8 → 0.1.18

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.
Files changed (79) hide show
  1. package/README.md +177 -1
  2. package/agent-meta/manifest.json +3 -3
  3. package/agent-meta/skills/server-auth-token/SKILL.md +33 -10
  4. package/build/guard.d.ts +1 -3
  5. package/build/guard.d.ts.map +1 -1
  6. package/build/guard.js +37 -14
  7. package/build/guard.js.map +1 -1
  8. package/build/handlers/create.d.ts +5 -0
  9. package/build/handlers/create.d.ts.map +1 -0
  10. package/build/handlers/create.js +18 -0
  11. package/build/handlers/create.js.map +1 -0
  12. package/build/handlers/index.d.ts +11 -11
  13. package/build/handlers/index.d.ts.map +1 -1
  14. package/build/handlers/index.js +8 -93
  15. package/build/handlers/index.js.map +1 -1
  16. package/build/handlers/issue.d.ts +6 -0
  17. package/build/handlers/issue.d.ts.map +1 -0
  18. package/build/handlers/issue.js +42 -0
  19. package/build/handlers/issue.js.map +1 -0
  20. package/build/handlers/list.d.ts +3 -0
  21. package/build/handlers/list.d.ts.map +1 -0
  22. package/build/handlers/list.js +18 -0
  23. package/build/handlers/list.js.map +1 -0
  24. package/build/handlers/refuse.d.ts +19 -0
  25. package/build/handlers/refuse.d.ts.map +1 -0
  26. package/build/handlers/refuse.js +20 -0
  27. package/build/handlers/refuse.js.map +1 -0
  28. package/build/handlers/revoke.d.ts +17 -0
  29. package/build/handlers/revoke.d.ts.map +1 -0
  30. package/build/handlers/revoke.js +35 -0
  31. package/build/handlers/revoke.js.map +1 -0
  32. package/build/handlers/types.d.ts +37 -0
  33. package/build/handlers/types.d.ts.map +1 -0
  34. package/build/handlers/types.js +2 -0
  35. package/build/handlers/types.js.map +1 -0
  36. package/build/handlers/utils/types.d.ts +10 -0
  37. package/build/handlers/utils/types.d.ts.map +1 -0
  38. package/build/handlers/utils/types.js +2 -0
  39. package/build/handlers/utils/types.js.map +1 -0
  40. package/build/handlers/utils.d.ts +4 -0
  41. package/build/handlers/utils.d.ts.map +1 -0
  42. package/build/handlers/utils.js +11 -0
  43. package/build/handlers/utils.js.map +1 -0
  44. package/build/hash/types.d.ts +16 -0
  45. package/build/hash/types.d.ts.map +1 -0
  46. package/build/hash/types.js +2 -0
  47. package/build/hash/types.js.map +1 -0
  48. package/build/hash.d.ts +4 -15
  49. package/build/hash.d.ts.map +1 -1
  50. package/build/hash.js +13 -16
  51. package/build/hash.js.map +1 -1
  52. package/build/index.d.ts +3 -0
  53. package/build/index.d.ts.map +1 -1
  54. package/build/index.js +1 -0
  55. package/build/index.js.map +1 -1
  56. package/build/prefix.d.ts +4 -0
  57. package/build/prefix.d.ts.map +1 -0
  58. package/build/prefix.js +4 -0
  59. package/build/prefix.js.map +1 -0
  60. package/build/types.d.ts +20 -0
  61. package/build/types.d.ts.map +1 -1
  62. package/package.json +17 -16
  63. package/src/guard.ts +39 -16
  64. package/src/handlers/create.ts +21 -0
  65. package/src/handlers/index.ts +17 -115
  66. package/src/handlers/issue.ts +50 -0
  67. package/src/handlers/list.ts +21 -0
  68. package/src/handlers/refuse.ts +20 -0
  69. package/src/handlers/revoke.ts +42 -0
  70. package/src/handlers/types.ts +40 -0
  71. package/src/handlers/utils/types.ts +10 -0
  72. package/src/handlers/utils.ts +18 -0
  73. package/src/hash/types.ts +16 -0
  74. package/src/hash.ts +17 -21
  75. package/src/index.ts +3 -0
  76. package/src/prefix.ts +6 -0
  77. package/src/types.ts +21 -0
  78. package/tests/guard.spec.ts +54 -10
  79. package/tests/handlers.spec.ts +56 -8
@@ -0,0 +1,6 @@
1
+ import type { AuthTokenContext } from '../types.js';
2
+ import type { AccessTokenIssuer } from './types.js';
3
+ export declare const makeAccessTokenIssuer: (ctx: AuthTokenContext) => AccessTokenIssuer;
4
+ /** The token issuer of a context — one per context. */
5
+ export declare const accessTokenIssuerOf: (target: AuthTokenContext) => AccessTokenIssuer;
6
+ //# sourceMappingURL=issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../src/handlers/issue.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAoD,MAAM,YAAY,CAAA;AAGrG,eAAO,MAAM,qBAAqB,QAAS,gBAAgB,KAAG,iBAqC7D,CAAA;AAED,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,iDAA4C,CAAA"}
@@ -0,0 +1,42 @@
1
+ import { AuthForbidden, ALL_SCOPES } from '@owlmeans/auth';
2
+ import { AUTH_TOKEN_MAX_TTL } from '@owlmeans/auth-token';
3
+ import { memoHelper } from '@owlmeans/context';
4
+ import { tokenHashHelper } from '../hash.js';
5
+ import { prefixOf } from '../prefix.js';
6
+ import { tokenRecordUtils } from './utils.js';
7
+ export const makeAccessTokenIssuer = (ctx) => {
8
+ const issueAccessToken = async (subject, payload) => {
9
+ const own = subject.scopes;
10
+ const scopes = payload.scopes ?? own;
11
+ // A token is a delegation, so it can only ever narrow. Asking for a scope the caller does not
12
+ // hold is refused rather than silently dropped: a token that quietly grants less than it was
13
+ // asked for fails later, somewhere else, with an error about the wrong thing.
14
+ if (!own.includes(ALL_SCOPES) && scopes.some(scope => !own.includes(scope))) {
15
+ throw new AuthForbidden('scope');
16
+ }
17
+ // The SAME resolver the guard uses, so a minted token is one this deployment's guard claims.
18
+ const minted = tokenHashHelper.mintAccessToken(prefixOf(ctx));
19
+ const now = new Date();
20
+ const record = await tokenRecordUtils.tokens(ctx).create({
21
+ hash: minted.hash,
22
+ display: minted.display,
23
+ name: payload.name,
24
+ userId: subject.userId,
25
+ profileId: subject.profileId,
26
+ entityId: subject.entityId,
27
+ scopes,
28
+ role: subject.role,
29
+ createdAt: now,
30
+ ...(payload.audience != null ? { audience: payload.audience } : {}),
31
+ ...(payload.expiresIn != null
32
+ ? { expiresAt: new Date(now.getTime() + Math.min(payload.expiresIn * 1000, AUTH_TOKEN_MAX_TTL)) }
33
+ : {}),
34
+ });
35
+ // The only moment the plaintext exists outside the caller's own machine.
36
+ return { token: minted.token, record: tokenRecordUtils.view(record) };
37
+ };
38
+ return { issueAccessToken };
39
+ };
40
+ /** The token issuer of a context — one per context. */
41
+ export const accessTokenIssuerOf = memoHelper.oncePer(makeAccessTokenIssuer);
42
+ //# sourceMappingURL=issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue.js","sourceRoot":"","sources":["../../src/handlers/issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,kBAAkB,EAAkD,MAAM,sBAAsB,CAAA;AACzG,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAqB,EAAqB,EAAE;IAChF,MAAM,gBAAgB,GAAG,KAAK,EAC5B,OAAgC,EAAE,OAAgC,EACtC,EAAE;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAA;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,CAAA;QACpC,8FAA8F;QAC9F,6FAA6F;QAC7F,8EAA8E;QAC9E,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5E,MAAM,IAAI,aAAa,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,6FAA6F;QAC7F,MAAM,MAAM,GAAG,eAAe,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;QAC7D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;QACtB,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;YACvD,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,MAAM;YACN,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS,EAAE,GAAG;YACd,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI;gBAC3B,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,EAAE,kBAAkB,CAAC,CAAC,EAAE;gBACjG,CAAC,CAAC,EAAE,CAAC;SACa,CAAC,CAAA;QAEvB,yEAAyE;QACzE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAA8B,CAAA;IACnG,CAAC,CAAA;IAED,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAC7B,CAAC,CAAA;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { AccessTokenList, AuthTokenEntrypoints } from '@owlmeans/auth-token';
2
+ export declare const listAccessTokens: (protocol: AuthTokenEntrypoints['list']) => import("@owlmeans/server-entrypoint").BoundEntrypointHandler<import("@owlmeans/entrypoint").EntrypointProtocol<import("@owlmeans/entrypoint").OpenRequest, AccessTokenList>>;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/handlers/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAMjF,eAAO,MAAM,gBAAgB,aAAc,oBAAoB,CAAC,MAAM,CAAC,iLAarE,CAAA"}
@@ -0,0 +1,18 @@
1
+ import { AuthForbidden } from '@owlmeans/auth';
2
+ import { makeEntityScope } from '@owlmeans/auth-common';
3
+ import { handlers } from '@owlmeans/server-api';
4
+ import { tokenRecordUtils } from './utils.js';
5
+ export const listAccessTokens = (protocol) => handlers().request(protocol, async (req, context) => {
6
+ const ctx = context;
7
+ const entityId = makeEntityScope(req).requireEntityKey();
8
+ const profileId = req.auth?.profileId;
9
+ if (profileId == null)
10
+ throw new AuthForbidden('profile');
11
+ const result = await tokenRecordUtils.tokens(ctx).list({ entityId, profileId }, { size: 0 });
12
+ return {
13
+ items: result.items
14
+ .map(tokenRecordUtils.view)
15
+ .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()),
16
+ };
17
+ });
18
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/handlers/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAsC,EAAE,EAAE,CAAC,QAAQ,EAAoB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;IAChJ,MAAM,GAAG,GAAG,OAA2B,CAAA;IACvC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,gBAAgB,EAAE,CAAA;IACxD,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAA;IACrC,IAAI,SAAS,IAAI,IAAI;QAAE,MAAM,IAAI,aAAa,CAAC,SAAS,CAAC,CAAA;IAEzD,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IAE5F,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK;aAChB,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC;aAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;KAC3D,CAAA;AAC7B,CAAC,CAAC,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * A token may never mint another token.
3
+ *
4
+ * Minting is the one operation that turns a stolen credential into a permanent one: a token that
5
+ * can create tokens survives the revocation of the token that leaked. Creating and revoking
6
+ * therefore require a credential a person produced in a browser — which is also why the deployment
7
+ * names these routes in the guard's deny list, so the refusal is a 401 at the boundary rather than
8
+ * a check every future handler has to remember.
9
+ *
10
+ * Exported because an OAuth authorization server's consent-approval handler
11
+ * (`@owlmeans/server-oauth`) mints tokens too and needs the exact same guard, over a session it
12
+ * verified itself rather than a route this package bound.
13
+ */
14
+ export declare const refuseTokenAuth: (req: {
15
+ auth?: {
16
+ type?: string;
17
+ };
18
+ }, what: string) => void;
19
+ //# sourceMappingURL=refuse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refuse.d.ts","sourceRoot":"","sources":["../../src/handlers/refuse.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,QAAS;IAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,QAAQ,MAAM,KAAG,IAIjF,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { AuthForbidden, AuthroizationType } from '@owlmeans/auth';
2
+ /**
3
+ * A token may never mint another token.
4
+ *
5
+ * Minting is the one operation that turns a stolen credential into a permanent one: a token that
6
+ * can create tokens survives the revocation of the token that leaked. Creating and revoking
7
+ * therefore require a credential a person produced in a browser — which is also why the deployment
8
+ * names these routes in the guard's deny list, so the refusal is a 401 at the boundary rather than
9
+ * a check every future handler has to remember.
10
+ *
11
+ * Exported because an OAuth authorization server's consent-approval handler
12
+ * (`@owlmeans/server-oauth`) mints tokens too and needs the exact same guard, over a session it
13
+ * verified itself rather than a route this package bound.
14
+ */
15
+ export const refuseTokenAuth = (req, what) => {
16
+ if (req.auth?.type === AuthroizationType.AuthToken) {
17
+ throw new AuthForbidden(what);
18
+ }
19
+ };
20
+ //# sourceMappingURL=refuse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refuse.js","sourceRoot":"","sources":["../../src/handlers/refuse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAEjE;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAiC,EAAE,IAAY,EAAQ,EAAE;IACvF,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,iBAAiB,CAAC,SAAS,EAAE,CAAC;QACnD,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,CAAA;IAC/B,CAAC;AACH,CAAC,CAAA"}
@@ -0,0 +1,17 @@
1
+ import type { AuthTokenEntrypoints } from '@owlmeans/auth-token';
2
+ import type { RevokeAccessTokenOptions } from './types.js';
3
+ /**
4
+ * Revoke one of the caller's own tokens.
5
+ *
6
+ * By default only a credential a person produced in a browser may revoke. `allowAccessTokens`
7
+ * admits an access token too — a deployment's coding-agent surface that lets the person clean up
8
+ * their own tokens — and changes nothing else: still the caller's OWN profile in their OWN
9
+ * organization, and a foreign token still answers exactly as an unknown id does. Revoking never
10
+ * mints, so it cannot turn a stolen token into a lasting one; minting stays refused regardless.
11
+ */
12
+ export declare const revokeAccessToken: (protocol: AuthTokenEntrypoints['revoke'], opts?: RevokeAccessTokenOptions) => import("@owlmeans/server-entrypoint").BoundEntrypointHandler<import("@owlmeans/entrypoint").EntrypointProtocol<{
13
+ params: import("@owlmeans/auth-token").AccessTokenParams;
14
+ }, {
15
+ id: string;
16
+ }>>;
17
+ //# sourceMappingURL=revoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revoke.d.ts","sourceRoot":"","sources":["../../src/handlers/revoke.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAKhE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAG1D;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,aAClB,oBAAoB,CAAC,QAAQ,CAAC,SAAQ,wBAAwB;;;;GAsBxE,CAAA"}
@@ -0,0 +1,35 @@
1
+ import { AuthForbidden } from '@owlmeans/auth';
2
+ import { makeEntityScope } from '@owlmeans/auth-common';
3
+ import { handlers } from '@owlmeans/server-api';
4
+ import { refuseTokenAuth } from './refuse.js';
5
+ import { tokenRecordUtils } from './utils.js';
6
+ /**
7
+ * Revoke one of the caller's own tokens.
8
+ *
9
+ * By default only a credential a person produced in a browser may revoke. `allowAccessTokens`
10
+ * admits an access token too — a deployment's coding-agent surface that lets the person clean up
11
+ * their own tokens — and changes nothing else: still the caller's OWN profile in their OWN
12
+ * organization, and a foreign token still answers exactly as an unknown id does. Revoking never
13
+ * mints, so it cannot turn a stolen token into a lasting one; minting stays refused regardless.
14
+ */
15
+ export const revokeAccessToken = (protocol, opts = {}) => handlers().params(protocol, async (payload, context, req) => {
16
+ const ctx = context;
17
+ if (opts.allowAccessTokens !== true)
18
+ refuseTokenAuth(req, 'token-revoke');
19
+ const entityId = makeEntityScope(req).requireEntityKey();
20
+ const profileId = req.auth?.profileId;
21
+ if (profileId == null)
22
+ throw new AuthForbidden('profile');
23
+ const record = await tokenRecordUtils.tokens(ctx).load(payload.id);
24
+ // A token of another profile answers exactly as an unknown id does — an owner learns nothing
25
+ // about tokens that are not theirs, not even that one exists.
26
+ if (record == null || record.entityId !== entityId || record.profileId !== profileId) {
27
+ throw new AuthForbidden('token');
28
+ }
29
+ // Idempotent: revoking twice is what a retry looks like.
30
+ if (record.revokedAt == null) {
31
+ await tokenRecordUtils.tokens(ctx).save({ ...record, revokedAt: new Date(), updatedAt: new Date() });
32
+ }
33
+ return { id: payload.id };
34
+ });
35
+ //# sourceMappingURL=revoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revoke.js","sourceRoot":"","sources":["../../src/handlers/revoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,QAAwC,EAAE,IAAI,GAA6B,EAAE,EAC7E,EAAE,CAAC,QAAQ,EAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;IACjF,MAAM,GAAG,GAAG,OAA2B,CAAA;IACvC,IAAI,IAAI,CAAC,iBAAiB,KAAK,IAAI;QAAE,eAAe,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IAEzE,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,gBAAgB,EAAE,CAAA;IACxD,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,EAAE,SAAS,CAAA;IACrC,IAAI,SAAS,IAAI,IAAI;QAAE,MAAM,IAAI,aAAa,CAAC,SAAS,CAAC,CAAA;IAEzD,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAClE,6FAA6F;IAC7F,8DAA8D;IAC9D,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACrF,MAAM,IAAI,aAAa,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IAED,yDAAyD;IACzD,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAA;IACtG,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAA;AAC3B,CAAC,CAAC,CAAA"}
@@ -0,0 +1,37 @@
1
+ import { AuthRole } from '@owlmeans/auth';
2
+ import type { CreateAccessToken, IssuedAccessToken } from '@owlmeans/auth-token';
3
+ /** Whoever is minting the token — read once, by whichever caller resolved the session. */
4
+ export interface IssueAccessTokenSubject {
5
+ entityId: string;
6
+ userId: string;
7
+ profileId: string;
8
+ role: AuthRole;
9
+ /** The subject's OWN scopes — minting can only narrow, never widen, this set. */
10
+ scopes: string[];
11
+ }
12
+ export interface IssueAccessTokenRequest extends CreateAccessToken {
13
+ /**
14
+ * The resource(s) this token is FOR (RFC 8707), when it is minted through an OAuth grant.
15
+ * Absent for a token minted by hand — the ordinary, unrestricted kind.
16
+ */
17
+ audience?: string[];
18
+ }
19
+ /** Token issuance over one context's store — the one path every minting caller goes through. */
20
+ export interface AccessTokenIssuer {
21
+ /**
22
+ * Mint one token for `subject`, exactly what `createAccessToken` does over an HTTP body — pulled
23
+ * out so a second caller (an OAuth token endpoint) can mint the SAME shape of record over a
24
+ * session it authenticated its own way, without a duplicate copy of the narrowing rule or the
25
+ * TTL clamp silently drifting from this one.
26
+ */
27
+ issueAccessToken: (subject: IssueAccessTokenSubject, payload: IssueAccessTokenRequest) => Promise<IssuedAccessToken>;
28
+ }
29
+ /** How a deployment binds `revokeAccessToken`. */
30
+ export interface RevokeAccessTokenOptions {
31
+ /**
32
+ * Let an access token revoke one of its own person's tokens (itself included). Defaults to
33
+ * `false`: only an interactive session revokes. Ownership is checked the same either way.
34
+ */
35
+ allowAccessTokens?: boolean;
36
+ }
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAEhF,0FAA0F;AAC1F,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,CAAA;IACd,iFAAiF;IACjF,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,gGAAgG;AAChG,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,gBAAgB,EAAE,CAAC,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAA;CACrH;AAED,kDAAkD;AAClD,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import type { AccessTokenRecord, AccessTokenView } from '@owlmeans/auth-token';
2
+ import type { AccessTokenResource, AuthTokenContext } from '../../types.js';
3
+ /** What every token handler shares: the store and the view a caller may see. */
4
+ export interface TokenRecordUtils {
5
+ /** A record without its hash — the hash never leaves the server. */
6
+ view: (record: AccessTokenRecord) => AccessTokenView;
7
+ /** The token store of a context. */
8
+ tokens: (ctx: AuthTokenContext) => AccessTokenResource;
9
+ }
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/handlers/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAE3E,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,IAAI,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,eAAe,CAAA;IACpD,oCAAoC;IACpC,MAAM,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,mBAAmB,CAAA;CACvD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/handlers/utils/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { TokenRecordUtils } from './utils/types.js';
2
+ export declare const createTokenRecordUtils: () => TokenRecordUtils;
3
+ export declare const tokenRecordUtils: TokenRecordUtils;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/handlers/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD,eAAO,MAAM,sBAAsB,QAAO,gBAWzC,CAAA;AAED,eAAO,MAAM,gBAAgB,kBAA2B,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { AUTH_TOKEN_RESOURCE } from '@owlmeans/auth-token';
2
+ export const createTokenRecordUtils = () => {
3
+ const view = (record) => {
4
+ const { hash, ...rest } = record;
5
+ return rest;
6
+ };
7
+ const tokens = (ctx) => ctx.resource(AUTH_TOKEN_RESOURCE);
8
+ return { view, tokens };
9
+ };
10
+ export const tokenRecordUtils = createTokenRecordUtils();
11
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/handlers/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAgD,MAAM,sBAAsB,CAAA;AAIxG,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAqB,EAAE;IAC3D,MAAM,IAAI,GAAG,CAAC,MAAyB,EAAmB,EAAE;QAC1D,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAA;QAEhC,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,CAAC,GAAqB,EAAuB,EAAE,CAC5D,GAAG,CAAC,QAAQ,CAAsB,mBAAmB,CAAC,CAAA;IAExD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACzB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,sBAAsB,EAAE,CAAA"}
@@ -0,0 +1,16 @@
1
+ import type { MintedToken } from '../types.js';
2
+ /** Access tokens minted and stored: the plaintext once, the hash forever. */
3
+ export interface TokenHashHelper {
4
+ /**
5
+ * The stored form of a token.
6
+ *
7
+ * SHA-256 rather than a password hash on purpose: the input is 192 bits of machine-generated
8
+ * randomness, so there is no dictionary to slow down, and the hash is computed on every single
9
+ * API request — a deliberately slow function here would be a deliberate rate limit on the
10
+ * deployment's whole authenticated surface.
11
+ */
12
+ hashAccessToken: (token: string) => string;
13
+ /** Mint one token: the plaintext (returned once), its hash (stored) and its display form. */
14
+ mintAccessToken: (prefix: string) => MintedToken;
15
+ }
16
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hash/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAC1C,6FAA6F;IAC7F,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,WAAW,CAAA;CACjD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/hash/types.ts"],"names":[],"mappings":""}
package/build/hash.d.ts CHANGED
@@ -1,17 +1,6 @@
1
- /**
2
- * The stored form of a token.
3
- *
4
- * SHA-256 rather than a password hash on purpose: the input is 192 bits of machine-generated
5
- * randomness, so there is no dictionary to slow down, and the hash is computed on every single
6
- * API request — a deliberately slow function here would be a deliberate rate limit on the
7
- * deployment's whole authenticated surface.
8
- */
1
+ import type { TokenHashHelper } from './hash/types.js';
2
+ export declare const createTokenHashHelper: () => TokenHashHelper;
3
+ export declare const tokenHashHelper: TokenHashHelper;
4
+ /** @deprecated compat:factory-refactor — use `tokenHashHelper.hashAccessToken(…)` */
9
5
  export declare const hashAccessToken: (token: string) => string;
10
- export interface MintedToken {
11
- token: string;
12
- hash: string;
13
- display: string;
14
- }
15
- /** Mint one token: the plaintext (returned once), its hash (stored) and its display form. */
16
- export declare const mintAccessToken: (prefix: string) => MintedToken;
17
6
  //# sourceMappingURL=hash.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,UAAW,MAAM,KAAG,MAA6D,CAAA;AAE7G,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,6FAA6F;AAC7F,eAAO,MAAM,eAAe,WAAY,MAAM,KAAG,WAIhD,CAAA"}
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,qBAAqB,QAAO,eAUxC,CAAA;AAED,eAAO,MAAM,eAAe,iBAA0B,CAAA;AAEtD,qFAAqF;AACrF,eAAO,MAAM,eAAe,UAAW,MAAM,KAAG,MAAgD,CAAA"}
package/build/hash.js CHANGED
@@ -1,19 +1,16 @@
1
- import { AUTH_TOKEN_SECRET_BYTES, displayOf } from '@owlmeans/auth-token';
1
+ import { AUTH_TOKEN_SECRET_BYTES, tokenFormatHelper } from '@owlmeans/auth-token';
2
2
  import { base58 } from '@scure/base';
3
- import { sha256 } from '@noble/hashes/sha256';
4
- import { bytesToHex, randomBytes } from '@noble/hashes/utils';
5
- /**
6
- * The stored form of a token.
7
- *
8
- * SHA-256 rather than a password hash on purpose: the input is 192 bits of machine-generated
9
- * randomness, so there is no dictionary to slow down, and the hash is computed on every single
10
- * API request — a deliberately slow function here would be a deliberate rate limit on the
11
- * deployment's whole authenticated surface.
12
- */
13
- export const hashAccessToken = (token) => bytesToHex(sha256(new TextEncoder().encode(token)));
14
- /** Mint one token: the plaintext (returned once), its hash (stored) and its display form. */
15
- export const mintAccessToken = (prefix) => {
16
- const token = `${prefix}${base58.encode(randomBytes(AUTH_TOKEN_SECRET_BYTES))}`;
17
- return { token, hash: hashAccessToken(token), display: displayOf(token, prefix) };
3
+ import { sha256 } from '@noble/hashes/sha2.js';
4
+ import { bytesToHex, randomBytes } from '@noble/hashes/utils.js';
5
+ export const createTokenHashHelper = () => {
6
+ const hashAccessToken = (token) => bytesToHex(sha256(new TextEncoder().encode(token)));
7
+ const mintAccessToken = (prefix) => {
8
+ const token = `${prefix}${base58.encode(randomBytes(AUTH_TOKEN_SECRET_BYTES))}`;
9
+ return { token, hash: hashAccessToken(token), display: tokenFormatHelper.displayOf(token, prefix) };
10
+ };
11
+ return { hashAccessToken, mintAccessToken };
18
12
  };
13
+ export const tokenHashHelper = createTokenHashHelper();
14
+ /** @deprecated compat:factory-refactor — use `tokenHashHelper.hashAccessToken(…)` */
15
+ export const hashAccessToken = (token) => tokenHashHelper.hashAccessToken(token);
19
16
  //# sourceMappingURL=hash.js.map
package/build/hash.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE7D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAQ7G,6FAA6F;AAC7F,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAc,EAAe,EAAE;IAC7D,MAAM,KAAK,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC,EAAE,CAAA;IAE/E,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAA;AACnF,CAAC,CAAA"}
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAIhE,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAoB,EAAE;IACzD,MAAM,eAAe,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAEtG,MAAM,eAAe,GAAG,CAAC,MAAc,EAAe,EAAE;QACtD,MAAM,KAAK,GAAG,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC,EAAE,CAAA;QAE/E,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAA;IACrG,CAAC,CAAA;IAED,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,CAAA;AAC7C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,EAAE,CAAA;AAEtD,qFAAqF;AACrF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,eAAe,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA"}
package/build/index.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  export * from './consts.js';
2
2
  export * from './resource.js';
3
+ export * from './prefix.js';
3
4
  export * from './guard.js';
4
5
  export * from './hash.js';
5
6
  export * from './coguard.js';
6
7
  export * from './append.js';
7
8
  export * from './handlers/index.js';
9
+ export type * from './handlers/types.js';
8
10
  export type * from './types.js';
11
+ export type * from './hash/types.js';
9
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,mBAAmB,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,mBAAmB,qBAAqB,CAAA;AACxC,mBAAmB,YAAY,CAAA;AAC/B,mBAAmB,iBAAiB,CAAA"}
package/build/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './consts.js';
2
2
  export * from './resource.js';
3
+ export * from './prefix.js';
3
4
  export * from './guard.js';
4
5
  export * from './hash.js';
5
6
  export * from './coguard.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { AuthTokenContext, AuthTokenGuardOptions } from './types.js';
2
+ /** Where the deployment's prefix comes from: the guard's own options, then config, then default. */
3
+ export declare const prefixOf: (context: AuthTokenContext, opts?: AuthTokenGuardOptions) => string;
4
+ //# sourceMappingURL=prefix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix.d.ts","sourceRoot":"","sources":["../src/prefix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAE1F,oGAAoG;AACpG,eAAO,MAAM,QAAQ,YAAa,gBAAgB,SAAS,qBAAqB,KAAG,MACc,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { AUTH_TOKEN_DEFAULT_PREFIX } from '@owlmeans/auth-token';
2
+ /** Where the deployment's prefix comes from: the guard's own options, then config, then default. */
3
+ export const prefixOf = (context, opts) => opts?.prefix ?? context.cfg.authToken?.prefix ?? AUTH_TOKEN_DEFAULT_PREFIX;
4
+ //# sourceMappingURL=prefix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix.js","sourceRoot":"","sources":["../src/prefix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAA;AAGhE,oGAAoG;AACpG,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAyB,EAAE,IAA4B,EAAU,EAAE,CAC1F,IAAI,EAAE,MAAM,IAAK,OAAO,CAAC,GAAuB,CAAC,SAAS,EAAE,MAAM,IAAI,yBAAyB,CAAA"}
package/build/types.d.ts CHANGED
@@ -26,6 +26,21 @@ export interface AuthTokenGuardOptions {
26
26
  resourceAlias?: string;
27
27
  /** Resource alias holding the identity profiles a token is bound to. */
28
28
  profileAlias?: string;
29
+ /**
30
+ * The resource(s) this guard speaks for, opting it into audience admission.
31
+ *
32
+ * Left unset (the default), the guard admits every token whatever its `audience` — full
33
+ * backward compatibility for a deployment that never mints an audience-restricted token. Set
34
+ * it to the canonical resource URI(s) this route surface serves, and a token issued FOR a
35
+ * different resource (an OAuth-issued, MCP-only token, say) is refused here rather than
36
+ * quietly working everywhere the profile's scopes would otherwise reach.
37
+ *
38
+ * A function is resolved with the live context on every request rather than once at
39
+ * registration time — `appendAuthTokenGuard` runs from `makeContext`, before a hostname a
40
+ * Kubernetes secret mount populates is necessarily readable yet, and this guard's `handle`
41
+ * already runs per-request regardless.
42
+ */
43
+ resources?: string[] | ((context: AuthTokenContext) => string[]);
29
44
  }
30
45
  export interface AuthTokenConfig extends ServerConfig {
31
46
  authToken?: {
@@ -33,4 +48,9 @@ export interface AuthTokenConfig extends ServerConfig {
33
48
  };
34
49
  }
35
50
  export type AuthTokenContext<C extends AuthTokenConfig = AuthTokenConfig> = ServerContext<C>;
51
+ export interface MintedToken {
52
+ token: string;
53
+ hash: string;
54
+ display: string;
55
+ }
36
56
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE3E,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAAA;AAElE,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,IAAI,aAAa,CAAC,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAE3E,MAAM,MAAM,mBAAmB,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAAA;AAElE,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,EAAE,CAAC,CAAA;CACjE;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,IAAI,aAAa,CAAC,CAAC,CAAC,CAAA;AAE5F,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@owlmeans/server-auth-token",
3
- "version": "0.1.18-rc.8",
3
+ "version": "0.1.18",
4
4
  "license": "MIT",
5
- "description": "The server half of OwlMeans access tokens — the store, the guard that verifies a presented token, the management handlers and the coguard that admits one on an existing route.",
5
+ "description": "The server half of OwlMeans access tokens \u2014 the store, the guard that verifies a presented token, the management handlers and the coguard that admits one on an existing route.",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "build": "tsc -b",
@@ -23,22 +23,23 @@
23
23
  }
24
24
  },
25
25
  "dependencies": {
26
- "@noble/hashes": "^1.5.0",
27
- "@owlmeans/auth": "^0.1.18-rc.17",
28
- "@owlmeans/auth-common": "^0.1.18-rc.21",
29
- "@owlmeans/auth-token": "^0.1.18-rc.8",
30
- "@owlmeans/context": "^0.1.18-rc.16",
31
- "@owlmeans/entrypoint": "^0.1.18-rc.19",
32
- "@owlmeans/mongo-resource": "^0.1.18-rc.20",
33
- "@owlmeans/resource": "^0.1.18-rc.17",
34
- "@owlmeans/server-api": "^0.1.18-rc.25",
35
- "@owlmeans/server-auth-identity": "^0.1.18-rc.21",
36
- "@owlmeans/server-context": "^0.1.18-rc.20",
37
- "@scure/base": "^1.1.9"
26
+ "@noble/hashes": "^2.4.0",
27
+ "@owlmeans/auth": "^0.1.18",
28
+ "@owlmeans/auth-common": "^0.1.18",
29
+ "@owlmeans/auth-token": "^0.1.18",
30
+ "@owlmeans/context": "^0.1.18",
31
+ "@owlmeans/entrypoint": "^0.1.18",
32
+ "@owlmeans/log": "^0.1.18",
33
+ "@owlmeans/mongo-resource": "^0.1.18",
34
+ "@owlmeans/resource": "^0.1.18",
35
+ "@owlmeans/server-api": "^0.1.18",
36
+ "@owlmeans/server-auth-identity": "^0.1.18",
37
+ "@owlmeans/server-context": "^0.1.18",
38
+ "@scure/base": "^2.4.0"
38
39
  },
39
40
  "devDependencies": {
40
- "@owlmeans/dep-config": "workspace:*",
41
- "@types/bun": "^1.4.0",
41
+ "@owlmeans/dep-config": "^0.1.18",
42
+ "@types/bun": "^1.4.2",
42
43
  "nodemon": "^3.1.14",
43
44
  "typescript": "^7.0.2"
44
45
  },