@muze-nl/metro-oidc 0.9.2 → 0.9.3

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/docs/reference.md CHANGED
@@ -109,3 +109,7 @@ import oidcmockserver from '@muze-nl/metro-oidc/testing'
109
109
  ```
110
110
 
111
111
  The mock server exposes discovery metadata, dynamic client registration, JWKS, signed ID tokens, userinfo, and OAuth2-backed protected-resource behaviour for tests.
112
+
113
+ The middleware captures the token request grant type before sending the request.
114
+ ID-token validation and refresh handling therefore work with transports that
115
+ consume request bodies; callers do not need to buffer or replay token POSTs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muze-nl/metro-oidc",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "oidc client middleware for @muze-nl/metro",
5
5
  "type": "module",
6
6
  "source": [
package/src/oidcmw.mjs CHANGED
@@ -189,26 +189,27 @@ export default function oidcmw(options={}) {
189
189
  )
190
190
 
191
191
  const storeIdToken = async (req, next) => {
192
- const res = await next(req)
193
192
  const tokenEndpoint = metro.url(options.openid_configuration.token_endpoint, { hash: '' }).href
194
193
  const requestUrl = metro.url(req.url, { hash: '' }).href
195
194
  if (requestUrl !== tokenEndpoint) {
196
- return res
195
+ return next(req)
197
196
  }
197
+ // Fetch consumes the outgoing body; inspect the grant before dispatch.
198
+ const isRefresh = await grantTypeOf(req) == 'refresh_token'
199
+ const res = await next(req)
198
200
  const contentType = res.headers.get('content-type')
199
201
  if (!res.ok || !contentType?.startsWith('application/json')) {
200
202
  // oauth2mw reports the token endpoint's own error
201
203
  return res
202
204
  }
203
205
 
204
- let data = res.data && typeof res.data === 'object' ? res.data : null
205
- if (!data) {
206
+ let data = res.data
207
+ if (!data || typeof data !== 'object' || data instanceof ReadableStream) {
206
208
  const res2 = res.clone() // otherwise res.body can't be read again
207
209
  data = await res2.json()
208
210
  }
209
211
 
210
212
  const id_token = data?.id_token
211
- const isRefresh = await grantTypeOf(req) == 'refresh_token'
212
213
  if (isRefresh && !id_token) {
213
214
  // a refresh response may omit the id_token; the stored one stays
214
215
  return res