@opengeoweb/authentication 19.6.1 → 20.0.0-nightly-20260919

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.esm.js CHANGED
@@ -641,6 +641,7 @@ var authConfigKeys = {
641
641
  GW_AUTH_CLIENT_ID: null,
642
642
  GW_AUTH_ROLE_CLAIM_NAME: null,
643
643
  GW_AUTH_ROLE_CLAIM_VALUE_PRESETS_ADMIN: null,
644
+ GW_AUTH_TRUSTED_HOSTS: null,
644
645
  GW_FEATURE_SILENT_LOGIN: false,
645
646
  GW_FEATURE_FORCE_AUTHENTICATION: false
646
647
  };
@@ -684,6 +685,7 @@ var getAuthConfig = function getAuthConfig(_configUrls) {
684
685
  GW_AUTH_CLIENT_ID = _configUrls.GW_AUTH_CLIENT_ID,
685
686
  GW_AUTH_ROLE_CLAIM_NAME = _configUrls.GW_AUTH_ROLE_CLAIM_NAME,
686
687
  GW_AUTH_ROLE_CLAIM_VALUE_PRESETS_ADMIN = _configUrls.GW_AUTH_ROLE_CLAIM_VALUE_PRESETS_ADMIN,
688
+ GW_AUTH_TRUSTED_HOSTS = _configUrls.GW_AUTH_TRUSTED_HOSTS,
687
689
  GW_FEATURE_SILENT_LOGIN = _configUrls.GW_FEATURE_SILENT_LOGIN,
688
690
  GW_FEATURE_FORCE_AUTHENTICATION = _configUrls.GW_FEATURE_FORCE_AUTHENTICATION;
689
691
  var loginUrl = replaceTemplateKeys(GW_AUTH_LOGIN_URL, GW_AUTH_CLIENT_ID, GW_APP_URL, sessionStorageProvider.getOauthState(), sessionStorageProvider.getOauthCodeChallenge());
@@ -697,6 +699,7 @@ var getAuthConfig = function getAuthConfig(_configUrls) {
697
699
  GW_AUTH_CLIENT_ID: GW_AUTH_CLIENT_ID,
698
700
  GW_AUTH_ROLE_CLAIM_NAME: GW_AUTH_ROLE_CLAIM_NAME,
699
701
  GW_AUTH_ROLE_CLAIM_VALUE_PRESETS_ADMIN: GW_AUTH_ROLE_CLAIM_VALUE_PRESETS_ADMIN,
702
+ GW_AUTH_TRUSTED_HOSTS: GW_AUTH_TRUSTED_HOSTS,
700
703
  GW_FEATURE_SILENT_LOGIN: GW_FEATURE_SILENT_LOGIN,
701
704
  GW_FEATURE_FORCE_AUTHENTICATION: GW_FEATURE_FORCE_AUTHENTICATION
702
705
  };
@@ -853,7 +856,15 @@ var AuthenticationProvider = function AuthenticationProvider(_ref2) {
853
856
  currentRole: currentRole,
854
857
  setCurrentRole: setCurrentRole
855
858
  };
856
- }, [isLoggedIn, onLogin, auth, onSetAuth, authConfig, sessionStorageProvider, currentRole, setCurrentRole]);
859
+ },
860
+ // `auth` is a mutable ref (see the hotfix note in
861
+ // useAuthenticationDefaultProps), so its identity never changes when its
862
+ // contents do -- eslint can't know that, and considers the fields below
863
+ // redundant with `auth`. They're not: depending on them individually is
864
+ // what makes this memo (and therefore the context value handed to
865
+ // consumers) actually update when e.g. the access token is refreshed.
866
+ // eslint-disable-next-line react-hooks/exhaustive-deps
867
+ [isLoggedIn, onLogin, auth, auth == null ? void 0 : auth.token, auth == null ? void 0 : auth.refresh_token, auth == null ? void 0 : auth.expires_at, auth == null ? void 0 : auth.has_connection_issue, auth == null ? void 0 : auth.username, auth == null ? void 0 : auth.roles, onSetAuth, authConfig, sessionStorageProvider, currentRole, setCurrentRole]);
857
868
  return jsx(AuthenticationContext.Provider, {
858
869
  value: contextValue,
859
870
  children: children
@@ -1219,6 +1230,139 @@ var UserMenuRoles = function UserMenuRoles(_ref) {
1219
1230
  });
1220
1231
  };
