@muze-nl/metro-oidc 0.2.0 → 0.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muze-nl/metro-oidc",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "oidc client middleware for @muze-nl/metro",
5
5
  "type": "module",
6
6
  "source": [
@@ -48,7 +48,7 @@
48
48
  ],
49
49
  "dependencies": {
50
50
  "@muze-nl/assert": "^0.3.3",
51
- "@muze-nl/metro": "^0.5.5",
52
- "@muze-nl/metro-oauth2": "^0.4.0"
51
+ "@muze-nl/metro": "^0.6.1",
52
+ "@muze-nl/metro-oauth2": "^0.5.1"
53
53
  }
54
54
  }
package/src/browser.mjs CHANGED
@@ -1,12 +1,19 @@
1
+ import metro from '@muze-nl/metro'
2
+ import oauth2 from '@muze-nl/metro-oauth2'
1
3
  import oidcDiscover from './oidc.discovery.mjs'
2
4
  import oidcRegister from './oidc.register.mjs'
3
5
  import oidcmw, {isRedirected, idToken} from './oidcmw.mjs'
4
6
 
5
- export const oidc = Object.assign(oidcmw, {
7
+ const oidc = {
8
+ oidcmw,
6
9
  discover: oidcDiscover,
7
10
  register: oidcRegister,
8
11
  isRedirected,
9
12
  idToken
10
- })
13
+ }
11
14
 
12
- globalThis.oidc = oidc
15
+ if (!globalThis.metro.oidc) {
16
+ globalThis.metro.oidc = oidc
17
+ }
18
+
19
+ export default oidc
@@ -89,7 +89,7 @@ export default async function oidcDiscovery(options={}) {
89
89
  // note: this allows path components in the options.issuer url
90
90
  configURL
91
91
  )
92
- const openid_config = response.body[Symbol.metroSource]
92
+ const openid_config = response.data
93
93
  assert(openid_config, openid_provider_metadata)
94
94
 
95
95
  // https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation
@@ -63,7 +63,7 @@ export default async function register(options)
63
63
  .post(options.registration_endpoint, {
64
64
  body: options.client_info
65
65
  })
66
- let info = response.body
66
+ let info = response.data
67
67
  if (!info.client_id || !info.client_secret) {
68
68
  throw metro.metroError('metro.oidc: Error: dynamic registration of client failed, no client_id or client_secret returned', response)
69
69
  }
package/src/oidcmw.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import metro from '@muze-nl/metro'
2
- import oauth2 from '@muze-nl/metro-oauth2'
1
+ import * as metro from '@muze-nl/metro/src/metro.mjs'
2
+ import oauth2mw, * as oauth2 from '@muze-nl/metro-oauth2/src/oauth2.mjs'
3
+ import dpopmw from '@muze-nl/metro-oauth2/src/oauth2.dpop.mjs'
3
4
  import { assert, Required, Optional, validURL, instanceOf } from '@muze-nl/assert'
4
5
  import discover from './oidc.discovery.mjs'
5
6
  import register from './oidc.register.mjs'
@@ -9,7 +10,14 @@ export default function oidcmw(options={}) {
9
10
 
10
11
  const defaultOptions = {
11
12
  client: metro.client(),
12
- force_authorization: false
13
+ force_authorization: false,
14
+ use_dpop: true,
15
+ authorize_callback: async url => {
16
+ if (window.location.href != url.href) {
17
+ window.location.replace(url.href)
18
+ }
19
+ return false
20
+ }
13
21
  }
14
22
 
15
23
  options = Object.assign({}, defaultOptions, options)
@@ -73,6 +81,7 @@ export default function oidcmw(options={}) {
73
81
  site: options.issuer,
74
82
  client: options.client,
75
83
  force_authorization: true,
84
+ authorize_callback: options.authorize_callback,
76
85
  oauth2_configuration: {
77
86
  client_id: options.client_info.client_id,
78
87
  client_secret: options.client_info.client_secret,
@@ -88,42 +97,46 @@ export default function oidcmw(options={}) {
88
97
  //...
89
98
  )
90
99
 
91
- const dpopOptions = {
92
- site: options.issuer,
93
- authorization_endpoint: options.openid_configuration.authorization_endpoint,
94
- token_endpoint: options.openid_configuration.token_endpoint,
95
- dpop_signing_alg_values_supported: options.openid_configuration.dpop_signing_alg_values_supported
96
- }
97
-
98
100
  const storeIdToken = async (req, next) => {
99
101
  const res = await next(req)
100
102
  const contentType = res.headers.get('content-type')
101
103
  if (contentType?.startsWith('application/json')) {
102
- const res2 = res.clone() // otherwise res.body can't be read again
103
- try {
104
- let data = await res2.json()
105
- if (data && data.id_token) {
106
- options.store.set('id_token', data.id_token)
104
+ //FIXME: check that this is actually the token endpoint
105
+ let id_token = res.data?.id_token
106
+ if (!id_token) {
107
+ const res2 = res.clone() // otherwise res.body can't be read again
108
+ try {
109
+ let data = await res2.json()
110
+ if (data && data.id_token) {
111
+ id_token = data.id_token
112
+ }
113
+ } catch(e) {
114
+ // ignore errors
107
115
  }
108
- } catch(e) {
109
- // ignore errors
116
+ }
117
+ if (id_token) {
118
+ options.store.set('id_token', id_token)
110
119
  }
111
120
  }
112
121
  return res
113
122
  }
114
123
 
115
- const dPopClient = options.client
116
- .with(options.issuer)
117
- .with(storeIdToken)
118
- .with(oauth2.dpopmw(dpopOptions))
124
+ let oauth2client = options.client.with(options.issuer).with(storeIdToken)
119
125
 
120
- oauth2Options.client = dPopClient
126
+ if (options.use_dpop) {
127
+ const dpopOptions = {
128
+ site: options.issuer,
129
+ authorization_endpoint: options.openid_configuration.authorization_endpoint,
130
+ token_endpoint: options.openid_configuration.token_endpoint,
131
+ dpop_signing_alg_values_supported: options.openid_configuration.dpop_signing_alg_values_supported
132
+ }
133
+ oauth2client = oauth2client.with(dpopmw(dpopOptions)) // add DPoP headers in requests with Authorization headers
134
+ oauth2Options.client = oauth2client // make sure oath2 token request use dpop
135
+ }
121
136
 
122
- const oauth2client = dPopClient
123
- .with(oauth2(oauth2Options))
137
+ oauth2client = oauth2client.with(oauth2mw(oauth2Options))
124
138
 
125
139
  res = await oauth2client.fetch(req)
126
- // ...
127
140
 
128
141
  return res
129
142
  }
@@ -136,4 +149,8 @@ export function isRedirected() {
136
149
 
137
150
  export function idToken(options) {
138
151
  return options.store.get('id_token')
139
- }
152
+ }
153
+
154
+ export async function authorizePopup(authorizationCodeURL) {
155
+ return oauth2.authorizePopup(authorizationCodeURL)
156
+ }