docpouch-client 1.0.1 → 1.0.4

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/dist/index.d.ts CHANGED
@@ -179,6 +179,15 @@ export default class docPouchClient {
179
179
  * @returns {void}
180
180
  */
181
181
  debugSocketConnection(): void;
182
+ /**
183
+ * Sets the OIDC configuration to use for the callback and token exchange.
184
+ * Call this before {@link handleOidcCallback} if the client was freshly
185
+ * instantiated after a page reload (the config is otherwise only set
186
+ * internally by {@link loginWithOidc} before the redirect).
187
+ *
188
+ * @param {I_OidcConfig} config - OIDC provider configuration.
189
+ */
190
+ setOidcConfig(config: I_OidcConfig): void;
182
191
  /**
183
192
  * Initiates the OIDC authentication flow by redirecting to the authorization endpoint.
184
193
  *
@@ -330,6 +339,7 @@ export interface I_OidcConfig {
330
339
  issuer: string;
331
340
  clientId: string;
332
341
  redirectUri: string;
342
+ scope?: string;
333
343
  scopes?: string[];
334
344
  clientSecret?: string;
335
345
  }
package/dist/index.js CHANGED
@@ -305,6 +305,17 @@ export default class docPouchClient {
305
305
  }
306
306
  }
307
307
  // OIDC Authentication Methods
308
+ /**
309
+ * Sets the OIDC configuration to use for the callback and token exchange.
310
+ * Call this before {@link handleOidcCallback} if the client was freshly
311
+ * instantiated after a page reload (the config is otherwise only set
312
+ * internally by {@link loginWithOidc} before the redirect).
313
+ *
314
+ * @param {I_OidcConfig} config - OIDC provider configuration.
315
+ */
316
+ setOidcConfig(config) {
317
+ this.oidcConfig = config;
318
+ }
308
319
  /**
309
320
  * Initiates the OIDC authentication flow by redirecting to the authorization endpoint.
310
321
  *
@@ -318,11 +329,19 @@ export default class docPouchClient {
318
329
  this.codeVerifier = this.generateCodeVerifier();
319
330
  this.oidcState = this.generateState();
320
331
  const codeChallenge = await this.generateCodeChallenge(this.codeVerifier);
332
+ if (typeof window !== 'undefined' && window.sessionStorage) {
333
+ sessionStorage.setItem('docpouch_oidc_state', this.oidcState);
334
+ sessionStorage.setItem('docpouch_oidc_code_verifier', this.codeVerifier);
335
+ sessionStorage.setItem('docpouch_oidc_issuer', config.issuer);
336
+ sessionStorage.setItem('docpouch_oidc_client_id', config.clientId);
337
+ sessionStorage.setItem('docpouch_oidc_redirect_uri', config.redirectUri);
338
+ }
339
+ const scope = config.scope || config.scopes?.join(' ') || 'openid profile';
321
340
  const params = new URLSearchParams({
322
341
  response_type: 'code',
323
342
  client_id: config.clientId,
324
343
  redirect_uri: config.redirectUri,
325
- scope: config.scopes?.join(' ') || 'openid profile',
344
+ scope,
326
345
  state: this.oidcState,
327
346
  code_challenge: codeChallenge,
328
347
  code_challenge_method: 'S256'
@@ -343,6 +362,23 @@ export default class docPouchClient {
343
362
  throw new Error(`OAuth error: ${error}`);
344
363
  if (!code || !state)
345
364
  return false;
365
+ if (typeof window !== 'undefined' && window.sessionStorage) {
366
+ this.oidcState = sessionStorage.getItem('docpouch_oidc_state') || this.oidcState;
367
+ this.codeVerifier = sessionStorage.getItem('docpouch_oidc_code_verifier') || this.codeVerifier;
368
+ sessionStorage.removeItem('docpouch_oidc_state');
369
+ sessionStorage.removeItem('docpouch_oidc_code_verifier');
370
+ if (!this.oidcConfig) {
371
+ const issuer = sessionStorage.getItem('docpouch_oidc_issuer');
372
+ const clientId = sessionStorage.getItem('docpouch_oidc_client_id');
373
+ const redirectUri = sessionStorage.getItem('docpouch_oidc_redirect_uri');
374
+ if (issuer && clientId && redirectUri) {
375
+ this.oidcConfig = { issuer, clientId, redirectUri };
376
+ sessionStorage.removeItem('docpouch_oidc_issuer');
377
+ sessionStorage.removeItem('docpouch_oidc_client_id');
378
+ sessionStorage.removeItem('docpouch_oidc_redirect_uri');
379
+ }
380
+ }
381
+ }
346
382
  if (state !== this.oidcState)
347
383
  throw new Error('State mismatch');
348
384
  const discovery = await this.discoverOidc();
@@ -441,6 +477,7 @@ export default class docPouchClient {
441
477
  * @returns {Promise<void>}
442
478
  */
443
479
  async logout() {
480
+ const wasOidc = this.authMethod === 'oidc';
444
481
  this.authToken = null;
445
482
  this.clearOidcTokens();
446
483
  this.authMethod = 'none';
@@ -450,6 +487,10 @@ export default class docPouchClient {
450
487
  (window.location.search.includes('code=') || window.location.search.includes('state='))) {
451
488
  window.history.replaceState({}, '', window.location.pathname);
452
489
  }
490
+ if (wasOidc && this.oidcConfig && typeof window !== 'undefined') {
491
+ const logoutUrl = `${this.oidcConfig.issuer}/session/end?post_logout_redirect_uri=${encodeURIComponent(this.oidcConfig.redirectUri)}`;
492
+ window.location.href = logoutUrl;
493
+ }
453
494
  }
454
495
  // OIDC Dynamic Client Registration Methods
455
496
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docpouch-client",
3
- "version": "1.0.1",
3
+ "version": "1.0.4",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
@@ -23,16 +23,16 @@
23
23
  "description": "Client SDK for DocPouch API - supports JWT and OIDC authentication",
24
24
  "repository": {
25
25
  "type": "git",
26
- "url": "https://github.com/BFH-JTF/docpouch-client"
26
+ "url": "git+https://github.com/BFH-JTF/docpouch-client.git"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/express": "^5.0.6",
30
30
  "@types/jest": "^30.0.0",
31
- "@types/node": "^25.7.0",
31
+ "@types/node": "^25.9.1",
32
32
  "express": "^5.2.1",
33
33
  "jest": "^30.4.2",
34
34
  "socket.io": "^4.8.3",
35
- "ts-jest": "^29.4.9",
35
+ "ts-jest": "^29.4.10",
36
36
  "typescript": "^6.0.3"
37
37
  },
38
38
  "dependencies": {
@@ -1,223 +0,0 @@
1
- Chat 'ChatTitle(text="I am adding authent…" with OpenCode, isCustom=true)' (09e440bd-c52c-44b9-bba4-01cebc84bd7b)
2
- Context:
3
-
4
- Messages: 18
5
- =================================================================================================================
6
-
7
- ==== RestoredMessage #1 ====
8
- User:
9
- I am adding authentication using node-oidcProvider to my app in addition to the already present localStorage solution. To give clients the possibility to register, is it enough to create a call to `this.expressApp.post` and get the necessary information from the client including some kind of secret?
10
- Attachments:
11
- Attachment Name: Console Selection
12
- Attachments Kind: Visible
13
- Attachments Source: Other / RestoredChatAttachment
14
- Attachments Text:
15
- this.expressApp.get
16
- Attachment Name: Console Selection
17
- Attachments Kind: Visible
18
- Attachments Source: Other / RestoredChatAttachment
19
- Attachments Text:
20
- validate
21
-
22
-
23
- kotlin.Unit
24
-
25
- ==== RestoredMessage #2 ====
26
- Assistant:
27
-
28
-
29
- kotlin.Unit
30
-
31
- ==== RestoredMessage #3 ====
32
- User:
33
- Yes, good idea
34
- Attachments:
35
- Attachment Name: Console Selection
36
- Attachments Kind: Visible
37
- Attachments Source: Other / RestoredChatAttachment
38
- Attachments Text:
39
- validate
40
-
41
-
42
- kotlin.Unit
43
-
44
- ==== RestoredMessage #4 ====
45
- Assistant:
46
-
47
-
48
- kotlin.Unit
49
-
50
- ==== RestoredMessage #5 ====
51
- User:
52
- 1. I want a controlled registration. I changed initialAccessToken to `process.env.OIDC_REGISTRATION_TOKEN`.
53
- 2. I don't even know what JWKS is, let alone have anything set up for it.
54
- Yes, please proceed
55
- Attachments:
56
- Attachment Name: Console Selection
57
- Attachments Kind: Visible
58
- Attachments Source: Other / RestoredChatAttachment
59
- Attachments Text:
60
- process.env.OIDC_REGISTRATION_TOKEN
61
- Attachment Name: Console Selection
62
- Attachments Kind: Visible
63
- Attachments Source: Other / RestoredChatAttachment
64
- Attachments Text:
65
- validate
66
-
67
-
68
- kotlin.Unit
69
-
70
- ==== RestoredMessage #6 ====
71
- Assistant:
72
-
73
-
74
- kotlin.Unit
75
-
76
- ==== RestoredMessage #7 ====
77
- User:
78
- Let's go with a static JWKS for starters. Yes, I would like the clients to have their choice, whether they want to use the localStorage or the OIDC approach for authentication. For both, the clients are expected to build their own login masks.
79
- If the registration token is not just a random string, I need help, yes.
80
- Attachments:
81
- Attachment Name: Console Selection
82
- Attachments Kind: Visible
83
- Attachments Source: Other / RestoredChatAttachment
84
- Attachments Text:
85
- process.env.OIDC_REGISTRATION_TOKEN
86
- Attachment Name: Console Selection
87
- Attachments Kind: Visible
88
- Attachments Source: Other / RestoredChatAttachment
89
- Attachments Text:
90
- validate
91
-
92
-
93
- kotlin.Unit
94
-
95
- ==== RestoredMessage #8 ====
96
- Assistant:
97
-
98
-
99
- kotlin.Unit
100
-
101
- ==== RestoredMessage #9 ====
102
- User:
103
- I am unsure,now. If I give clients these options for auth, is it easier for them, than having to build their own login mask?
104
- 1. The old approach using the token in localStorage.
105
- 2. OIDC and they can use a login mask provided by docPouch.
106
- Attachments:
107
- Attachment Name: Console Selection
108
- Attachments Kind: Visible
109
- Attachments Source: Other / RestoredChatAttachment
110
- Attachments Text:
111
- process.env.OIDC_REGISTRATION_TOKEN
112
- Attachment Name: Console Selection
113
- Attachments Kind: Visible
114
- Attachments Source: Other / RestoredChatAttachment
115
- Attachments Text:
116
- validate
117
- Attachment Name: Console Selection
118
- Attachments Kind: Visible
119
- Attachments Source: Other / RestoredChatAttachment
120
- Attachments Text:
121
- JWT_SECRET=your-secure-jwt-secret-here
122
- Attachment Name: Console Selection
123
- Attachments Kind: Visible
124
- Attachments Source: Other / RestoredChatAttachment
125
- Attachments Text:
126
- NODE_ENV
127
-
128
-
129
- kotlin.Unit
130
-
131
- ==== RestoredMessage #10 ====
132
- Assistant:
133
-
134
-
135
- kotlin.Unit
136
-
137
- ==== RestoredMessage #11 ====
138
- User:
139
- I want to offer both choices and build a server-side login page.
140
- Attachments:
141
- Attachment Name: Console Selection
142
- Attachments Kind: Visible
143
- Attachments Source: Other / RestoredChatAttachment
144
- Attachments Text:
145
- process.env.OIDC_REGISTRATION_TOKEN
146
- Attachment Name: Console Selection
147
- Attachments Kind: Visible
148
- Attachments Source: Other / RestoredChatAttachment
149
- Attachments Text:
150
- validate
151
- Attachment Name: Console Selection
152
- Attachments Kind: Visible
153
- Attachments Source: Other / RestoredChatAttachment
154
- Attachments Text:
155
- JWT_SECRET=your-secure-jwt-secret-here
156
- Attachment Name: Console Selection
157
- Attachments Kind: Visible
158
- Attachments Source: Other / RestoredChatAttachment
159
- Attachments Text:
160
- NODE_ENV
161
-
162
-
163
- kotlin.Unit
164
-
165
- ==== RestoredMessage #12 ====
166
- Assistant:
167
-
168
-
169
- kotlin.Unit
170
-
171
- ==== RestoredMessage #13 ====
172
- User:
173
- Do I need to update the express routes, so that they are able to validate users using both approaches?
174
- Attachments:
175
- Attachment Name: Console Selection
176
- Attachments Kind: Visible
177
- Attachments Source: Other / RestoredChatAttachment
178
- Attachments Text:
179
- JWT_SECRET=your-secure-jwt-secret-here
180
-
181
-
182
- kotlin.Unit
183
-
184
- ==== RestoredMessage #14 ====
185
- Assistant:
186
-
187
-
188
- kotlin.Unit
189
-
190
- ==== RestoredMessage #15 ====
191
- User:
192
- I am importing interfaces from the docPouch client I have written. I assume I will have to update some of those, as well, when I update the docPouch client, correct?
193
- Attachments:
194
- Attachment Name: Console Selection
195
- Attachments Kind: Visible
196
- Attachments Source: Other / RestoredChatAttachment
197
- Attachments Text:
198
- JWT_SECRET=your-secure-jwt-secret-here
199
-
200
-
201
- kotlin.Unit
202
-
203
- ==== RestoredMessage #16 ====
204
- Assistant:
205
-
206
-
207
- kotlin.Unit
208
-
209
- ==== UserMessageImpl #17 ====
210
- User:
211
- Yes, I would like to go for Option A and the client should offer different methods for the different auth methods and thus explicitly choose. Please make a detailed plan for yourself, so when I load up my docpouch-client project and give you this instruction, you know exactly what to do.
212
-
213
- kotlin.Unit
214
-
215
- ==== AgentMessage #18 ====
216
- Assistant:
217
-
218
-
219
- Tool use list:
220
-
221
-
222
- kotlin.Unit
223
-
package/jest.config.cjs DELETED
@@ -1,18 +0,0 @@
1
- module.exports = {
2
- preset: 'ts-jest',
3
- testEnvironment: 'node',
4
- moduleNameMapper: {
5
- '^(\\.{1,2}/.*)\\.js$': '$1',
6
- },
7
- transform: {
8
- '^.+\\.tsx?$': ['ts-jest', {
9
- useESM: true,
10
- }],
11
- },
12
- extensionsToTreatAsEsm: ['.ts'],
13
- moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
14
- testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)', 'tests/**/*.test.ts'],
15
- collectCoverage: true,
16
- coverageDirectory: 'coverage',
17
- coverageReporters: ['text', 'lcov'],
18
- };