1221
1232
 
1233
+ /* *
1234
+ * Licensed under the Apache License, Version 2.0 (the "License");
1235
+ * you may not use this file except in compliance with the License.
1236
+ * You may obtain a copy of the License at
1237
+ *
1238
+ * http://www.apache.org/licenses/LICENSE-2.0
1239
+ *
1240
+ * Unless required by applicable law or agreed to in writing, software
1241
+ * distributed under the License is distributed on an "AS IS" BASIS,
1242
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1243
+ * See the License for the specific language governing permissions and
1244
+ * limitations under the License.
1245
+ *
1246
+ * Copyright 2026 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
1247
+ * Copyright 2026 - Finnish Meteorological Institute (FMI)
1248
+ * Copyright 2026 - The Norwegian Meteorological Institute (MET Norway)
1249
+ * */
1250
+ var store = {
1251
+ access_token: undefined,
1252
+ trustedHosts: new Set()
1253
+ };
1254
+ var setJWTAccessTokenForTrustedServices = function setJWTAccessTokenForTrustedServices(access_token) {
1255
+ store.access_token = access_token;
1256
+ };
1257
+ /**
1258
+ * Resets the list of trusted services
1259
+ */
1260
+ var resetAuthFetchTrustedServices = function resetAuthFetchTrustedServices() {
1261
+ store.trustedHosts.clear();
1262
+ };
1263
+ /**
1264
+ * A list of hostnames (e.g. "adaguc-server-geoweb.geoweb.knmi.cloud") that
1265
+ * are allowed to receive the JWT access_token.
1266
+ * @param hosts
1267
+ * @param enable
1268
+ */
1269
+ var enableAuthFetchTrustedServices = function enableAuthFetchTrustedServices(hosts, enable) {
1270
+ if (enable === void 0) {
1271
+ enable = true;
1272
+ }
1273
+ hosts.forEach(function (host) {
1274
+ var normalizedHost = host.toLowerCase();
1275
+ if (enable) {
1276
+ store.trustedHosts.add(normalizedHost);
1277
+ } else {
1278
+ store.trustedHosts["delete"](normalizedHost);
1279
+ }
1280
+ });
1281
+ };
1282
+ /**
1283
+ * Extend the headers with an Authorization header containing the JWT access_token.
1284
+ * @param fetchHeaders Incoming Headers, will be extended with an Authorization header.
1285
+ * @param url Incoming url, whose hostname is checked (case-insensitively) against the list of hosts set by enableAuthFetchTrustedServices.
1286
+ * @returns
1287
+ */
1288
+ var extendHeadersWithJWTAccessToken = function extendHeadersWithJWTAccessToken(fetchHeaders, url) {
1289
+ if (!store.access_token) {
1290
+ return fetchHeaders;
1291
+ }
1292
+ try {
1293
+ var newUrl = url.url || url;
1294
+ var _URL = new URL(newUrl.toString()),
1295
+ hostname = _URL.hostname;
1296
+ if (store.trustedHosts.has(hostname.toLowerCase())) {
1297
+ fetchHeaders.append('Authorization', "Bearer " + store.access_token);
1298
+ }
1299
+ } catch (_e) {
1300
+ /* empty */
1301
+ }
1302
+ return fetchHeaders;
1303
+ };
1304
+ /**
1305
+ * Similar to fetch, but when trusted it adds an Authorization header with the JWT access_token. The trusted urls can be set as regexp in enableAuthFetchTrustedServices.
1306
+ * @param url
1307
+ * @param init
1308
+ * @returns
1309
+ */
1310
+ // eslint-disable-next-line @typescript-eslint/promise-function-async, @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types
1311
+ var authFetch = function authFetch(url, init) {
1312
+ return fetch(url, Object.assign({}, init || {}, {
1313
+ headers: extendHeadersWithJWTAccessToken(new Headers(init == null ? void 0 : init.headers), url)
1314
+ }));
1315
+ };
1316
+
1317
+ var AuthFetchTrustedServicesContext = /*#__PURE__*/React.createContext('');
1318
+ /**
1319
+ * Provider that keeps authFetch's module-level trusted-services store in
1320
+ * sync with the current auth token and GW_AUTH_TRUSTED_HOSTS config.
1321
+ *
1322
+ * authFetch() is also called from outside the React tree (e.g. WMImage.ts,
1323
+ * the timeseries/soundings api clients), so the token itself cannot live in
1324
+ * React context alone -- this provider is what bridges React state into
1325
+ * that module-level store. It also exposes the token via context for React
1326
+ * consumers, see useAuthFetchToken.
1327
+ */
1328
+ var AuthFetchTrustedServicesProvider = function AuthFetchTrustedServicesProvider(_ref) {
1329
+ var auth = _ref.auth,
1330
+ authConfig = _ref.authConfig,
1331
+ children = _ref.children;
1332
+ // This will make the JWT token available for authFetch.
1333
+ React.useEffect(function () {
1334
+ setJWTAccessTokenForTrustedServices((auth == null ? void 0 : auth.token) || '');
1335
+ }, [auth == null ? void 0 : auth.token]);
1336
+ // This will tell authFetch to do calls with the JWT token for specific trusted services.
1337
+ React.useEffect(function () {
1338
+ var _authConfig$GW_AUTH_T;
1339
+ var trustedHosts = ((_authConfig$GW_AUTH_T = authConfig == null ? void 0 : authConfig.GW_AUTH_TRUSTED_HOSTS) != null ? _authConfig$GW_AUTH_T : '').split(',').map(function (host) {
1340
+ return host.trim();
1341
+ }).filter(function (host) {
1342
+ return host.length > 0;
1343
+ });
1344
+ if (trustedHosts.length === 0) {
1345
+ return undefined;
1346
+ }
1347
+ enableAuthFetchTrustedServices(trustedHosts);
1348
+ return function () {
1349
+ enableAuthFetchTrustedServices(trustedHosts, false);
1350
+ };
1351
+ }, [authConfig == null ? void 0 : authConfig.GW_AUTH_TRUSTED_HOSTS]);
1352
+ return jsx(AuthFetchTrustedServicesContext.Provider, {
1353
+ value: (auth == null ? void 0 : auth.token) || '',
1354
+ children: children
1355
+ });
1356
+ };
1357
+ /**
1358
+ * Consumer hook for React components that want to read the access token
1359
+ * currently registered with authFetch for trusted services. Must be used
1360
+ * within an AuthFetchTrustedServicesProvider; returns '' otherwise.
1361
+ */
1362
+ var useAuthFetchToken = function useAuthFetchToken() {
1363
+ return React.useContext(AuthFetchTrustedServicesContext);
1364
+ };
1365
+
1222
1366
  var generateRandomId = function generateRandomId() {
1223
1367
  return "-" + Math.random().toString(36).substring(2, 11);
1224
1368
  };
