@openeo/js-client 2.9.0 → 2.11.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.
- package/README.md +2 -2
- package/openeo.d.ts +90 -2
- package/openeo.js +8011 -7814
- package/openeo.min.js +1 -1
- package/package.json +5 -5
- package/src/authprovider.js +22 -4
- package/src/connection.js +1 -1
- package/src/oidcprovider.js +192 -4
- package/src/openeo.js +1 -1
package/src/authprovider.js
CHANGED
|
@@ -88,15 +88,23 @@ class AuthProvider {
|
|
|
88
88
|
*
|
|
89
89
|
* Returns `null` if no access token has been set yet (i.e. not authenticated any longer).
|
|
90
90
|
*
|
|
91
|
+
* Checks whether the server supports the JWT conformance class.
|
|
92
|
+
*
|
|
91
93
|
* @returns {string | null}
|
|
92
94
|
*/
|
|
93
95
|
getToken() {
|
|
96
|
+
//check conformance
|
|
97
|
+
const isJWT = this.connection.capabilities().hasConformance(
|
|
98
|
+
"https://api.openeo.org/*/authentication/jwt"
|
|
99
|
+
);
|
|
94
100
|
if (typeof this.token === 'string') {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
if(isJWT) {
|
|
102
|
+
return this.token; // JWT since API v1.3.0
|
|
103
|
+
} else {
|
|
104
|
+
return this.getType() + "/" + this.getProviderId() + "/" + this.token; // legacy
|
|
105
|
+
}
|
|
99
106
|
}
|
|
107
|
+
return null;
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
/**
|
|
@@ -119,6 +127,16 @@ class AuthProvider {
|
|
|
119
127
|
}
|
|
120
128
|
}
|
|
121
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Tries to resume an existing session.
|
|
132
|
+
*
|
|
133
|
+
* @param {...any} args
|
|
134
|
+
* @returns {boolean} `true` if the session could be resumed, `false` otherwise
|
|
135
|
+
*/
|
|
136
|
+
async resume(...args) { // eslint-disable-line no-unused-vars
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
122
140
|
/**
|
|
123
141
|
* Abstract method that extending classes implement the login process with.
|
|
124
142
|
*
|
package/src/connection.js
CHANGED
|
@@ -745,7 +745,7 @@ class Connection {
|
|
|
745
745
|
const response = await this._post('/validation', this._normalizeUserProcess(process).process);
|
|
746
746
|
if (Array.isArray(response.data.errors)) {
|
|
747
747
|
const errors = response.data.errors;
|
|
748
|
-
errors['federation:backends'] = Array.isArray(response.data['federation:
|
|
748
|
+
errors['federation:backends'] = Array.isArray(response.data['federation:backends']) ? response.data['federation:backends'] : [];
|
|
749
749
|
return errors;
|
|
750
750
|
}
|
|
751
751
|
else {
|
package/src/oidcprovider.js
CHANGED
|
@@ -53,6 +53,7 @@ class OidcProvider extends AuthProvider {
|
|
|
53
53
|
}
|
|
54
54
|
let providerOptions = provider.getOptions(options);
|
|
55
55
|
let oidc = new Oidc.UserManager(providerOptions);
|
|
56
|
+
await oidc.clearStaleState();
|
|
56
57
|
return await oidc.signinCallback(url);
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -82,10 +83,19 @@ class OidcProvider extends AuthProvider {
|
|
|
82
83
|
*/
|
|
83
84
|
this.clientId = null;
|
|
84
85
|
|
|
86
|
+
/**
|
|
87
|
+
* The client secret to use for authentication.
|
|
88
|
+
*
|
|
89
|
+
* Only used for the `client_credentials` grant type.
|
|
90
|
+
*
|
|
91
|
+
* @type {string | null}
|
|
92
|
+
*/
|
|
93
|
+
this.clientSecret = null;
|
|
94
|
+
|
|
85
95
|
/**
|
|
86
96
|
* The grant type (flow) to use for this provider.
|
|
87
97
|
*
|
|
88
|
-
* Either "authorization_code+pkce" (default) or "
|
|
98
|
+
* Either "authorization_code+pkce" (default), "implicit" or "client_credentials"
|
|
89
99
|
*
|
|
90
100
|
* @type {string}
|
|
91
101
|
*/
|
|
@@ -127,12 +137,29 @@ class OidcProvider extends AuthProvider {
|
|
|
127
137
|
*/
|
|
128
138
|
this.defaultClients = Array.isArray(options.default_clients) ? options.default_clients : [];
|
|
129
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Additional parameters to include in authorization requests.
|
|
142
|
+
*
|
|
143
|
+
* As defined by the API, these parameters MUST be included when
|
|
144
|
+
* requesting the authorization endpoint.
|
|
145
|
+
*
|
|
146
|
+
* @type {object.<string, *>}
|
|
147
|
+
*/
|
|
148
|
+
this.authorizationParameters = Utils.isObject(options.authorization_parameters) ? options.authorization_parameters : {};
|
|
149
|
+
|
|
130
150
|
/**
|
|
131
151
|
* The detected default Client.
|
|
132
152
|
*
|
|
133
153
|
* @type {OidcClient}
|
|
134
154
|
*/
|
|
135
155
|
this.defaultClient = this.detectDefaultClient();
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The cached OpenID Connect well-known configuration document.
|
|
159
|
+
*
|
|
160
|
+
* @type {object.<string, *> | null}
|
|
161
|
+
*/
|
|
162
|
+
this.wellKnownDocument = null;
|
|
136
163
|
}
|
|
137
164
|
|
|
138
165
|
/**
|
|
@@ -166,7 +193,8 @@ class OidcProvider extends AuthProvider {
|
|
|
166
193
|
/**
|
|
167
194
|
* Authenticate with OpenID Connect (OIDC).
|
|
168
195
|
*
|
|
169
|
-
* Supported
|
|
196
|
+
* Supported in Browser environments for `authorization_code+pkce` and `implicit` grants.
|
|
197
|
+
* The `client_credentials` grant is supported in all environments.
|
|
170
198
|
*
|
|
171
199
|
* @async
|
|
172
200
|
* @param {object.<string, *>} [options={}] - Object with authentication options.
|
|
@@ -181,6 +209,10 @@ class OidcProvider extends AuthProvider {
|
|
|
181
209
|
throw new Error("No Issuer URL available for OpenID Connect");
|
|
182
210
|
}
|
|
183
211
|
|
|
212
|
+
if (this.grant === 'client_credentials') {
|
|
213
|
+
return await this.loginClientCredentials();
|
|
214
|
+
}
|
|
215
|
+
|
|
184
216
|
this.manager = new Oidc.UserManager(this.getOptions(options, requestRefreshToken));
|
|
185
217
|
this.addListener('UserLoaded', async () => this.setUser(await this.manager.getUser()), 'js-client');
|
|
186
218
|
this.addListener('AccessTokenExpired', () => this.setUser(null), 'js-client');
|
|
@@ -192,12 +224,143 @@ class OidcProvider extends AuthProvider {
|
|
|
192
224
|
}
|
|
193
225
|
}
|
|
194
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Authenticate using the OIDC Client Credentials grant.
|
|
229
|
+
*
|
|
230
|
+
* Requires `clientId` and `clientSecret` to be set.
|
|
231
|
+
* This flow does not use the oidc-client library and works in all environments.
|
|
232
|
+
*
|
|
233
|
+
* @async
|
|
234
|
+
* @protected
|
|
235
|
+
* @returns {Promise<void>}
|
|
236
|
+
* @throws {Error}
|
|
237
|
+
*/
|
|
238
|
+
async loginClientCredentials() {
|
|
239
|
+
if (!this.clientId || !this.clientSecret) {
|
|
240
|
+
throw new Error("Client ID and Client Secret are required for the client credentials flow");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let tokenEndpoint = await this.getTokenEndpoint();
|
|
244
|
+
|
|
245
|
+
let params = new URLSearchParams();
|
|
246
|
+
params.append('grant_type', 'client_credentials');
|
|
247
|
+
params.append('client_id', this.clientId);
|
|
248
|
+
params.append('client_secret', this.clientSecret);
|
|
249
|
+
params.append('scope', this.scopes.join(' '));
|
|
250
|
+
|
|
251
|
+
let response = await Environment.axios.post(tokenEndpoint, params.toString(), {
|
|
252
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
let data = response.data;
|
|
256
|
+
let user = new Oidc.User({
|
|
257
|
+
access_token: data.access_token,
|
|
258
|
+
token_type: data.token_type || 'Bearer',
|
|
259
|
+
scope: data.scope || this.scopes.join(' '),
|
|
260
|
+
expires_at: data.expires_in ? Math.floor(Date.now() / 1000) + data.expires_in : undefined,
|
|
261
|
+
profile: {}
|
|
262
|
+
});
|
|
263
|
+
this.setUser(user);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Retrieves the OpenID Connect well-known configuration document.
|
|
268
|
+
*
|
|
269
|
+
* @async
|
|
270
|
+
* @returns {Promise<object.<str, *>> | null} The well-known configuration document, or `null` if the issuer URL is not set.
|
|
271
|
+
*/
|
|
272
|
+
async getWellKnownDocument() {
|
|
273
|
+
if (!this.issuer || typeof this.issuer !== 'string') {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
if (this.wellKnownDocument === null) {
|
|
277
|
+
const authority = this.issuer.replace('/.well-known/openid-configuration', '');
|
|
278
|
+
const discoveryUrl = authority + '/.well-known/openid-configuration';
|
|
279
|
+
const response = await Environment.axios.get(discoveryUrl);
|
|
280
|
+
this.wellKnownDocument = response.data;
|
|
281
|
+
}
|
|
282
|
+
return this.wellKnownDocument;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Discovers the token endpoint from the OpenID Connect issuer.
|
|
287
|
+
*
|
|
288
|
+
* @async
|
|
289
|
+
* @protected
|
|
290
|
+
* @returns {Promise<string>} The token endpoint URL.
|
|
291
|
+
* @throws {Error}
|
|
292
|
+
*/
|
|
293
|
+
async getTokenEndpoint() {
|
|
294
|
+
const wellKnown = await this.getWellKnownDocument();
|
|
295
|
+
if (!Utils.isObject(wellKnown) || !wellKnown.token_endpoint) {
|
|
296
|
+
throw new Error("Unable to discover token endpoint from issuer");
|
|
297
|
+
}
|
|
298
|
+
return wellKnown.token_endpoint;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Checks whether the OpenID Connect provider supports the Client Credentials grant.
|
|
303
|
+
*
|
|
304
|
+
* @async
|
|
305
|
+
* @returns {Promise<boolean|null>} `true` if the Client Credentials grant is supported, `false` otherwise. `null` if unknown.
|
|
306
|
+
*/
|
|
307
|
+
async supportsClientCredentials() {
|
|
308
|
+
try {
|
|
309
|
+
const wellKnown = await this.getWellKnownDocument();
|
|
310
|
+
if (!Utils.isObject(wellKnown) || !Array.isArray(wellKnown.grant_types_supported)) {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
return wellKnown.grant_types_supported.includes('client_credentials');
|
|
314
|
+
} catch (error) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Restores a previously established OIDC session from storage.
|
|
321
|
+
*
|
|
322
|
+
* Not supported for the `client_credentials` grant as credentials
|
|
323
|
+
* are not persisted. Use `login()` to re-authenticate instead.
|
|
324
|
+
*
|
|
325
|
+
* @async
|
|
326
|
+
* @param {object.<string, *>} [options={}] - Additional options passed to the OIDC UserManager.
|
|
327
|
+
* @returns {Promise<boolean>} `true` if the session could be resumed, `false` otherwise.
|
|
328
|
+
* @see https://github.com/IdentityModel/oidc-client-js/wiki#usermanager
|
|
329
|
+
*/
|
|
330
|
+
async resume(options = {}) {
|
|
331
|
+
if (this.grant === 'client_credentials') {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
this.manager = new Oidc.UserManager(this.getOptions(options));
|
|
336
|
+
this.addListener('UserLoaded', async () => this.setUser(await this.manager.getUser()), 'js-client');
|
|
337
|
+
this.addListener('AccessTokenExpired', () => this.setUser(null), 'js-client');
|
|
338
|
+
|
|
339
|
+
let user = await this.manager.getUser();
|
|
340
|
+
if (user && user.expired && user.refresh_token) {
|
|
341
|
+
user = await this.manager.signinSilent();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (user && !user.expired) {
|
|
345
|
+
this.setUser(user);
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
|
|
195
352
|
/**
|
|
196
353
|
* Logout from the established session.
|
|
197
354
|
*
|
|
198
355
|
* @async
|
|
199
356
|
*/
|
|
200
357
|
async logout() {
|
|
358
|
+
if (this.grant === 'client_credentials') {
|
|
359
|
+
super.logout();
|
|
360
|
+
this.setUser(null);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
201
364
|
if (this.manager !== null) {
|
|
202
365
|
try {
|
|
203
366
|
if (OidcProvider.uiMethod === 'popup') {
|
|
@@ -244,7 +407,8 @@ class OidcProvider extends AuthProvider {
|
|
|
244
407
|
scope: scope.join(' '),
|
|
245
408
|
validateSubOnSilentRenew: true,
|
|
246
409
|
response_type,
|
|
247
|
-
response_mode: response_type.includes('code') ? 'query' : 'fragment'
|
|
410
|
+
response_mode: response_type.includes('code') ? 'query' : 'fragment',
|
|
411
|
+
extraQueryParams: this.authorizationParameters
|
|
248
412
|
}, options);
|
|
249
413
|
}
|
|
250
414
|
|
|
@@ -261,6 +425,8 @@ class OidcProvider extends AuthProvider {
|
|
|
261
425
|
return 'code';
|
|
262
426
|
case 'implicit':
|
|
263
427
|
return 'token id_token';
|
|
428
|
+
case 'client_credentials':
|
|
429
|
+
return null;
|
|
264
430
|
default:
|
|
265
431
|
throw new Error('Grant Type not supported');
|
|
266
432
|
}
|
|
@@ -276,6 +442,7 @@ class OidcProvider extends AuthProvider {
|
|
|
276
442
|
switch(grant) {
|
|
277
443
|
case 'authorization_code+pkce':
|
|
278
444
|
case 'implicit':
|
|
445
|
+
case 'client_credentials':
|
|
279
446
|
this.grant = grant;
|
|
280
447
|
break;
|
|
281
448
|
default:
|
|
@@ -294,6 +461,17 @@ class OidcProvider extends AuthProvider {
|
|
|
294
461
|
this.clientId = clientId;
|
|
295
462
|
}
|
|
296
463
|
|
|
464
|
+
/**
|
|
465
|
+
* Sets the Client Secret for OIDC authentication.
|
|
466
|
+
*
|
|
467
|
+
* Only used for the `client_credentials` grant type.
|
|
468
|
+
*
|
|
469
|
+
* @param {string | null} clientSecret
|
|
470
|
+
*/
|
|
471
|
+
setClientSecret(clientSecret) {
|
|
472
|
+
this.clientSecret = clientSecret;
|
|
473
|
+
}
|
|
474
|
+
|
|
297
475
|
/**
|
|
298
476
|
* Sets the OIDC User.
|
|
299
477
|
*
|
|
@@ -314,12 +492,21 @@ class OidcProvider extends AuthProvider {
|
|
|
314
492
|
/**
|
|
315
493
|
* Returns a display name for the authenticated user.
|
|
316
494
|
*
|
|
495
|
+
* For the `client_credentials` grant, returns a name based on the client ID.
|
|
496
|
+
*
|
|
317
497
|
* @returns {string?} Name of the user or `null`
|
|
318
498
|
*/
|
|
319
499
|
getDisplayName() {
|
|
320
500
|
if (this.user && Utils.isObject(this.user.profile)) {
|
|
321
501
|
return this.user.profile.name || this.user.profile.preferred_username || this.user.profile.email || null;
|
|
322
502
|
}
|
|
503
|
+
if (this.grant === 'client_credentials' && this.clientId) {
|
|
504
|
+
let id = this.clientId;
|
|
505
|
+
if (id.length > 15) {
|
|
506
|
+
id = id.slice(0, 5) + '\u2026' + id.slice(-5);
|
|
507
|
+
}
|
|
508
|
+
return `Client ${id}`;
|
|
509
|
+
}
|
|
323
510
|
return null;
|
|
324
511
|
}
|
|
325
512
|
|
|
@@ -381,7 +568,8 @@ OidcProvider.redirectUrl = Environment.getUrl().split('#')[0].split('?')[0].repl
|
|
|
381
568
|
*/
|
|
382
569
|
OidcProvider.grants = [
|
|
383
570
|
'authorization_code+pkce',
|
|
384
|
-
'implicit'
|
|
571
|
+
'implicit',
|
|
572
|
+
'client_credentials'
|
|
385
573
|
];
|
|
386
574
|
|
|
387
575
|
module.exports = OidcProvider;
|