fhirstarterjs 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md CHANGED
@@ -1,44 +1,44 @@
1
- # Kopimi License
2
-
3
- This software is released under the Kopimi License.
4
-
5
- ## Permission
6
-
7
- Permission is hereby granted, free of charge, to any person obtaining a copy of
8
- this software and associated documentation files (the "Software"), to copy,
9
- modify, merge, publish, distribute, sublicense, sell, use, study,
10
- reverse-engineer, decompile, and otherwise deal in the Software without
11
- restriction, including without limitation for commercial or non-commercial
12
- purposes.
13
-
14
- Commercial use, sale, resale, or distribution for profit must include clear
15
- attribution to the original author(s) in the distributed copy and in any
16
- customary public-facing product notices, documentation, credits, or legal
17
- notices associated with that use.
18
-
19
- ## Kopimi Propagation
20
-
21
- The Software is Kopimi. Copies, substantial portions, and derivative works must
22
- preserve the freedom to copy, share, modify, remix, and redistribute the
23
- Software. No copy, substantial portion, or derivative work may be distributed
24
- under terms that prohibit those freedoms.
25
-
26
- License notices, author notices, and Kopimi notices included with the Software
27
- may not be removed from redistributed copies, substantial portions, or
28
- derivative works.
29
-
30
- Attribution to the original author(s) is appreciated for non-commercial use and
31
- required for commercial use as described above.
32
-
33
- ## Disclaimer
34
-
35
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
37
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
38
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
39
- CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
40
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41
-
42
- This license is itself Kopimi. Copy it, use it, and remix it.
43
-
44
- For more information, please refer to <https://kopimi.com>
1
+ # Kopimi License
2
+
3
+ This software is released under the Kopimi License.
4
+
5
+ ## Permission
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
8
+ this software and associated documentation files (the "Software"), to copy,
9
+ modify, merge, publish, distribute, sublicense, sell, use, study,
10
+ reverse-engineer, decompile, and otherwise deal in the Software without
11
+ restriction, including without limitation for commercial or non-commercial
12
+ purposes.
13
+
14
+ Commercial use, sale, resale, or distribution for profit must include clear
15
+ attribution to the original author(s) in the distributed copy and in any
16
+ customary public-facing product notices, documentation, credits, or legal
17
+ notices associated with that use.
18
+
19
+ ## Kopimi Propagation
20
+
21
+ The Software is Kopimi. Copies, substantial portions, and derivative works must
22
+ preserve the freedom to copy, share, modify, remix, and redistribute the
23
+ Software. No copy, substantial portion, or derivative work may be distributed
24
+ under terms that prohibit those freedoms.
25
+
26
+ License notices, author notices, and Kopimi notices included with the Software
27
+ may not be removed from redistributed copies, substantial portions, or
28
+ derivative works.
29
+
30
+ Attribution to the original author(s) is appreciated for non-commercial use and
31
+ required for commercial use as described above.
32
+
33
+ ## Disclaimer
34
+
35
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
37
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
38
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
39
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
40
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41
+
42
+ This license is itself Kopimi. Copy it, use it, and remix it.
43
+
44
+ For more information, please refer to <https://kopimi.com>
package/README.md CHANGED
@@ -1,142 +1,142 @@
1
- # 🔥 fhirStarter
2
-
3
- SMART on FHIR Backend Services auth lifecycle for any FHIR client.
4
-
5
- ## Install
6
-
7
- ```sh
8
- npm install fhirstarterjs
9
- ```
10
-
11
- ## Usage
12
-
13
- This example uses the official `fhirclient` package as the FHIR client; `fhirStarter` only manages auth.
14
-
15
- ```ts
16
- import FHIR from "fhirclient"
17
- import fhirStarter from "fhirstarterjs"
18
-
19
- const auth = new fhirStarter({
20
- clientId: "your-client-id",
21
- privateKey: "./privatekey.pem",
22
- tokenEndpointUrl: "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token",
23
- scopes: ["system/Patient.rs", "system/Observation.rs"],
24
- })
25
-
26
- await auth.start()
27
-
28
- const client = FHIR.client({
29
- serverUrl: "https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4",
30
- tokenResponse: auth.tokenResponse(),
31
- })
32
-
33
- const bundle = await client.request("Patient?family=Smith")
34
- ```
35
-
36
- `auth.start()` fetches the first token and starts the proactive refresh loop. `auth.tokenResponse()` returns a live getter-backed object — `fhirclient` reads `access_token` dynamically per request, so it always picks up the latest token.
37
-
38
- `fhirStarter` does not fetch FHIR resources and does not bundle a FHIR client. It manages the auth lifecycle; the FHIR client does the rest.
39
-
40
- `privateKey` can be PEM text, a `Buffer` from `readFileSync`, or a path to a PKCS#8 PEM file.
41
-
42
- ## TypeScript types
43
-
44
- If needed, you can import the public types directly:
45
-
46
- ```ts
47
- import type { AuthConfig, JwkSet, LiveTokenResponse, Provider } from "fhirstarterjs"
48
- ```
49
-
50
- ## Other FHIR clients
51
-
52
- For clients with a bearer token setter (e.g. `fhir-kit-client`):
53
-
54
- ```ts
55
- const unsubscribe = auth.onRefresh((token) => {
56
- client.bearerToken = token
57
- })
58
- ```
59
-
60
- For raw `fetch` or any other HTTP client:
61
-
62
- ```ts
63
- const token = await auth.getAccessToken()
64
- const res = await fetch(url, {
65
- headers: { Authorization: `Bearer ${token}` },
66
- })
67
- ```
68
-
69
- ## API
70
-
71
- `new fhirStarter(config)`
72
-
73
- | Member | Returns | Description |
74
- |---|---|---|
75
- | `start()` | `Promise<void>` | Fetch first token and begin proactive refresh loop |
76
- | `stop()` | `void` | Clear the refresh timer |
77
- | `token` | `string \| null` | Current valid token, or null if expired |
78
- | `expiresIn` | `number \| null` | Seconds until actual expiry, or null |
79
- | `authorizationHeader` | `string \| null` | `Bearer <token>` or null |
80
- | `getAccessToken()` | `Promise<string>` | Async valid token with lazy refresh |
81
- | `tokenResponse()` | `LiveTokenResponse` | Getter-backed token response for `fhirclient` |
82
- | `onRefresh(callback)` | `() => void` | Subscribe to token updates — returns unsubscribe |
83
- | `getJwks()` | `Promise<JwkSet>` | Public JWKS derived from the private key |
84
- | `fhirStarter.thumbprint(privateKey)` | `string` | RFC 7638 JWK Thumbprint (base64url SHA-256) |
85
-
86
- `getJwks()` strips private key material — host the output JSON at your registered JWKS URL and pass that URL as `jwksUrl` so the JWT `jku` header is set automatically.
87
-
88
- ## Thumbprint
89
-
90
- Derive a deterministic `kid` from a private key without instantiating the class:
91
-
92
- ```ts
93
- import fhirStarter from "fhirstarterjs"
94
-
95
- const kid = fhirStarter.thumbprint("./privatekey.pem")
96
- console.log(kid) // base64url SHA-256 of the canonical RSA public JWK
97
- ```
98
-
99
- This implements RFC 7638 — the SHA-256 of the sorted canonical JWK members `{e, kty, n}`, base64url-encoded. Use it as the `keyId` when registering your JWKS.
100
-
101
- ## JWKS
102
-
103
- Some SMART Backend Services registrations require a public JWKS URL when using `jku`. Generate it from the same private key you use for auth:
104
-
105
- ```ts
106
- import { writeFileSync } from "node:fs"
107
- import fhirStarter from "fhirstarterjs"
108
-
109
- const auth = new fhirStarter({
110
- clientId: "your-client-id",
111
- privateKey: "./privatekey.pem",
112
- tokenEndpointUrl: "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token",
113
- scopes: ["system/Patient.rs"],
114
- keyId: "my-key-id",
115
- jwksUrl: "https://example.com/.well-known/jwks.json",
116
- })
117
-
118
- // No need to call auth.start() — getJwks() only needs the private key.
119
- const jwks = await auth.getJwks()
120
- writeFileSync("./jwks.json", JSON.stringify(jwks, null, 3))
121
- ```
122
-
123
- Host `jwks.json` at the exact URL you register with your authorization server, then pass that URL as `jwksUrl`. If you set `keyId`, the generated key includes `kid`, and signed JWTs use the same `kid` header.
124
-
125
- ## Compatibility
126
-
127
- `tokenResponse()` is designed for `fhirclient.request()`. If a client copies the token at construction time rather than reading it per-request, use `onRefresh()` to update or recreate that client instead. If `fhirclient` clears its internal state after a 401, recreate the client instance with `auth.tokenResponse()`.
128
-
129
- ## Scripts
130
-
131
- | Command | What |
132
- |---|---|
133
- | `npm run check` | `tsc --noEmit` |
134
- | `npm run build` | Compile to `dist/` |
135
-
136
- ## Notes
137
-
138
- - Call `auth.start()` to fetch the first token and begin the proactive refresh loop — call `auth.stop()` during shutdown in long-running processes
139
- - Tokens are cached with separate refresh and expiry timestamps — if a refresh fails but the token is not yet expired, the old token remains usable
140
- - Concurrent callers share a single in-flight token refresh
141
- - JWT assertions are signed RS384, expire after 5 minutes
142
- - Requires Node 20+, a PKCS#8 RSA key, and SMART Backend Services scopes
1
+ # 🔥 fhirStarter
2
+
3
+ SMART on FHIR Backend Services auth lifecycle for any FHIR client.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install fhirstarterjs
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ This example uses the official `fhirclient` package as the FHIR client; `fhirStarter` only manages auth.
14
+
15
+ ```ts
16
+ import FHIR from "fhirclient"
17
+ import fhirStarter from "fhirstarterjs"
18
+
19
+ const auth = new fhirStarter({
20
+ clientId: "your-client-id",
21
+ privateKey: "./privatekey.pem",
22
+ tokenEndpointUrl: "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token",
23
+ scopes: ["system/Patient.rs", "system/Observation.rs"],
24
+ })
25
+
26
+ await auth.start()
27
+
28
+ const client = FHIR.client({
29
+ serverUrl: "https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4",
30
+ tokenResponse: auth.tokenResponse(),
31
+ })
32
+
33
+ const bundle = await client.request("Patient?family=Smith")
34
+ ```
35
+
36
+ `auth.start()` fetches the first token and starts the proactive refresh loop. `auth.tokenResponse()` returns a live getter-backed object — `fhirclient` reads `access_token` dynamically per request, so it always picks up the latest token.
37
+
38
+ `fhirStarter` does not fetch FHIR resources and does not bundle a FHIR client. It manages the auth lifecycle; the FHIR client does the rest.
39
+
40
+ `privateKey` can be PEM text, a `Buffer` from `readFileSync`, or a path to a PKCS#8 PEM file.
41
+
42
+ ## TypeScript types
43
+
44
+ If needed, you can import the public types directly:
45
+
46
+ ```ts
47
+ import type { AuthConfig, JwkSet, LiveTokenResponse, Provider } from "fhirstarterjs"
48
+ ```
49
+
50
+ ## Other FHIR clients
51
+
52
+ For clients with a bearer token setter (e.g. `fhir-kit-client`):
53
+
54
+ ```ts
55
+ const unsubscribe = auth.onRefresh((token) => {
56
+ client.bearerToken = token
57
+ })
58
+ ```
59
+
60
+ For raw `fetch` or any other HTTP client:
61
+
62
+ ```ts
63
+ const token = await auth.getAccessToken()
64
+ const res = await fetch(url, {
65
+ headers: { Authorization: `Bearer ${token}` },
66
+ })
67
+ ```
68
+
69
+ ## API
70
+
71
+ `new fhirStarter(config)`
72
+
73
+ | Member | Returns | Description |
74
+ |---|---|---|
75
+ | `start()` | `Promise<void>` | Fetch first token and begin proactive refresh loop |
76
+ | `stop()` | `void` | Clear the refresh timer |
77
+ | `token` | `string \| null` | Current valid token, or null if expired |
78
+ | `expiresIn` | `number \| null` | Seconds until actual expiry, or null |
79
+ | `authorizationHeader` | `string \| null` | `Bearer <token>` or null |
80
+ | `getAccessToken()` | `Promise<string>` | Async valid token with lazy refresh |
81
+ | `tokenResponse()` | `LiveTokenResponse` | Getter-backed token response for `fhirclient` |
82
+ | `onRefresh(callback)` | `() => void` | Subscribe to token updates — returns unsubscribe |
83
+ | `getJwks()` | `Promise<JwkSet>` | Public JWKS derived from the private key |
84
+ | `fhirStarter.thumbprint(privateKey)` | `string` | RFC 7638 JWK Thumbprint (base64url SHA-256) |
85
+
86
+ `getJwks()` strips private key material — host the output JSON at your registered JWKS URL and pass that URL as `jwksUrl` so the JWT `jku` header is set automatically.
87
+
88
+ ## Thumbprint
89
+
90
+ Derive a deterministic `kid` from a private key without instantiating the class:
91
+
92
+ ```ts
93
+ import fhirStarter from "fhirstarterjs"
94
+
95
+ const kid = fhirStarter.thumbprint("./privatekey.pem")
96
+ console.log(kid) // base64url SHA-256 of the canonical RSA public JWK
97
+ ```
98
+
99
+ This implements RFC 7638 — the SHA-256 of the sorted canonical JWK members `{e, kty, n}`, base64url-encoded. Use it as the `keyId` when registering your JWKS.
100
+
101
+ ## JWKS
102
+
103
+ Some SMART Backend Services registrations require a public JWKS URL when using `jku`. Generate it from the same private key you use for auth:
104
+
105
+ ```ts
106
+ import { writeFileSync } from "node:fs"
107
+ import fhirStarter from "fhirstarterjs"
108
+
109
+ const auth = new fhirStarter({
110
+ clientId: "your-client-id",
111
+ privateKey: "./privatekey.pem",
112
+ tokenEndpointUrl: "https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token",
113
+ scopes: ["system/Patient.rs"],
114
+ keyId: "my-key-id",
115
+ jwksUrl: "https://example.com/.well-known/jwks.json",
116
+ })
117
+
118
+ // No need to call auth.start() — getJwks() only needs the private key.
119
+ const jwks = await auth.getJwks()
120
+ writeFileSync("./jwks.json", JSON.stringify(jwks, null, 3))
121
+ ```
122
+
123
+ Host `jwks.json` at the exact URL you register with your authorization server, then pass that URL as `jwksUrl`. If you set `keyId`, the generated key includes `kid`, and signed JWTs use the same `kid` header.
124
+
125
+ ## Compatibility
126
+
127
+ `tokenResponse()` is designed for `fhirclient.request()`. If a client copies the token at construction time rather than reading it per-request, use `onRefresh()` to update or recreate that client instead. If `fhirclient` clears its internal state after a 401, recreate the client instance with `auth.tokenResponse()`.
128
+
129
+ ## Scripts
130
+
131
+ | Command | What |
132
+ |---|---|
133
+ | `npm run check` | `tsc --noEmit` |
134
+ | `npm run build` | Compile to `dist/` |
135
+
136
+ ## Notes
137
+
138
+ - Call `auth.start()` to fetch the first token and begin the proactive refresh loop — call `auth.stop()` during shutdown in long-running processes
139
+ - Tokens are cached with separate refresh and expiry timestamps — if a refresh fails but the token is not yet expired, the old token remains usable
140
+ - Concurrent callers share a single in-flight token refresh
141
+ - JWT assertions are signed RS384, expire after 5 minutes
142
+ - Requires Node 20+, a PKCS#8 RSA key, and SMART Backend Services scopes
@@ -0,0 +1,81 @@
1
+ /**
2
+ * SMART Backend Services auth provider.
3
+ *
4
+ * Manages client-credentials token acquisition and proactive refresh
5
+ * using a private RSA key and the JWT Bearer client-assertion flow (RFC 7523).
6
+ */
7
+ export default class fhirStarter implements Provider {
8
+ private readonly config;
9
+ private readonly privateKeyText;
10
+ private readonly refreshCallbacks;
11
+ private cache;
12
+ private refreshPromise;
13
+ private refreshTimer;
14
+ private privateKeyObj;
15
+ private started;
16
+ private refreshFailed;
17
+ private refreshRetryMs;
18
+ /**
19
+ * @param config - Auth configuration including client ID, private key, token endpoint, and scopes.
20
+ * @throws If any required field is missing, blank, or invalid.
21
+ */
22
+ constructor(config: AuthConfig);
23
+ /** The current access token, or `null` if no valid token is cached. */
24
+ get token(): string | null;
25
+ /** Seconds until the cached token expires, or `null` if no valid token is cached. */
26
+ get expiresIn(): number | null;
27
+ /** Ready-to-use `Authorization` header value (e.g. `"Bearer <token>"`), or `null` if no valid token is cached. */
28
+ get authorizationHeader(): string | null;
29
+ /**
30
+ * Acquires an initial token and starts the proactive background refresh timer.
31
+ * Safe to call multiple times — subsequent calls are no-ops.
32
+ * @throws If the initial token acquisition fails.
33
+ */
34
+ start: () => Promise<void>;
35
+ /**
36
+ * Stops the background refresh timer.
37
+ * Any in-flight refresh will still complete, but no new timers will be scheduled.
38
+ */
39
+ stop: () => void;
40
+ /**
41
+ * Returns a live `LiveTokenResponse` object whose `access_token` and `expires_in`
42
+ * properties are always read from the current cache.
43
+ * Useful for libraries that hold a reference to a token response object.
44
+ */
45
+ tokenResponse: () => LiveTokenResponse;
46
+ /**
47
+ * Registers a callback that is invoked whenever a new access token is obtained.
48
+ * The callback is called immediately with the current token if one is already cached.
49
+ * @param callback - Receives the new access token string.
50
+ * @returns An unsubscribe function call it to stop receiving updates.
51
+ */
52
+ onRefresh: (callback: RefreshCallback) => (() => void);
53
+ /**
54
+ * Returns the public JWKS derived from the configured private key.
55
+ * Private key material (`d`, `p`, `q`, etc.) is stripped before returning.
56
+ */
57
+ getJwks: () => Promise<JwkSet>;
58
+ /**
59
+ * Returns a valid access token, refreshing if the cached token is at or past its refresh threshold.
60
+ * Falls back to a not-yet-expired stale token if the refresh request fails.
61
+ * @throws If no cached token is available and the refresh request fails.
62
+ */
63
+ getAccessToken: () => Promise<string>;
64
+ private doRefresh;
65
+ private scheduleRefresh;
66
+ private notifyRefresh;
67
+ private refreshAccessToken;
68
+ private getPrivateKey;
69
+ private buildJwt;
70
+ private static normalizeScopes;
71
+ private static resolvePrivateKey;
72
+ /**
73
+ * Derives a deterministic key identifier from a private key using an
74
+ * RFC 7638 JWK Thumbprint (SHA-256 of canonical RSA public JWK members, base64url).
75
+ *
76
+ * @param privateKey - RSA PKCS#8 PEM text, a Buffer, or a readable file path.
77
+ * @returns A base64url-encoded SHA-256 thumbprint string.
78
+ * @throws If the key is not RSA or cannot be parsed.
79
+ */
80
+ static thumbprint(privateKey: string | Buffer): string;
81
+ }
@@ -117,7 +117,7 @@ export default class fhirStarter {
117
117
  * Registers a callback that is invoked whenever a new access token is obtained.
118
118
  * The callback is called immediately with the current token if one is already cached.
119
119
  * @param callback - Receives the new access token string.
120
- * @returns An unsubscribe function; call it to stop receiving updates.
120
+ * @returns An unsubscribe function call it to stop receiving updates.
121
121
  */
122
122
  onRefresh = (callback) => {
123
123
  this.refreshCallbacks.add(callback);
@@ -138,14 +138,14 @@ export default class fhirStarter {
138
138
  */
139
139
  getJwks = async () => {
140
140
  const { keyId } = this.config, privateKey = await this.getPrivateKey(), jwk = await exportJWK(privateKey);
141
- // Public key only — strip private components
142
- (delete jwk.d,
143
- delete jwk.p,
144
- delete jwk.q,
145
- delete jwk.dp,
146
- delete jwk.dq,
147
- delete jwk.qi);
148
- ((jwk.alg = "RS384"), (jwk.use = "sig"));
141
+ delete jwk.d;
142
+ delete jwk.p;
143
+ delete jwk.q;
144
+ delete jwk.dp;
145
+ delete jwk.dq;
146
+ delete jwk.qi;
147
+ jwk.alg = "RS384";
148
+ jwk.use = "sig";
149
149
  if (keyId)
150
150
  jwk.kid = keyId;
151
151
  return { keys: [jwk] };
@@ -215,7 +215,7 @@ export default class fhirStarter {
215
215
  callback(token);
216
216
  }
217
217
  catch {
218
- // Ignore callback failures; auth lifecycle must continue.
218
+ // Ignore callback failures auth lifecycle must continue.
219
219
  }
220
220
  };
221
221
  refreshAccessToken = async () => {
@@ -314,3 +314,4 @@ export default class fhirStarter {
314
314
  return createHash("sha256").update(canonical).digest("base64url");
315
315
  }
316
316
  }
317
+ //# sourceMappingURL=fhirstarter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fhirstarter.js","sourceRoot":"","sources":["../ts/fhirstarter.ts"],"names":[],"mappings":"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"}