@@ -1315,4 +1459,4 @@ params, callbacks) {
1315
1459
  };
1316
1460
  };
1317
1461
 
1318
- export { AUTH_NAMESPACE, AuthenticationContext, AuthenticationProvider, HandleOAuth2Code as Code, GEOWEB_ROLE_PRESETS_ADMIN, GEOWEB_ROLE_USER, KEEP_ALIVE_POLLER_IN_SECONDS, OAuth2Login as Login, OAuth2Logout as Logout, MILLISECOND_TO_SECOND, OIDC_NO_INTERACTION_ERROR_CODES, REFRESH_TOKEN_WHEN_PCT_EXPIRED, UserMenuRoles, apiTranslations, authTranslations, broadcastLogout, buildSilentLoginUrl, clearSession, clearSilentLoginAttempt, clearSilentLoginSuppression, createApiInstance, createFakeApiInstance, createLogoutBroadcastChannel, createNonAuthApiInstance, fakeApiRequest, getAuthConfig, getCodeChallenge, getCurrentTimeInSeconds, getCurrentUrlLocation, getRandomString, groupsToRoles, hasRecentSilentLoginAttempt, isSilentLoginEnabled, isSilentLoginSuppressed, makeCredentialsFromTokenResponse, recordSilentLoginAttempt, refreshAccessToken, refreshAccessTokenAndSetAuthContext, setAuthChangeListener, suppressSilentLogin, useApi, useAuthenticationContext, useAuthenticationDefaultProps };
1462
+ export { AUTH_NAMESPACE, AuthFetchTrustedServicesProvider, AuthenticationContext, AuthenticationProvider, HandleOAuth2Code as Code, GEOWEB_ROLE_PRESETS_ADMIN, GEOWEB_ROLE_USER, KEEP_ALIVE_POLLER_IN_SECONDS, OAuth2Login as Login, OAuth2Logout as Logout, MILLISECOND_TO_SECOND, OIDC_NO_INTERACTION_ERROR_CODES, REFRESH_TOKEN_WHEN_PCT_EXPIRED, UserMenuRoles, apiTranslations, authFetch, authTranslations, broadcastLogout, buildSilentLoginUrl, clearSession, clearSilentLoginAttempt, clearSilentLoginSuppression, createApiInstance, createFakeApiInstance, createLogoutBroadcastChannel, createNonAuthApiInstance, enableAuthFetchTrustedServices, extendHeadersWithJWTAccessToken, fakeApiRequest, getAuthConfig, getCodeChallenge, getCurrentTimeInSeconds, getCurrentUrlLocation, getRandomString, groupsToRoles, hasRecentSilentLoginAttempt, isSilentLoginEnabled, isSilentLoginSuppressed, makeCredentialsFromTokenResponse, recordSilentLoginAttempt, refreshAccessToken, refreshAccessTokenAndSetAuthContext, resetAuthFetchTrustedServices, setAuthChangeListener, setJWTAccessTokenForTrustedServices, suppressSilentLogin, useApi, useAuthFetchToken, useAuthenticationContext, useAuthenticationDefaultProps };
@@ -5,9 +5,11 @@ export { default as Login } from './lib/components/pages/Login';
5
5
  export { default as Logout } from './lib/components/pages/Logout';
