@c9up/transit 0.1.0

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 (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +191 -0
  3. package/dist/Oauth1Driver.d.ts +68 -0
  4. package/dist/Oauth1Driver.d.ts.map +1 -0
  5. package/dist/Oauth1Driver.js +148 -0
  6. package/dist/Oauth1Driver.js.map +1 -0
  7. package/dist/Oauth2Driver.d.ts +89 -0
  8. package/dist/Oauth2Driver.d.ts.map +1 -0
  9. package/dist/Oauth2Driver.js +196 -0
  10. package/dist/Oauth2Driver.js.map +1 -0
  11. package/dist/TransitManager.d.ts +59 -0
  12. package/dist/TransitManager.d.ts.map +1 -0
  13. package/dist/TransitManager.js +100 -0
  14. package/dist/TransitManager.js.map +1 -0
  15. package/dist/TransitProvider.d.ts +26 -0
  16. package/dist/TransitProvider.d.ts.map +1 -0
  17. package/dist/TransitProvider.js +32 -0
  18. package/dist/TransitProvider.js.map +1 -0
  19. package/dist/apple.d.ts +45 -0
  20. package/dist/apple.d.ts.map +1 -0
  21. package/dist/apple.js +80 -0
  22. package/dist/apple.js.map +1 -0
  23. package/dist/ber.d.ts +50 -0
  24. package/dist/ber.d.ts.map +1 -0
  25. package/dist/ber.js +156 -0
  26. package/dist/ber.js.map +1 -0
  27. package/dist/c14n.d.ts +38 -0
  28. package/dist/c14n.d.ts.map +1 -0
  29. package/dist/c14n.js +129 -0
  30. package/dist/c14n.js.map +1 -0
  31. package/dist/config.d.ts +115 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +146 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/configure.d.ts +18 -0
  36. package/dist/configure.d.ts.map +1 -0
  37. package/dist/configure.js +33 -0
  38. package/dist/configure.js.map +1 -0
  39. package/dist/drivers/AppleDriver.d.ts +36 -0
  40. package/dist/drivers/AppleDriver.d.ts.map +1 -0
  41. package/dist/drivers/AppleDriver.js +58 -0
  42. package/dist/drivers/AppleDriver.js.map +1 -0
  43. package/dist/drivers/DiscordDriver.d.ts +15 -0
  44. package/dist/drivers/DiscordDriver.d.ts.map +1 -0
  45. package/dist/drivers/DiscordDriver.js +45 -0
  46. package/dist/drivers/DiscordDriver.js.map +1 -0
  47. package/dist/drivers/FacebookDriver.d.ts +15 -0
  48. package/dist/drivers/FacebookDriver.d.ts.map +1 -0
  49. package/dist/drivers/FacebookDriver.js +47 -0
  50. package/dist/drivers/FacebookDriver.js.map +1 -0
  51. package/dist/drivers/GitHubDriver.d.ts +33 -0
  52. package/dist/drivers/GitHubDriver.d.ts.map +1 -0
  53. package/dist/drivers/GitHubDriver.js +72 -0
  54. package/dist/drivers/GitHubDriver.js.map +1 -0
  55. package/dist/drivers/GoogleDriver.d.ts +16 -0
  56. package/dist/drivers/GoogleDriver.d.ts.map +1 -0
  57. package/dist/drivers/GoogleDriver.js +31 -0
  58. package/dist/drivers/GoogleDriver.js.map +1 -0
  59. package/dist/drivers/LdapDirectory.d.ts +51 -0
  60. package/dist/drivers/LdapDirectory.d.ts.map +1 -0
  61. package/dist/drivers/LdapDirectory.js +127 -0
  62. package/dist/drivers/LdapDirectory.js.map +1 -0
  63. package/dist/drivers/LinkedInDriver.d.ts +29 -0
  64. package/dist/drivers/LinkedInDriver.d.ts.map +1 -0
  65. package/dist/drivers/LinkedInDriver.js +97 -0
  66. package/dist/drivers/LinkedInDriver.js.map +1 -0
  67. package/dist/drivers/LinkedInOpenidConnectDriver.d.ts +17 -0
  68. package/dist/drivers/LinkedInOpenidConnectDriver.d.ts.map +1 -0
  69. package/dist/drivers/LinkedInOpenidConnectDriver.js +27 -0
  70. package/dist/drivers/LinkedInOpenidConnectDriver.js.map +1 -0
  71. package/dist/drivers/OidcDriver.d.ts +64 -0
  72. package/dist/drivers/OidcDriver.d.ts.map +1 -0
  73. package/dist/drivers/OidcDriver.js +259 -0
  74. package/dist/drivers/OidcDriver.js.map +1 -0
  75. package/dist/drivers/SamlDriver.d.ts +66 -0
  76. package/dist/drivers/SamlDriver.d.ts.map +1 -0
  77. package/dist/drivers/SamlDriver.js +228 -0
  78. package/dist/drivers/SamlDriver.js.map +1 -0
  79. package/dist/drivers/SpotifyDriver.d.ts +16 -0
  80. package/dist/drivers/SpotifyDriver.d.ts.map +1 -0
  81. package/dist/drivers/SpotifyDriver.js +34 -0
  82. package/dist/drivers/SpotifyDriver.js.map +1 -0
  83. package/dist/drivers/TwitterDriver.d.ts +21 -0
  84. package/dist/drivers/TwitterDriver.d.ts.map +1 -0
  85. package/dist/drivers/TwitterDriver.js +46 -0
  86. package/dist/drivers/TwitterDriver.js.map +1 -0
  87. package/dist/drivers/TwitterXDriver.d.ts +22 -0
  88. package/dist/drivers/TwitterXDriver.d.ts.map +1 -0
  89. package/dist/drivers/TwitterXDriver.js +47 -0
  90. package/dist/drivers/TwitterXDriver.js.map +1 -0
  91. package/dist/dsig.d.ts +51 -0
  92. package/dist/dsig.d.ts.map +1 -0
  93. package/dist/dsig.js +273 -0
  94. package/dist/dsig.js.map +1 -0
  95. package/dist/index.d.ts +38 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +33 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/jwt.d.ts +135 -0
  100. package/dist/jwt.d.ts.map +1 -0
  101. package/dist/jwt.js +167 -0
  102. package/dist/jwt.js.map +1 -0
  103. package/dist/ldap.d.ts +82 -0
  104. package/dist/ldap.d.ts.map +1 -0
  105. package/dist/ldap.js +271 -0
  106. package/dist/ldap.js.map +1 -0
  107. package/dist/nodeEnv.d.ts +17 -0
  108. package/dist/nodeEnv.d.ts.map +1 -0
  109. package/dist/nodeEnv.js +33 -0
  110. package/dist/nodeEnv.js.map +1 -0
  111. package/dist/oauth1.d.ts +68 -0
  112. package/dist/oauth1.d.ts.map +1 -0
  113. package/dist/oauth1.js +106 -0
  114. package/dist/oauth1.js.map +1 -0
  115. package/dist/oidc.d.ts +61 -0
  116. package/dist/oidc.d.ts.map +1 -0
  117. package/dist/oidc.js +151 -0
  118. package/dist/oidc.js.map +1 -0
  119. package/dist/quasar.d.ts +14 -0
  120. package/dist/quasar.d.ts.map +1 -0
  121. package/dist/quasar.js +42 -0
  122. package/dist/quasar.js.map +1 -0
  123. package/dist/replay.d.ts +70 -0
  124. package/dist/replay.d.ts.map +1 -0
  125. package/dist/replay.js +82 -0
  126. package/dist/replay.js.map +1 -0
  127. package/dist/saml.d.ts +68 -0
  128. package/dist/saml.d.ts.map +1 -0
  129. package/dist/saml.js +181 -0
  130. package/dist/saml.js.map +1 -0
  131. package/dist/services/main.d.ts +22 -0
  132. package/dist/services/main.d.ts.map +1 -0
  133. package/dist/services/main.js +39 -0
  134. package/dist/services/main.js.map +1 -0
  135. package/dist/testing/FakeTransit.d.ts +82 -0
  136. package/dist/testing/FakeTransit.d.ts.map +1 -0
  137. package/dist/testing/FakeTransit.js +160 -0
  138. package/dist/testing/FakeTransit.js.map +1 -0
  139. package/dist/types.d.ts +118 -0
  140. package/dist/types.d.ts.map +1 -0
  141. package/dist/types.js +27 -0
  142. package/dist/types.js.map +1 -0
  143. package/dist/xml.d.ts +72 -0
  144. package/dist/xml.d.ts.map +1 -0
  145. package/dist/xml.js +353 -0
  146. package/dist/xml.js.map +1 -0
  147. package/package.json +73 -0
  148. package/src/Oauth1Driver.ts +216 -0
  149. package/src/Oauth2Driver.ts +271 -0
  150. package/src/TransitManager.ts +145 -0
  151. package/src/TransitProvider.ts +51 -0
  152. package/src/apple.ts +101 -0
  153. package/src/ber.ts +175 -0
  154. package/src/c14n.ts +187 -0
  155. package/src/config.ts +160 -0
  156. package/src/configure.ts +47 -0
  157. package/src/drivers/AppleDriver.ts +69 -0
  158. package/src/drivers/DiscordDriver.ts +50 -0
  159. package/src/drivers/FacebookDriver.ts +53 -0
  160. package/src/drivers/GitHubDriver.ts +91 -0
  161. package/src/drivers/GoogleDriver.ts +38 -0
  162. package/src/drivers/LdapDirectory.ts +185 -0
  163. package/src/drivers/LinkedInDriver.ts +105 -0
  164. package/src/drivers/LinkedInOpenidConnectDriver.ts +33 -0
  165. package/src/drivers/OidcDriver.ts +379 -0
  166. package/src/drivers/SamlDriver.ts +326 -0
  167. package/src/drivers/SpotifyDriver.ts +38 -0
  168. package/src/drivers/TwitterDriver.ts +55 -0
  169. package/src/drivers/TwitterXDriver.ts +53 -0
  170. package/src/dsig.ts +405 -0
  171. package/src/index.ts +85 -0
  172. package/src/jwt.ts +263 -0
  173. package/src/ldap.ts +374 -0
  174. package/src/nodeEnv.ts +31 -0
  175. package/src/oauth1.ts +144 -0
  176. package/src/oidc.ts +208 -0
  177. package/src/quasar.ts +64 -0
  178. package/src/replay.ts +136 -0
  179. package/src/saml.ts +309 -0
  180. package/src/services/main.ts +47 -0
  181. package/src/testing/FakeTransit.ts +233 -0
  182. package/src/types.ts +150 -0
  183. package/src/xml.ts +438 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LdapDirectory.js","sourceRoot":"","sources":["../../src/drivers/LdapDirectory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * LinkedIn OAuth2 driver — the member API.
3
+ *
4
+ * For an application whose LinkedIn app holds `r_liteprofile` /
5
+ * `r_emailaddress`. It needs two calls: the profile carries no address, and
6
+ * the address endpoint carries no profile.
7
+ *
8
+ * LinkedIn issues new applications OpenID Connect instead — that is
9
+ * `LinkedInOpenidConnectDriver`.
10
+ */
11
+ import { Oauth2Driver } from "../Oauth2Driver.js";
12
+ import type { TransitUser } from "../types.js";
13
+ export declare class LinkedInDriver extends Oauth2Driver {
14
+ protected readonly provider = "LinkedIn";
15
+ protected readonly authorizeUrl = "https://www.linkedin.com/oauth/v2/authorization";
16
+ protected readonly accessTokenUrl = "https://www.linkedin.com/oauth/v2/accessToken";
17
+ protected readonly userInfoUrl = "https://api.linkedin.com/v2/me";
18
+ protected readonly defaultScopes: readonly ["r_liteprofile", "r_emailaddress"];
19
+ protected userInfoParams(): Record<string, string>;
20
+ protected fetchUser(accessToken: string): Promise<TransitUser>;
21
+ /**
22
+ * The address lives behind its own endpoint, and only with the
23
+ * `r_emailaddress` scope — without it the response has no elements, which is
24
+ * reported here rather than surfacing as an empty address downstream.
25
+ */
26
+ fetchEmail(accessToken: string): Promise<string>;
27
+ protected mapUser(raw: Record<string, unknown>): TransitUser;
28
+ }
29
+ //# sourceMappingURL=LinkedInDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedInDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/LinkedInDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,qBAAa,cAAe,SAAQ,YAAY;IAC/C,SAAS,CAAC,QAAQ,CAAC,QAAQ,cAAc;IACzC,SAAS,CAAC,QAAQ,CAAC,YAAY,qDACoB;IACnD,SAAS,CAAC,QAAQ,CAAC,cAAc,mDACgB;IACjD,SAAS,CAAC,QAAQ,CAAC,WAAW,oCAAoC;IAClE,SAAS,CAAC,QAAQ,CAAC,aAAa,+CAGrB;cAEQ,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;cAIlC,SAAS,CACjC,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC;IAQvB;;;;OAIG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBtD,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW;CAiB5D"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * LinkedIn OAuth2 driver — the member API.
3
+ *
4
+ * For an application whose LinkedIn app holds `r_liteprofile` /
5
+ * `r_emailaddress`. It needs two calls: the profile carries no address, and
6
+ * the address endpoint carries no profile.
7
+ *
8
+ * LinkedIn issues new applications OpenID Connect instead — that is
9
+ * `LinkedInOpenidConnectDriver`.
10
+ */
11
+ import { Oauth2Driver } from "../Oauth2Driver.js";
12
+ const EMAIL_URL = "https://api.linkedin.com/v2/emailAddress";
13
+ const PROFILE_PROJECTION = "(id,localizedFirstName,localizedLastName,vanityName,profilePicture(displayImage~:playableStreams))";
14
+ export class LinkedInDriver extends Oauth2Driver {
15
+ provider = "LinkedIn";
16
+ authorizeUrl = "https://www.linkedin.com/oauth/v2/authorization";
17
+ accessTokenUrl = "https://www.linkedin.com/oauth/v2/accessToken";
18
+ userInfoUrl = "https://api.linkedin.com/v2/me";
19
+ defaultScopes = [
20
+ "r_liteprofile",
21
+ "r_emailaddress",
22
+ ];
23
+ userInfoParams() {
24
+ return { projection: PROFILE_PROJECTION };
25
+ }
26
+ async fetchUser(accessToken) {
27
+ const raw = await this.get(this.userInfoUrl, accessToken, {
28
+ ...this.userInfoParams(),
29
+ });
30
+ const email = await this.fetchEmail(accessToken);
31
+ return { ...this.mapUser(raw), email };
32
+ }
33
+ /**
34
+ * The address lives behind its own endpoint, and only with the
35
+ * `r_emailaddress` scope — without it the response has no elements, which is
36
+ * reported here rather than surfacing as an empty address downstream.
37
+ */
38
+ async fetchEmail(accessToken) {
39
+ const body = await this.get(EMAIL_URL, accessToken, {
40
+ q: "members",
41
+ projection: "(elements*(primary,type,handle~))",
42
+ });
43
+ const elements = Array.isArray(body.elements) ? body.elements : [];
44
+ for (const element of elements) {
45
+ if (typeof element !== "object" || element === null)
46
+ continue;
47
+ if (Reflect.get(element, "type") !== "EMAIL")
48
+ continue;
49
+ const handle = Reflect.get(element, "handle~");
50
+ if (typeof handle !== "object" || handle === null)
51
+ continue;
52
+ const address = Reflect.get(handle, "emailAddress");
53
+ if (typeof address === "string" && address !== "")
54
+ return address;
55
+ }
56
+ throw new Error("LinkedIn returned no email address — the application needs the 'r_emailaddress' scope.");
57
+ }
58
+ mapUser(raw) {
59
+ const first = String(raw.localizedFirstName ?? "");
60
+ const last = String(raw.localizedLastName ?? "");
61
+ return {
62
+ id: String(raw.id ?? ""),
63
+ email: "",
64
+ name: [first, last].filter(Boolean).join(" "),
65
+ nickName: typeof raw.vanityName === "string" && raw.vanityName !== ""
66
+ ? raw.vanityName
67
+ : [first, last].filter(Boolean).join(" "),
68
+ avatarUrl: pictureUrl(raw),
69
+ // The member API vouches for nothing about the address.
70
+ emailVerificationState: "unsupported",
71
+ raw,
72
+ };
73
+ }
74
+ }
75
+ /**
76
+ * The picture arrives as a list of renditions, largest last. Nothing about
77
+ * the shape is guaranteed, so every step is checked.
78
+ */
79
+ function pictureUrl(raw) {
80
+ const picture = raw.profilePicture;
81
+ if (typeof picture !== "object" || picture === null)
82
+ return undefined;
83
+ const display = Reflect.get(picture, "displayImage~");
84
+ if (typeof display !== "object" || display === null)
85
+ return undefined;
86
+ const elements = Reflect.get(display, "elements");
87
+ if (!Array.isArray(elements) || elements.length === 0)
88
+ return undefined;
89
+ const identifiers = Reflect.get(Object(elements[0]), "identifiers");
90
+ if (!Array.isArray(identifiers) || identifiers.length === 0)
91
+ return undefined;
92
+ const identifier = Reflect.get(Object(identifiers[0]), "identifier");
93
+ return typeof identifier === "string" && identifier !== ""
94
+ ? identifier
95
+ : undefined;
96
+ }
97
+ //# sourceMappingURL=LinkedInDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedInDriver.js","sourceRoot":"","sources":["../../src/drivers/LinkedInDriver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * LinkedIn OAuth2 driver — OpenID Connect.
3
+ *
4
+ * This is the flow LinkedIn issues new applications: one `userinfo` call,
5
+ * standard claims. The member API is `LinkedInDriver`.
6
+ */
7
+ import { Oauth2Driver } from "../Oauth2Driver.js";
8
+ import type { TransitUser } from "../types.js";
9
+ export declare class LinkedInOpenidConnectDriver extends Oauth2Driver {
10
+ protected readonly provider = "LinkedIn";
11
+ protected readonly authorizeUrl = "https://www.linkedin.com/oauth/v2/authorization";
12
+ protected readonly accessTokenUrl = "https://www.linkedin.com/oauth/v2/accessToken";
13
+ protected readonly userInfoUrl = "https://api.linkedin.com/v2/userinfo";
14
+ protected readonly defaultScopes: readonly ["openid", "profile", "email"];
15
+ protected mapUser(raw: Record<string, unknown>): TransitUser;
16
+ }
17
+ //# sourceMappingURL=LinkedInOpenidConnectDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedInOpenidConnectDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/LinkedInOpenidConnectDriver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAO,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,qBAAa,2BAA4B,SAAQ,YAAY;IAC5D,SAAS,CAAC,QAAQ,CAAC,QAAQ,cAAc;IACzC,SAAS,CAAC,QAAQ,CAAC,YAAY,qDACoB;IACnD,SAAS,CAAC,QAAQ,CAAC,cAAc,mDACgB;IACjD,SAAS,CAAC,QAAQ,CAAC,WAAW,0CAA0C;IACxE,SAAS,CAAC,QAAQ,CAAC,aAAa,0CAA2C;IAE3E,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW;CAa5D"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * LinkedIn OAuth2 driver — OpenID Connect.
3
+ *
4
+ * This is the flow LinkedIn issues new applications: one `userinfo` call,
5
+ * standard claims. The member API is `LinkedInDriver`.
6
+ */
7
+ import { Oauth2Driver, str } from "../Oauth2Driver.js";
8
+ export class LinkedInOpenidConnectDriver extends Oauth2Driver {
9
+ provider = "LinkedIn";
10
+ authorizeUrl = "https://www.linkedin.com/oauth/v2/authorization";
11
+ accessTokenUrl = "https://www.linkedin.com/oauth/v2/accessToken";
12
+ userInfoUrl = "https://api.linkedin.com/v2/userinfo";
13
+ defaultScopes = ["openid", "profile", "email"];
14
+ mapUser(raw) {
15
+ return {
16
+ // `sub` is the stable subject identifier; `id` does not exist here.
17
+ id: String(raw.sub ?? ""),
18
+ email: String(raw.email ?? ""),
19
+ name: String(raw.name ?? ""),
20
+ nickName: str(raw, "given_name"),
21
+ avatarUrl: str(raw, "picture"),
22
+ emailVerificationState: raw.email_verified === true ? "verified" : "unverified",
23
+ raw,
24
+ };
25
+ }
26
+ }
27
+ //# sourceMappingURL=LinkedInOpenidConnectDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedInOpenidConnectDriver.js","sourceRoot":"","sources":["../../src/drivers/LinkedInOpenidConnectDriver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAGvD,MAAM,OAAO,2BAA4B,SAAQ,YAAY;IACzC,QAAQ,GAAG,UAAU,CAAC;IACtB,YAAY,GAC9B,iDAAiD,CAAC;IAChC,cAAc,GAChC,+CAA+C,CAAC;IAC9B,WAAW,GAAG,sCAAsC,CAAC;IACrD,aAAa,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC;IAEjE,OAAO,CAAC,GAA4B;QAC7C,OAAO;YACN,oEAAoE;YACpE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC;YACzB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;YAC9B,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;YAC5B,QAAQ,EAAE,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC;YAChC,SAAS,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC;YAC9B,sBAAsB,EACrB,GAAG,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;YACxD,GAAG;SACH,CAAC;IACH,CAAC;CACD"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Generic OpenID Connect.
3
+ *
4
+ * One driver for every provider that conforms: Keycloak, Auth0, Okta,
5
+ * Entra ID, Authentik, Zitadel, Ping, Google. It is given an issuer and reads
6
+ * the rest — endpoints, keys, supported algorithms — from what the provider
7
+ * publishes about itself.
8
+ *
9
+ * What separates this from a plain OAuth2 driver is that the answer is a
10
+ * SIGNED STATEMENT about who the user is, not just a token to go ask with.
11
+ * That statement is only worth anything once it has been verified, which is
12
+ * what `jwt.ts` does and what most of this class exists to feed.
13
+ */
14
+ import { type RemoteOptions } from "../oidc.js";
15
+ import type { OAuthToken, RedirectRequest, TransitDriver, TransitUser } from "../types.js";
16
+ export interface OidcConfig {
17
+ /** The provider's issuer URL, exactly as it appears in its tokens. */
18
+ issuer: string;
19
+ clientId: string;
20
+ /**
21
+ * The client secret, or something that mints one. Apple has no static
22
+ * secret — it expects a short-lived JWT signed with a private key — so this
23
+ * is resolved at each token request rather than read once.
24
+ */
25
+ clientSecret: string | (() => string | Promise<string>);
26
+ callbackUrl: string;
27
+ /** Default `["openid", "profile", "email"]`. `openid` is added if omitted. */
28
+ scopes?: string[];
29
+ /** Extra parameters on the authorize URL — `prompt`, `login_hint`, `acr_values`. */
30
+ authorizeParams?: Record<string, string>;
31
+ /**
32
+ * Also call the userinfo endpoint, when the provider advertises one.
33
+ * Default `true`: the id_token often carries only the subject.
34
+ */
35
+ userinfo?: boolean;
36
+ /** Tolerance for clock drift against the provider, in seconds. Default 60. */
37
+ leewaySeconds?: number;
38
+ /** Cache tuning for the discovery document and the signing keys. */
39
+ cache?: RemoteOptions;
40
+ }
41
+ export declare class OidcDriver implements TransitDriver {
42
+ #private;
43
+ constructor(config: OidcConfig);
44
+ /**
45
+ * The endpoints are only known once the provider has been asked, so there
46
+ * is nothing to build offline.
47
+ */
48
+ redirectUrl(): string;
49
+ begin(state?: string): Promise<RedirectRequest>;
50
+ callback(code: string, state?: string, expectedState?: string, secret?: string): Promise<{
51
+ user: TransitUser;
52
+ token: OAuthToken;
53
+ }>;
54
+ /** Read a profile behind a token already held, through the userinfo endpoint. */
55
+ userFromToken(accessToken: string): Promise<TransitUser>;
56
+ /**
57
+ * Turn the claims into the shape every driver answers with. A provider that
58
+ * spells a standard claim its own way overrides this.
59
+ */
60
+ protected mapUser(raw: Record<string, unknown>): TransitUser;
61
+ }
62
+ /** Standard OpenID Connect claims, in the shape every driver answers with. */
63
+ export declare function mapOidcUser(raw: Record<string, unknown>): TransitUser;
64
+ //# sourceMappingURL=OidcDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OidcDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/OidcDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EACX,UAAU,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,UAAU;IAC1B,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB;AASD,qBAAa,UAAW,YAAW,aAAa;;gBAKnC,MAAM,EAAE,UAAU;IAM9B;;;OAGG;IACH,WAAW,IAAI,MAAM;IAMf,KAAK,CAAC,KAAK,GAAE,MAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAmC7D,QAAQ,CACb,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;IAgCpD,iFAAiF;IAC3E,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAY9D;;;OAGG;IACH,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW;CA0J5D;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAkBrE"}
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Generic OpenID Connect.
3
+ *
4
+ * One driver for every provider that conforms: Keycloak, Auth0, Okta,
5
+ * Entra ID, Authentik, Zitadel, Ping, Google. It is given an issuer and reads
6
+ * the rest — endpoints, keys, supported algorithms — from what the provider
7
+ * publishes about itself.
8
+ *
9
+ * What separates this from a plain OAuth2 driver is that the answer is a
10
+ * SIGNED STATEMENT about who the user is, not just a token to go ask with.
11
+ * That statement is only worth anything once it has been verified, which is
12
+ * what `jwt.ts` does and what most of this class exists to feed.
13
+ */
14
+ import { randomUUID } from "node:crypto";
15
+ import { assertIdTokenClaims, decodeJws, isSupportedAlg, verifyJwsSignature, } from "../jwt.js";
16
+ import { challengeFor, createCodeVerifier } from "../Oauth2Driver.js";
17
+ import { JwksCache, OidcDiscovery, } from "../oidc.js";
18
+ import { assertOAuthState } from "../types.js";
19
+ /**
20
+ * `secret` carries two values here — the PKCE verifier and the nonce — and the
21
+ * caller only has to store it and hand it back. Joined by a dot, which the
22
+ * base64url alphabet does not contain, so neither half can forge a boundary.
23
+ */
24
+ const SECRET_SEPARATOR = ".";
25
+ export class OidcDriver {
26
+ #config;
27
+ #discovery;
28
+ #jwks;
29
+ constructor(config) {
30
+ this.#config = config;
31
+ this.#discovery = new OidcDiscovery(config.issuer, config.cache);
32
+ this.#jwks = new JwksCache(config.cache);
33
+ }
34
+ /**
35
+ * The endpoints are only known once the provider has been asked, so there
36
+ * is nothing to build offline.
37
+ */
38
+ redirectUrl() {
39
+ throw new Error("[transit] an OpenID Connect provider publishes its endpoints, so the redirect is fetched. Use begin() instead of redirect().");
40
+ }
41
+ async begin(state = randomUUID()) {
42
+ const metadata = await this.#discovery.metadata();
43
+ const verifier = createCodeVerifier();
44
+ const nonce = randomUUID();
45
+ const params = new URLSearchParams({
46
+ client_id: this.#config.clientId,
47
+ redirect_uri: this.#config.callbackUrl,
48
+ response_type: "code",
49
+ scope: this.#scopes().join(" "),
50
+ state,
51
+ nonce,
52
+ ...this.#config.authorizeParams,
53
+ });
54
+ // PKCE is not optional for a public client and costs nothing for a
55
+ // confidential one, so it is sent unless the provider says outright that
56
+ // it does not take S256.
57
+ const pkce = metadata.code_challenge_methods_supported?.includes("S256") !== false;
58
+ if (pkce) {
59
+ params.set("code_challenge", challengeFor(verifier));
60
+ params.set("code_challenge_method", "S256");
61
+ }
62
+ // Whether PKCE was used travels in `secret`. Sending a verifier for a
63
+ // challenge that was never sent is at best noise, and a strict provider
64
+ // refuses the exchange over it.
65
+ return {
66
+ url: `${metadata.authorization_endpoint}?${params}`,
67
+ state,
68
+ secret: `${pkce ? verifier : ""}${SECRET_SEPARATOR}${nonce}`,
69
+ };
70
+ }
71
+ async callback(code, state, expectedState, secret) {
72
+ assertOAuthState(state, expectedState);
73
+ const { verifier, nonce } = splitSecret(secret);
74
+ const metadata = await this.#discovery.metadata();
75
+ const tokens = await this.#exchange(metadata, code, verifier);
76
+ const idToken = tokens.id_token;
77
+ if (typeof idToken !== "string" || idToken === "") {
78
+ throw new Error("[transit] the provider returned no id_token — check that the 'openid' scope is granted");
79
+ }
80
+ const claims = await this.#verifyIdToken(metadata, idToken, nonce);
81
+ const accessToken = String(tokens.access_token ?? "");
82
+ const profile = await this.#profile(metadata, accessToken, claims);
83
+ return {
84
+ user: this.mapUser(profile),
85
+ token: {
86
+ accessToken,
87
+ ...(typeof tokens.refresh_token === "string"
88
+ ? { refreshToken: tokens.refresh_token }
89
+ : {}),
90
+ ...(typeof tokens.expires_in === "number"
91
+ ? { expiresIn: tokens.expires_in }
92
+ : {}),
93
+ },
94
+ };
95
+ }
96
+ /** Read a profile behind a token already held, through the userinfo endpoint. */
97
+ async userFromToken(accessToken) {
98
+ const metadata = await this.#discovery.metadata();
99
+ if (!metadata.userinfo_endpoint) {
100
+ throw new Error(`[transit] '${this.#config.issuer}' publishes no userinfo endpoint, so a profile cannot be read from a token alone.`);
101
+ }
102
+ return this.mapUser(await this.#userinfo(metadata.userinfo_endpoint, accessToken));
103
+ }
104
+ /**
105
+ * Turn the claims into the shape every driver answers with. A provider that
106
+ * spells a standard claim its own way overrides this.
107
+ */
108
+ mapUser(raw) {
109
+ return mapOidcUser(raw);
110
+ }
111
+ /** The secret for one token request. */
112
+ async #clientSecret() {
113
+ const secret = this.#config.clientSecret;
114
+ return typeof secret === "function" ? await secret() : secret;
115
+ }
116
+ #scopes() {
117
+ const scopes = [...(this.#config.scopes ?? ["openid", "profile", "email"])];
118
+ // Without `openid` the provider runs a plain OAuth2 flow and returns no
119
+ // id_token, which fails later with a much less obvious message.
120
+ if (!scopes.includes("openid"))
121
+ scopes.unshift("openid");
122
+ return scopes;
123
+ }
124
+ async #exchange(metadata, code, verifier) {
125
+ const body = new URLSearchParams({
126
+ grant_type: "authorization_code",
127
+ code,
128
+ redirect_uri: this.#config.callbackUrl,
129
+ client_id: this.#config.clientId,
130
+ client_secret: await this.#clientSecret(),
131
+ // Only when a challenge was actually sent.
132
+ ...(verifier === "" ? {} : { code_verifier: verifier }),
133
+ });
134
+ const response = await fetch(metadata.token_endpoint, {
135
+ method: "POST",
136
+ headers: {
137
+ Accept: "application/json",
138
+ "Content-Type": "application/x-www-form-urlencoded",
139
+ },
140
+ body,
141
+ });
142
+ if (!response.ok) {
143
+ throw new Error(`[transit] OpenID Connect token exchange failed (HTTP ${response.status})`);
144
+ }
145
+ return (await response.json());
146
+ }
147
+ /**
148
+ * The signature first, then every claim. The algorithm comes from what the
149
+ * provider declared it signs with, intersected with what can be verified —
150
+ * never from the token's own header.
151
+ */
152
+ async #verifyIdToken(metadata, idToken, nonce) {
153
+ const parts = decodeJws(idToken);
154
+ const alg = this.#algorithmFor(metadata, parts.header.alg);
155
+ const kid = typeof parts.header.kid === "string" ? parts.header.kid : undefined;
156
+ const key = await this.#jwks.key(metadata.jwks_uri, kid);
157
+ if (!verifyJwsSignature(parts, key, alg)) {
158
+ throw new Error("[transit] id_token signature does not verify");
159
+ }
160
+ return assertIdTokenClaims(parts.payload, {
161
+ issuer: metadata.issuer,
162
+ audience: this.#config.clientId,
163
+ nonce,
164
+ leewaySeconds: this.#config.leewaySeconds,
165
+ });
166
+ }
167
+ /**
168
+ * Which algorithm to verify with.
169
+ *
170
+ * The header's value is used only to CHOOSE among what the provider says it
171
+ * signs with; it can never introduce one that was not declared, and it can
172
+ * never select a family this refuses.
173
+ */
174
+ #algorithmFor(metadata, headerAlg) {
175
+ // Every conforming provider supports RS256 and publishes the list; the
176
+ // narrow reading when it does not is that RS256 is all there is.
177
+ const declared = metadata.id_token_signing_alg_values_supported ?? [
178
+ "RS256",
179
+ ];
180
+ const allowed = declared.filter(isSupportedAlg);
181
+ if (allowed.length === 0) {
182
+ throw new Error(`[transit] '${this.#config.issuer}' signs id_tokens only with algorithms Transit refuses (${declared.join(", ")}). Asymmetric signatures are required.`);
183
+ }
184
+ if (!isSupportedAlg(headerAlg)) {
185
+ throw new Error(`[transit] id_token announces '${String(headerAlg)}', which Transit does not verify — only asymmetric signatures are accepted`);
186
+ }
187
+ if (!allowed.includes(headerAlg)) {
188
+ throw new Error(`[transit] id_token announces '${headerAlg}', which '${this.#config.issuer}' did not declare it signs with`);
189
+ }
190
+ // The header only ever SELECTS from the set computed above. It cannot
191
+ // introduce an algorithm, which is what keeps `none` and the
192
+ // shared-secret families away from the verifier entirely.
193
+ return headerAlg;
194
+ }
195
+ /**
196
+ * The claims, plus userinfo when there is one. The subject must be the same
197
+ * in both: a userinfo response describing another user is a substituted
198
+ * token, not a richer profile.
199
+ */
200
+ async #profile(metadata, accessToken, claims) {
201
+ if (this.#config.userinfo === false ||
202
+ !metadata.userinfo_endpoint ||
203
+ accessToken === "") {
204
+ return claims;
205
+ }
206
+ const info = await this.#userinfo(metadata.userinfo_endpoint, accessToken);
207
+ if (info.sub !== claims.sub) {
208
+ throw new Error("[transit] the userinfo response describes a different subject than the id_token");
209
+ }
210
+ return { ...claims, ...info };
211
+ }
212
+ async #userinfo(endpoint, accessToken) {
213
+ const response = await fetch(endpoint, {
214
+ headers: {
215
+ Authorization: `Bearer ${accessToken}`,
216
+ Accept: "application/json",
217
+ },
218
+ });
219
+ if (!response.ok) {
220
+ throw new Error(`[transit] OpenID Connect userinfo request failed (HTTP ${response.status})`);
221
+ }
222
+ return (await response.json());
223
+ }
224
+ }
225
+ /** Standard OpenID Connect claims, in the shape every driver answers with. */
226
+ export function mapOidcUser(raw) {
227
+ const given = str(raw, "given_name");
228
+ const family = str(raw, "family_name");
229
+ const email = str(raw, "email");
230
+ return {
231
+ id: String(raw.sub ?? ""),
232
+ email: email ?? "",
233
+ name: str(raw, "name") ?? [given, family].filter(Boolean).join(" "),
234
+ nickName: str(raw, "preferred_username") ?? given,
235
+ avatarUrl: str(raw, "picture"),
236
+ emailVerificationState: email === undefined
237
+ ? "unsupported"
238
+ : raw.email_verified === true
239
+ ? "verified"
240
+ : "unverified",
241
+ raw,
242
+ };
243
+ }
244
+ function str(raw, key) {
245
+ const value = raw[key];
246
+ return typeof value === "string" && value !== "" ? value : undefined;
247
+ }
248
+ /** Split the value `begin()` asked the caller to keep. */
249
+ function splitSecret(secret) {
250
+ const index = secret?.indexOf(SECRET_SEPARATOR) ?? -1;
251
+ // An empty verifier is legitimate — it says PKCE was not used. A missing
252
+ // separator, or a missing nonce, is a value that did not come from begin().
253
+ const nonce = secret === undefined ? "" : secret.slice(index + 1);
254
+ if (secret === undefined || index === -1 || nonce === "") {
255
+ throw new Error("[transit] OpenID Connect needs the value begin() returned as `secret` — store it with the state and pass it back here.");
256
+ }
257
+ return { verifier: secret.slice(0, index), nonce };
258
+ }
259
+ //# sourceMappingURL=OidcDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OidcDriver.js","sourceRoot":"","sources":["../../src/drivers/OidcDriver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * SAML 2.0 Web Browser SSO.
3
+ *
4
+ * The pieces are the four layers below this one; what this adds is the walk
5
+ * between them, and the two bindings a browser sign-in uses: the request
6
+ * leaves deflated in a query string, and the response comes back base64 in a
7
+ * form POST.
8
+ *
9
+ * The order here is the security. The signature is checked FIRST, and
10
+ * everything read afterwards comes out of the element it covers — the status
11
+ * being the one exception, and a deliberate one.
12
+ */
13
+ import { type AssertionReplayStore } from "../replay.js";
14
+ import type { OAuthToken, RedirectRequest, TransitDriver, TransitUser } from "../types.js";
15
+ export interface SamlConfig {
16
+ /** This application's entity id, as the provider knows it. */
17
+ entityId: string;
18
+ /** Where the provider posts its response — this application's ACS URL. */
19
+ callbackUrl: string;
20
+ /** The provider's entity id, exactly as its metadata declares it. */
21
+ issuer: string;
22
+ /** The provider's sign-on endpoint, for the redirect binding. */
23
+ signOnUrl: string;
24
+ /**
25
+ * The provider's signing certificates, from its metadata. Several are
26
+ * accepted so a rotation can be prepared before it happens.
27
+ */
28
+ certificates: string[];
29
+ /** The name identifier format to ask for. */
30
+ nameIdFormat?: string;
31
+ /** Tolerance for clock drift against the provider. Default 60 seconds. */
32
+ clockSkewSeconds?: number;
33
+ /**
34
+ * Where used assertions are remembered.
35
+ *
36
+ * Defaults to this process's memory, which accepts the same assertion once
37
+ * per replica — pass `replayStores.redis(…)` as soon as there are two.
38
+ */
39
+ replayStore?: AssertionReplayStore | (() => AssertionReplayStore);
40
+ /** The attribute names this provider uses, when they are not the usual ones. */
41
+ claims?: {
42
+ email?: string;
43
+ name?: string;
44
+ nickName?: string;
45
+ };
46
+ }
47
+ export declare class SamlDriver implements TransitDriver {
48
+ #private;
49
+ constructor(config: SamlConfig);
50
+ /**
51
+ * A SAML request carries its own id, and that id is what the response has
52
+ * to answer. There is nothing to build without minting one.
53
+ */
54
+ redirectUrl(): string;
55
+ begin(state?: string): Promise<RedirectRequest>;
56
+ /**
57
+ * `code` is the base64 `SAMLResponse` from the form post, `state` the
58
+ * `RelayState` that came back, `expectedState` the one sent, and `secret`
59
+ * the request id `begin()` minted.
60
+ */
61
+ callback(code: string, state?: string, expectedState?: string, secret?: string): Promise<{
62
+ user: TransitUser;
63
+ token: OAuthToken;
64
+ }>;
65
+ }
66
+ //# sourceMappingURL=SamlDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SamlDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/SamlDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EACN,KAAK,oBAAoB,EAEzB,MAAM,cAAc,CAAC;AAQtB,OAAO,KAAK,EACX,UAAU,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,MAAM,aAAa,CAAC;AAkCrB,MAAM,WAAW,UAAU;IAC1B,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,oBAAoB,GAAG,CAAC,MAAM,oBAAoB,CAAC,CAAC;IAClE,gFAAgF;IAChF,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9D;AAsBD,qBAAa,UAAW,YAAW,aAAa;;gBAInC,MAAM,EAAE,UAAU;IAkB9B;;;OAGG;IACH,WAAW,IAAI,MAAM;IAMf,KAAK,CAAC,KAAK,GAAE,MAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAwBnE;;;;OAIG;IACG,QAAQ,CACb,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;CA+GpD"}