@fluixi/oauth2 1.0.0-alpha.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.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api-guard.cjs +185 -0
  3. package/dist/api-guard.d.ts +94 -0
  4. package/dist/api-guard.d.ts.map +1 -0
  5. package/dist/api-guard.js +127 -0
  6. package/dist/api-guard.mjs +141 -0
  7. package/dist/browser-FDUOEUM2.mjs +3544 -0
  8. package/dist/browser-ONMHX3Z3.mjs +3545 -0
  9. package/dist/browser.cjs +735 -0
  10. package/dist/browser.d.ts +3 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +448 -0
  13. package/dist/browser.mjs +704 -0
  14. package/dist/callback.cjs +125 -0
  15. package/dist/callback.d.ts +113 -0
  16. package/dist/callback.d.ts.map +1 -0
  17. package/dist/callback.js +183 -0
  18. package/dist/callback.mjs +106 -0
  19. package/dist/chunk-25WE6UWI.mjs +10 -0
  20. package/dist/chunk-4NSOGPLM.mjs +15 -0
  21. package/dist/chunk-7P6ASYW6.mjs +9 -0
  22. package/dist/chunk-OGSFNTKA.mjs +13 -0
  23. package/dist/client-auth.cjs +115 -0
  24. package/dist/client-auth.d.ts +43 -0
  25. package/dist/client-auth.d.ts.map +1 -0
  26. package/dist/client-auth.js +112 -0
  27. package/dist/client-auth.mjs +84 -0
  28. package/dist/discovery.cjs +86 -0
  29. package/dist/discovery.d.ts +15 -0
  30. package/dist/discovery.d.ts.map +1 -0
  31. package/dist/discovery.js +51 -0
  32. package/dist/discovery.mjs +63 -0
  33. package/dist/dpop-LVPWWADA.mjs +80 -0
  34. package/dist/dpop-NS7NKOWM.mjs +79 -0
  35. package/dist/dpop-store.cjs +152 -0
  36. package/dist/dpop-store.d.ts +37 -0
  37. package/dist/dpop-store.d.ts.map +1 -0
  38. package/dist/dpop-store.js +119 -0
  39. package/dist/dpop-store.mjs +121 -0
  40. package/dist/dpop.cjs +117 -0
  41. package/dist/dpop.d.ts +72 -0
  42. package/dist/dpop.d.ts.map +1 -0
  43. package/dist/dpop.js +114 -0
  44. package/dist/dpop.mjs +86 -0
  45. package/dist/env-config.cjs +366 -0
  46. package/dist/env-config.d.ts +103 -0
  47. package/dist/env-config.d.ts.map +1 -0
  48. package/dist/env-config.js +184 -0
  49. package/dist/env-config.mjs +343 -0
  50. package/dist/env-credentials.cjs +82 -0
  51. package/dist/env-credentials.d.ts +68 -0
  52. package/dist/env-credentials.d.ts.map +1 -0
  53. package/dist/env-credentials.js +76 -0
  54. package/dist/env-credentials.mjs +51 -0
  55. package/dist/index.cjs +940 -0
  56. package/dist/index.d.ts +104 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +101 -0
  59. package/dist/index.mjs +909 -0
  60. package/dist/pkce.cjs +87 -0
  61. package/dist/pkce.d.ts +58 -0
  62. package/dist/pkce.d.ts.map +1 -0
  63. package/dist/pkce.js +112 -0
  64. package/dist/pkce.mjs +66 -0
  65. package/dist/presets.cjs +240 -0
  66. package/dist/presets.d.ts +140 -0
  67. package/dist/presets.d.ts.map +1 -0
  68. package/dist/presets.js +182 -0
  69. package/dist/presets.mjs +217 -0
  70. package/dist/return-to.cjs +46 -0
  71. package/dist/return-to.d.ts +49 -0
  72. package/dist/return-to.d.ts.map +1 -0
  73. package/dist/return-to.js +71 -0
  74. package/dist/return-to.mjs +25 -0
  75. package/dist/roles.cjs +56 -0
  76. package/dist/roles.d.ts +35 -0
  77. package/dist/roles.d.ts.map +1 -0
  78. package/dist/roles.js +37 -0
  79. package/dist/roles.mjs +35 -0
  80. package/dist/server-client.cjs +134 -0
  81. package/dist/server-client.d.ts +12 -0
  82. package/dist/server-client.d.ts.map +1 -0
  83. package/dist/server-client.js +107 -0
  84. package/dist/server-client.mjs +111 -0
  85. package/dist/server.cjs +470 -0
  86. package/dist/server.d.ts +89 -0
  87. package/dist/server.d.ts.map +1 -0
  88. package/dist/server.js +360 -0
  89. package/dist/server.mjs +441 -0
  90. package/dist/service-client.cjs +244 -0
  91. package/dist/service-client.d.ts +89 -0
  92. package/dist/service-client.d.ts.map +1 -0
  93. package/dist/service-client.js +112 -0
  94. package/dist/service-client.mjs +213 -0
  95. package/dist/service.cjs +903 -0
  96. package/dist/service.d.ts +96 -0
  97. package/dist/service.d.ts.map +1 -0
  98. package/dist/service.js +129 -0
  99. package/dist/service.mjs +874 -0
  100. package/dist/tokens.cjs +29 -0
  101. package/dist/tokens.d.ts +13 -0
  102. package/dist/tokens.d.ts.map +1 -0
  103. package/dist/tokens.js +21 -0
  104. package/dist/tokens.mjs +8 -0
  105. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  106. package/dist/types.cjs +33 -0
  107. package/dist/types.d.ts +239 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +23 -0
  110. package/dist/types.mjs +12 -0
  111. package/dist/verify.cjs +724 -0
  112. package/dist/verify.d.ts +205 -0
  113. package/dist/verify.d.ts.map +1 -0
  114. package/dist/verify.js +371 -0
  115. package/dist/verify.mjs +590 -0
  116. package/package.json +121 -0
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/env-credentials.ts
31
+ var env_credentials_exports = {};
32
+ __export(env_credentials_exports, {
33
+ credentialsFromEnv: () => credentialsFromEnv,
34
+ explainCredentials: () => explainCredentials
35
+ });
36
+ module.exports = __toCommonJS(env_credentials_exports);
37
+ async function jwkAt(path) {
38
+ const [{ readFileSync }, { homedir }] = await Promise.all([
39
+ import("node:fs"),
40
+ import("node:os")
41
+ ]);
42
+ const file = path.replace(/^~(?=$|\/)/, homedir());
43
+ let text;
44
+ try {
45
+ text = readFileSync(file, "utf8");
46
+ } catch {
47
+ throw new Error(
48
+ `[fluixi/oauth2] the key file ${file} cannot be read. A signing key is named by path so it can stay outside the repository.`
49
+ );
50
+ }
51
+ try {
52
+ return JSON.parse(text);
53
+ } catch {
54
+ throw new Error(`[fluixi/oauth2] ${file} is not JSON, and a private key is expected as a JWK.`);
55
+ }
56
+ }
57
+ async function credentialsFromEnv(options) {
58
+ const source = options.env ?? (typeof process === "undefined" ? {} : process.env);
59
+ const upper = options.prefix.toUpperCase();
60
+ const prefer = (options.preferPrefix ?? `${upper}_INTROSPECT`).toUpperCase();
61
+ const read = (suffix) => source[`${prefer}_${suffix}`] ?? source[`${upper}_${suffix}`];
62
+ const clientId = read("CLIENT_ID") ?? options.clientId;
63
+ if (!clientId) return null;
64
+ const keyPath = read("PRIVATE_KEY");
65
+ if (keyPath) {
66
+ return {
67
+ clientId,
68
+ privateKey: await jwkAt(keyPath),
69
+ keyId: read("KEY_ID"),
70
+ clientAuthMethod: "private_key_jwt",
71
+ assertionAlgorithm: read("ASSERTION_ALG")
72
+ };
73
+ }
74
+ const clientSecret = read("SECRET") ?? read("CLIENT_SECRET");
75
+ if (clientSecret) return { clientId, clientSecret };
76
+ return null;
77
+ }
78
+ function explainCredentials(options) {
79
+ const upper = options.prefix.toUpperCase();
80
+ const who = options.label ?? options.prefix;
81
+ return `This call authenticates its caller, so ${who} needs credentials. For a client with a shared secret, set ${upper}_CLIENT_SECRET. For one registered with a public key (Okta calls this "Public key / Private key"), set ${upper}_PRIVATE_KEY to the path of its private JWK and ${upper}_KEY_ID to the kid the provider lists. Prefix either with ${upper}_INTROSPECT_ to have a different client ask, which Okta requires: a public SPA cannot introspect at all.`;
82
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Working out how a client proves who it is, from the environment.
3
+ *
4
+ * Introspection and revocation authenticate their caller and the provider decides how. Two
5
+ * ways are in use and they are exclusive: a shared secret, or a signature from a key whose
6
+ * public half the provider holds. Which one applies is a choice made in the provider's
7
+ * console, so code that assumes a secret describes a field that, for an Okta client set to
8
+ * "Public key / Private key", does not exist.
9
+ *
10
+ * Server side. A signing key and a client secret are both things a page must never see, so
11
+ * nothing here may be reached from a browser bundle. The file read is loaded on demand so
12
+ * importing this module does not require node.
13
+ */
14
+ import type { ClientAuthMethod } from './client-auth.js';
15
+ /** What a client needs to authenticate itself, shaped for the options these take. */
16
+ export interface EnvCredentials {
17
+ clientId: string;
18
+ clientSecret?: string;
19
+ privateKey?: Record<string, unknown>;
20
+ keyId?: string;
21
+ clientAuthMethod?: ClientAuthMethod;
22
+ assertionAlgorithm?: string;
23
+ }
24
+ export interface EnvCredentialsOptions {
25
+ /**
26
+ * Prefix for the variable names, upper-cased. `okta` reads `OKTA_CLIENT_SECRET` and the
27
+ * rest.
28
+ */
29
+ prefix: string;
30
+ /** Used when no `<PREFIX>_CLIENT_ID` is set, usually the client the app signs people in with. */
31
+ clientId?: string;
32
+ /**
33
+ * A second prefix tried first, for a provider that wants a different client to ask than
34
+ * the one that signed the user in. Okta needs this: a public SPA cannot introspect, so an
35
+ * API Services client does it.
36
+ *
37
+ * Defaults to `<PREFIX>_INTROSPECT`.
38
+ */
39
+ preferPrefix?: string;
40
+ /** Where to read variables from. Defaults to `process.env`. */
41
+ env?: Record<string, string | undefined>;
42
+ }
43
+ /**
44
+ * Credentials for one provider, or null when none are configured.
45
+ *
46
+ * A named key that cannot be read throws rather than returning null: that is a mistake in
47
+ * the configuration, not an absence of it, and the two need different answers.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const credentials = await credentialsFromEnv({ prefix: 'okta', clientId: config.clientId });
52
+ * if (!credentials) return Response.json({ error: explainCredentials({ prefix: 'okta' }) }, { status: 501 });
53
+ *
54
+ * const introspect = createTokenIntrospector({ issuer, ...credentials, audience: false });
55
+ * ```
56
+ */
57
+ export declare function credentialsFromEnv(options: EnvCredentialsOptions): Promise<EnvCredentials | null>;
58
+ /**
59
+ * What to set, when nothing is.
60
+ *
61
+ * Names both ways, because a message naming only the secret sends someone hunting for a
62
+ * field their client does not have.
63
+ */
64
+ export declare function explainCredentials(options: {
65
+ prefix: string;
66
+ label?: string;
67
+ }): string;
68
+ //# sourceMappingURL=env-credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-credentials.d.ts","sourceRoot":"","sources":["../src/env-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,qFAAqF;AACrF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAyBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA2BhC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAWtF"}
@@ -0,0 +1,76 @@
1
+ /** Reads a JWK from a path, with `~` expanded. Node only, and only when a key is named. */
2
+ async function jwkAt(path) {
3
+ const [{ readFileSync }, { homedir }] = await Promise.all([
4
+ import('node:fs'),
5
+ import('node:os'),
6
+ ]);
7
+ const file = path.replace(/^~(?=$|\/)/, homedir());
8
+ let text;
9
+ try {
10
+ text = readFileSync(file, 'utf8');
11
+ }
12
+ catch {
13
+ throw new Error(`[fluixi/oauth2] the key file ${file} cannot be read. A signing key is named by path so it can stay outside the repository.`);
14
+ }
15
+ try {
16
+ return JSON.parse(text);
17
+ }
18
+ catch {
19
+ throw new Error(`[fluixi/oauth2] ${file} is not JSON, and a private key is expected as a JWK.`);
20
+ }
21
+ }
22
+ /**
23
+ * Credentials for one provider, or null when none are configured.
24
+ *
25
+ * A named key that cannot be read throws rather than returning null: that is a mistake in
26
+ * the configuration, not an absence of it, and the two need different answers.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const credentials = await credentialsFromEnv({ prefix: 'okta', clientId: config.clientId });
31
+ * if (!credentials) return Response.json({ error: explainCredentials({ prefix: 'okta' }) }, { status: 501 });
32
+ *
33
+ * const introspect = createTokenIntrospector({ issuer, ...credentials, audience: false });
34
+ * ```
35
+ */
36
+ export async function credentialsFromEnv(options) {
37
+ const source = options.env ?? (typeof process === 'undefined' ? {} : process.env);
38
+ const upper = options.prefix.toUpperCase();
39
+ const prefer = (options.preferPrefix ?? `${upper}_INTROSPECT`).toUpperCase();
40
+ const read = (suffix) => source[`${prefer}_${suffix}`] ?? source[`${upper}_${suffix}`];
41
+ const clientId = read('CLIENT_ID') ?? options.clientId;
42
+ if (!clientId)
43
+ return null;
44
+ // A key wins over a secret. A client configured both ways at the provider is unusual, and
45
+ // the key is the stronger of the two.
46
+ const keyPath = read('PRIVATE_KEY');
47
+ if (keyPath) {
48
+ return {
49
+ clientId,
50
+ privateKey: await jwkAt(keyPath),
51
+ keyId: read('KEY_ID'),
52
+ clientAuthMethod: 'private_key_jwt',
53
+ assertionAlgorithm: read('ASSERTION_ALG'),
54
+ };
55
+ }
56
+ const clientSecret = read('SECRET') ?? read('CLIENT_SECRET');
57
+ if (clientSecret)
58
+ return { clientId, clientSecret };
59
+ return null;
60
+ }
61
+ /**
62
+ * What to set, when nothing is.
63
+ *
64
+ * Names both ways, because a message naming only the secret sends someone hunting for a
65
+ * field their client does not have.
66
+ */
67
+ export function explainCredentials(options) {
68
+ const upper = options.prefix.toUpperCase();
69
+ const who = options.label ?? options.prefix;
70
+ return (`This call authenticates its caller, so ${who} needs credentials. ` +
71
+ `For a client with a shared secret, set ${upper}_CLIENT_SECRET. ` +
72
+ `For one registered with a public key (Okta calls this "Public key / Private key"), set ` +
73
+ `${upper}_PRIVATE_KEY to the path of its private JWK and ${upper}_KEY_ID to the kid the ` +
74
+ `provider lists. Prefix either with ${upper}_INTROSPECT_ to have a different client ask, ` +
75
+ `which Okta requires: a public SPA cannot introspect at all.`);
76
+ }
@@ -0,0 +1,51 @@
1
+ // src/env-credentials.ts
2
+ async function jwkAt(path) {
3
+ const [{ readFileSync }, { homedir }] = await Promise.all([
4
+ import("node:fs"),
5
+ import("node:os")
6
+ ]);
7
+ const file = path.replace(/^~(?=$|\/)/, homedir());
8
+ let text;
9
+ try {
10
+ text = readFileSync(file, "utf8");
11
+ } catch {
12
+ throw new Error(
13
+ `[fluixi/oauth2] the key file ${file} cannot be read. A signing key is named by path so it can stay outside the repository.`
14
+ );
15
+ }
16
+ try {
17
+ return JSON.parse(text);
18
+ } catch {
19
+ throw new Error(`[fluixi/oauth2] ${file} is not JSON, and a private key is expected as a JWK.`);
20
+ }
21
+ }
22
+ async function credentialsFromEnv(options) {
23
+ const source = options.env ?? (typeof process === "undefined" ? {} : process.env);
24
+ const upper = options.prefix.toUpperCase();
25
+ const prefer = (options.preferPrefix ?? `${upper}_INTROSPECT`).toUpperCase();
26
+ const read = (suffix) => source[`${prefer}_${suffix}`] ?? source[`${upper}_${suffix}`];
27
+ const clientId = read("CLIENT_ID") ?? options.clientId;
28
+ if (!clientId) return null;
29
+ const keyPath = read("PRIVATE_KEY");
30
+ if (keyPath) {
31
+ return {
32
+ clientId,
33
+ privateKey: await jwkAt(keyPath),
34
+ keyId: read("KEY_ID"),
35
+ clientAuthMethod: "private_key_jwt",
36
+ assertionAlgorithm: read("ASSERTION_ALG")
37
+ };
38
+ }
39
+ const clientSecret = read("SECRET") ?? read("CLIENT_SECRET");
40
+ if (clientSecret) return { clientId, clientSecret };
41
+ return null;
42
+ }
43
+ function explainCredentials(options) {
44
+ const upper = options.prefix.toUpperCase();
45
+ const who = options.label ?? options.prefix;
46
+ return `This call authenticates its caller, so ${who} needs credentials. For a client with a shared secret, set ${upper}_CLIENT_SECRET. For one registered with a public key (Okta calls this "Public key / Private key"), set ${upper}_PRIVATE_KEY to the path of its private JWK and ${upper}_KEY_ID to the kid the provider lists. Prefix either with ${upper}_INTROSPECT_ to have a different client ask, which Okta requires: a public SPA cannot introspect at all.`;
47
+ }
48
+ export {
49
+ credentialsFromEnv,
50
+ explainCredentials
51
+ };