6
6
  export * from './lib/components/UserMenuRoles';
7
7
  export * from './lib/components/AuthenticationContext';
8
+ export * from './lib/components/AuthFetchTrustedServicesContext';
8
9
  export * from './lib/components/ApiContext';
9
10
  export * from './lib/components/apiHooks';
10
11
  export * from './lib/utils/utils';
12
+ export * from './lib/utils/authFetch';
11
13
  export * from './lib/utils/silentLogin';
12
14
  export { AUTH_NAMESPACE } from './lib/utils/i18n';
13
15
  export { authTranslations, apiTranslations };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { AuthFetchTrustedServicesProviderProps } from './types';
3
+ /**
4
+ * Provider that keeps authFetch's module-level trusted-services store in
5
+ * sync with the current auth token and GW_AUTH_TRUSTED_HOSTS config.
6
+ *
7
+ * authFetch() is also called from outside the React tree (e.g. WMImage.ts,
8
+ * the timeseries/soundings api clients), so the token itself cannot live in
9
+ * React context alone -- this provider is what bridges React state into
10
+ * that module-level store. It also exposes the token via context for React
11
+ * consumers, see useAuthFetchToken.
12
+ */
13
+ export declare const AuthFetchTrustedServicesProvider: React.FC<AuthFetchTrustedServicesProviderProps>;
14
+ /**
15
+ * Consumer hook for React components that want to read the access token
16
+ * currently registered with authFetch for trusted services. Must be used
17
+ * within an AuthFetchTrustedServicesProvider; returns '' otherwise.
18
+ */
19
+ export declare const useAuthFetchToken: () => string;
@@ -0,0 +1,2 @@
1
+ export { AuthFetchTrustedServicesProvider, useAuthFetchToken, } from './AuthFetchTrustedServicesContext';
2
+ export type * from './types';
@@ -0,0 +1,8 @@
1
+ import type React from 'react';
2
+ import type { Credentials } from '../ApiContext/types';
3
+ import type { AuthenticationConfig } from '../AuthenticationContext/types';
4
+ export interface AuthFetchTrustedServicesProviderProps {
5
+ auth?: Credentials | null;
6
+ authConfig?: AuthenticationConfig;
7
+ children?: React.ReactNode;
8
+ }
@@ -9,6 +9,7 @@ export interface AuthenticationConfig {
9
9
  GW_APP_URL: string;
10
10
  GW_BE_VERSION_BASE_URL?: string;
11
11
  GW_AUTH_CLIENT_ID: string;
12
+ GW_AUTH_TRUSTED_HOSTS?: string;
12
13
  GW_FEATURE_SILENT_LOGIN?: boolean;
13
14
  GW_FEATURE_FORCE_AUTHENTICATION?: boolean;
14
15
  }
@@ -0,0 +1,26 @@
1
+ export declare const setJWTAccessTokenForTrustedServices: (access_token: string | undefined) => void;
2
+ /**
3
+ * Resets the list of trusted services
4
+ */
5
+ export declare const resetAuthFetchTrustedServices: () => void;
6
+ /**
7
+ * A list of hostnames (e.g. "adaguc-server-geoweb.geoweb.knmi.cloud") that
8
+ * are allowed to receive the JWT access_token.
9
+ * @param hosts
10
+ * @param enable
11
+ */
12
+ export declare const enableAuthFetchTrustedServices: (hosts: string[], enable?: boolean) => void;
13
+ /**
14
+ * Extend the headers with an Authorization header containing the JWT access_token.
15
+ * @param fetchHeaders Incoming Headers, will be extended with an Authorization header.
16
+ * @param url Incoming url, whose hostname is checked (case-insensitively) against the list of hosts set by enableAuthFetchTrustedServices.
17
+ * @returns
18
+ */
19
+ export declare const extendHeadersWithJWTAccessToken: (fetchHeaders: Headers, url: string | URL | Request) => Headers;
20
+ /**
21
+ * Similar to fetch, but when trusted it adds an Authorization header with the JWT access_token. The trusted urls can be set as regexp in enableAuthFetchTrustedServices.
22
+ * @param url
23
+ * @param init
24
+ * @returns
25
+ */
26
+ export declare const authFetch: (url: string | URL | Request, init?: RequestInit) => Promise<Response>;
package/package.json CHANGED
@@ -1,45 +1,45 @@
1
1
  {
2
- "name": "@opengeoweb/authentication",
3
- "version": "19.6.1",
4
- "description": "GeoWeb authentication library for the opengeoweb project",
5
- "license": "Apache-2.0",
6
- "repository": {
7
- "type": "git",
8
- "url": "git@gitlab.com:opengeoweb/opengeoweb.git"
9
- },
10
- "main": "./dist/index.esm.js",
11
- "module": "./dist/index.esm.js",
12
- "types": "./dist/index.d.ts",
13
- "exports": {
14
- "./package.json": "./package.json",
15
- ".": {
16
- "@opengeoweb/source": "./src/index.ts",
17
- "types": "./dist/index.d.ts",
18
- "import": "./dist/index.esm.js",
19
- "default": "./dist/index.esm.js"
20
- }
21
- },
22
- "dependencies": {
23
- "axios": "^1.18.0",
24
- "@opengeoweb/shared": "*",
25
- "@opengeoweb/theme": "*",
26
- "i18next": "^25.0.1",
27
- "react-i18next": "^15.1.1",
28
- "@mui/material": "^9.0.1",
29
- "react-router": "^7.18.2"
30
- },
31
- "peerDependencies": {
32
- "react": "19",
33
- "@emotion/react": "*",
34
- "@emotion/styled": "*"
35
- },
36
- "devDependencies": {
37
- "eslint-plugin-storybook": "10.3.3"
38
- },
39
- "files": [
40
- "dist",
41
- "!dist/package.json",
42
- "README.md",
43
- "package.json"
44
- ]
45
- }
2
+ "name": "@opengeoweb/authentication",
3
+ "version": "20.0.0-nightly-20260919",
4
+ "description": "GeoWeb authentication library for the opengeoweb project",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git@gitlab.com:opengeoweb/opengeoweb.git"
9
+ },
10
+ "main": "./dist/index.esm.js",
11
+ "module": "./dist/index.esm.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ "./package.json": "./package.json",
15
+ ".": {
16
+ "@opengeoweb/source": "./src/index.ts",
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.esm.js",
19
+ "default": "./dist/index.esm.js"
20
+ }
21
+ },
22
+ "dependencies": {
23
+ "axios": "^1.18.0",
24
+ "@opengeoweb/shared": "20.0.0-nightly-20260919",
25
+ "@opengeoweb/theme": "20.0.0-nightly-20260919",
26
+ "i18next": "^25.0.1",
27
+ "react-i18next": "^15.1.1",
28
+ "@mui/material": "^9.0.1",
29
+ "react-router": "^7.18.2"
30
+ },
31
+ "peerDependencies": {
32
+ "react": "19",
33
+ "@emotion/react": "*",
34
+ "@emotion/styled": "*"
35
+ },
36
+ "devDependencies": {
37
+ "eslint-plugin-storybook": "10.3.3"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "!dist/package.json",
42
+ "README.md",
43
+ "package.json"
44
+ ]
45
+ }