@connectid-tools/idp-selector-react 6.7.0 → 6.8.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/Popup.css CHANGED
@@ -153,7 +153,8 @@
153
153
  flex-shrink: 0;
154
154
  }
155
155
  .cid-idp-selector-popup-participants {
156
- margin-top: 24px;
156
+ list-style: none;
157
+ margin: 24px 0 16px 0;
157
158
  display: grid;
158
159
  grid-template-columns: 225px 225px;
159
160
  grid-gap: 16px;
@@ -173,33 +174,11 @@
173
174
  padding: 8px 16px;
174
175
  border: 1px solid #E9E9E9;
175
176
  }
176
- .cid-idp-selector-popup-participant-greyed-out {
177
- display: flex;
178
- align-items: center;
179
- border-radius: 12px;
180
- cursor: pointer;
181
- box-sizing: border-box;
182
- padding: 8px 16px;
183
- border: 1px solid #E9E9E9;
184
- background-color: #F4F4F4;
185
- cursor: default;
186
- margin-bottom: 4px;
187
- }
188
- .cid-idp-selector-popup-participant-greyed-out-text {
189
- color: #5C5C5C;
190
- font-size: 10px;
191
- }
192
177
  .cid-idp-selector-popup-participant-icon {
193
178
  width: 32px;
194
179
  height: 32px;
195
180
  border-radius: 8px;
196
181
  }
197
- .cid-idp-selector-popup-participant-icon-greyed-out {
198
- width: 32px;
199
- height: 32px;
200
- border-radius: 8px;
201
- opacity: 60%
202
- }
203
182
  .cid-idp-selector-popup-participant-description {
204
183
  position: absolute;
205
184
  width: 1px;
@@ -224,16 +203,26 @@
224
203
  text-overflow: ellipsis;
225
204
  width: 90%;
226
205
  }
227
- .cid-idp-selector-popup-participant-name-greyed-out {
228
- font-size: 14px;
206
+ .cid-idp-selector-popup-missing {
207
+ border-radius: 12px;
208
+ background: #F4F4F4;
209
+ padding: 18px;
210
+ }
211
+ .cid-idp-selector-popup-missing-title {
212
+ color: var(--charcoal);
229
213
  font-family: var(--font);
214
+ font-size: 12px;
215
+ font-weight: 600;
216
+ line-height: 120%;
217
+ margin: 0;
218
+ }
219
+ .cid-idp-selector-popup-missing-text {
230
220
  color: var(--charcoal75);
231
- margin-left: 12px;
232
- overflow: hidden;
233
- white-space: nowrap;
234
- text-overflow: ellipsis;
235
- width: 90%;
236
-
221
+ font-family: var(--font);
222
+ font-size: 12px;
223
+ font-weight: 400;
224
+ line-height: 120%;
225
+ margin: 8px 0 0 0;
237
226
  }
238
227
  .cid-idp-selector-popup-manual {
239
228
  font-family: var(--font);
@@ -294,18 +283,6 @@
294
283
  max-width: 466px;
295
284
  }
296
285
 
297
- .cid-greyout-participant-name {
298
- position: absolute;
299
- display: inline-flex;
300
- flex-direction: row;
301
- align-items: center;
302
- }
303
-
304
- .cid-idp-selector-button-info-icon-greyed-out {
305
- margin-right: 2px;
306
- flex-shrink: 0;
307
- }
308
-
309
286
  @media (prefers-reduced-motion: reduce) {
310
287
  .cid-idp-selector-popup-logo-dot {
311
288
  animation: none;
@@ -324,6 +301,7 @@
324
301
  margin: 20px 0;
325
302
  }
326
303
  .cid-idp-selector-popup-participants {
304
+ margin: 16px 0 12px 0;
327
305
  grid-template-columns: 190px 190px;
328
306
  }
329
307
  }
@@ -358,13 +336,9 @@
358
336
  margin: 20px auto 0 auto;
359
337
  }
360
338
  .cid-idp-selector-popup-participants {
361
- margin-top: 12px;
362
339
  grid-template-columns: 1fr;
363
340
  max-height: 550px;
364
341
  }
365
- .cid-idp-selector-popup-participant-greyed-out {
366
- margin-bottom: 8px;
367
- }
368
342
  .cid-idp-selector-popup-participant-name {
369
343
  overflow: inherit;
370
344
  white-space: normal;
@@ -372,9 +346,6 @@
372
346
  width: 100%;
373
347
  font-size: 16px;
374
348
  }
375
- .cid-greyout-participant-name {
376
- margin-top: -6px;
377
- }
378
349
  .cid-idp-selector-popup-close {
379
350
  position: absolute;
380
351
  padding: 8px;
package/Popup.js CHANGED
@@ -12,7 +12,7 @@ import { useEffect, useRef, useState } from 'react';
12
12
  import ReactDOM from 'react-dom';
13
13
  import { useMediaQuery } from 'react-responsive';
14
14
  import { useAnalytics } from './analytics';
15
- import { filterAuthorisationServers, getManualAuthorisationServer, mapAuthorisationServerToDeviceType, } from './certification';
15
+ import { filterAuthorisationServers, getManualAuthorisationServer } from './certification';
16
16
  import './global.css';
17
17
  import { InfoBox } from './InfoBox';
18
18
  import { getCurrentUrlOrigin } from './navigator';
@@ -20,7 +20,6 @@ import { NoIdpError } from './NoIdpError';
20
20
  import { ParticipantsLoader } from './ParticipantsLoader';
21
21
  import './Popup.css';
22
22
  import { useOverrideShiftTab, useOverrideTab } from './TabHook';
23
- import { getDeviceType } from './userAgent';
24
23
  import detectIncognito from './incognito';
25
24
  export const Popup = ({ onProceed, onCancel, onError, claims, requiredClaims, showAllParticipants, certificationStatus, popupTitle, rpDataSharingDescription, enableManualVerification, requiredCertifications, rpLogoUrl, participants, error, isLoading, }) => {
26
25
  const [isIncognito, setIsIncognito] = useState();
@@ -123,14 +122,6 @@ export const Popup = ({ onProceed, onCancel, onError, claims, requiredClaims, sh
123
122
  }
124
123
  return (_jsxs(_Fragment, { children: [_jsx("div", { className: "cid-idp-selector-popup-title-container", children: renderClaimsTitle() }), renderClaimList()] }));
125
124
  };
126
- const participantTile = (AuthorisationServerId, CustomerFriendlyName, CustomerFriendlyLogoUri, deviceType) => {
127
- if (deviceType === 'desktop') {
128
- return (_jsxs("div", { children: [_jsx("span", { id: `participant-greyed-out-description-${CustomerFriendlyName}`, className: "cid-idp-selector-popup-participant-description", "aria-hidden": "true", children: "available on mobile only" }), _jsxs("li", { "data-testid": "participant-greyed-out", className: "cid-idp-selector-popup-participant-greyed-out", "aria-disabled": "true", "aria-describedby": `participant-greyed-out-description-${CustomerFriendlyName}`, tabIndex: 0, children: [_jsx("img", { className: "cid-idp-selector-popup-participant-icon-greyed-out", src: CustomerFriendlyLogoUri, alt: `${CustomerFriendlyName} logo` }), _jsx("div", { className: "cid-idp-selector-popup-participant-name-greyed-out", title: CustomerFriendlyName, "data-testid": "participant-name", children: CustomerFriendlyName })] }, AuthorisationServerId), _jsxs("div", { className: "cid-greyout-participant-name", children: [_jsxs("svg", { className: "cid-idp-selector-button-info-icon-greyed-out", width: "8", height: "8", viewBox: "0 0 13 13", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M6.53509 12.3572C9.59207 12.3572 12.0702 9.81483 12.0702 6.67859C12.0702 3.54239 9.59207 1 6.53509 1C3.47814 1 1 3.54239 1 6.67859C1 9.81483 3.47814 12.3572 6.53509 12.3572Z", stroke: "#262626", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M5.25781 9.29883H7.81247", stroke: "#262626", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M6.53515 4.49472C6.7703 4.49472 6.96093 4.29915 6.96093 4.05791C6.96093 3.81666 6.7703 3.62109 6.53515 3.62109C6.3 3.62109 6.10938 3.81666 6.10938 4.05791C6.10938 4.29915 6.3 4.49472 6.53515 4.49472Z", fill: "#262626", stroke: "#262626", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M6.53515 9.29989V6.24219H5.68359", stroke: "#262626", strokeLinecap: "round", strokeLinejoin: "round" })] }), _jsx("div", { "data-testid": "cid-greyout-participant-name-mobile-only", className: "cid-idp-selector-popup-participant-greyed-out-text", "aria-describedby": `participant-greyed-out-description-${CustomerFriendlyName}`, children: "Available on mobile only" })] })] }));
129
- }
130
- else {
131
- return (_jsxs("li", { "data-testid": "participant", className: "cid-idp-selector-popup-participant", tabIndex: 0, onClick: () => onProceed(AuthorisationServerId, CustomerFriendlyName), children: [_jsx("img", { className: "cid-idp-selector-popup-participant-icon", src: CustomerFriendlyLogoUri, alt: `${CustomerFriendlyName} logo` }), _jsx("div", { className: "cid-idp-selector-popup-participant-name", title: CustomerFriendlyName, "data-testid": "participant-name", children: CustomerFriendlyName })] }, AuthorisationServerId));
132
- }
133
- };
134
125
  const renderAuthorisationServers = () => {
135
126
  if (isLoading) {
136
127
  return (_jsxs("div", { className: "cid-idp-selector-popup-provider-wrapper", children: [_jsx("h3", { className: "cid-idp-selector-popup-subtitle", children: "Choose a provider" }), _jsx(ParticipantsLoader, {})] }));
@@ -142,18 +133,19 @@ export const Popup = ({ onProceed, onCancel, onError, claims, requiredClaims, sh
142
133
  return (_jsx("div", { className: "cid-idp-selector-popup-info-box-wrapper-warn", children: _jsx(NoIdpError, { dataTestId: "participant-error", hasManualIdp: false }) }));
143
134
  }
144
135
  const authorisationServers = participants
145
- .map((participant) => participant.AuthorisationServers)
146
- .flat()
136
+ .flatMap((participant) => participant.AuthorisationServers)
147
137
  .sort((authServer1, authServer2) => authServer1.CustomerFriendlyName.localeCompare(authServer2.CustomerFriendlyName));
148
138
  const manualAuthorisationServer = getManualAuthorisationServer(authorisationServers, showAllParticipants);
149
139
  const authorisationServersWithoutManual = authorisationServers.filter(({ AuthorisationServerId }) => AuthorisationServerId !== (manualAuthorisationServer === null || manualAuthorisationServer === void 0 ? void 0 : manualAuthorisationServer.AuthorisationServerId));
150
140
  const filterByClaims = requiredClaims || claims;
151
141
  const filteredAuthorisationServers = filterAuthorisationServers(authorisationServersWithoutManual, showAllParticipants, certificationStatus, filterByClaims, requiredCertifications);
152
- const filteredAuthServerByDevice = mapAuthorisationServerToDeviceType(filteredAuthorisationServers, getDeviceType());
142
+ // Getting all auth servers that have certifications with profile type 'Redirect' and profile variant 'FAPI2 Adv. OP w/Private Key, PAR'
143
+ const authorisationServerWithProfileRedirectFapi2 = authorisationServersWithoutManual.filter(({ AuthorisationServerCertifications }) => {
144
+ return AuthorisationServerCertifications.find(({ ProfileType, ProfileVariant }) => ProfileType === 'Redirect' && ProfileVariant === 'FAPI2 Adv. OP w/Private Key, PAR');
145
+ });
146
+ const missingAuthorisationServerWithProfileRedirectFapi2 = authorisationServerWithProfileRedirectFapi2.length !== filteredAuthorisationServers.length;
153
147
  const hasManualIdp = enableManualVerification && !!manualAuthorisationServer;
154
- return (_jsxs(_Fragment, { children: [filteredAuthorisationServers.length > 0 ? (_jsxs("div", { className: "cid-idp-selector-popup-provider-wrapper", children: [_jsx("h3", { className: "cid-idp-selector-popup-subtitle", children: "Choose a provider" }), _jsx("ul", { className: "cid-idp-selector-popup-participants", "data-testid": "participants", children: Array.from(filteredAuthServerByDevice.entries()).map(([authServer, device]) => {
155
- return (_jsx("div", { children: participantTile(authServer.AuthorisationServerId, authServer.CustomerFriendlyName, authServer.CustomerFriendlyLogoUri, device) }, authServer.AuthorisationServerId));
156
- }) })] })) : (_jsx("div", { className: "cid-idp-selector-popup-info-box-error-wrapper", "data-testid": "popup-error-info-box", children: _jsx(NoIdpError, { hasManualIdp: hasManualIdp }) })), enableManualVerification && manualAuthorisationServer && (_jsx(_Fragment, { children: _jsxs("p", { className: "cid-idp-selector-popup-manual", children: [_jsx("span", { className: "cid-idp-selector-popup-manual-title", "data-testid": "manual-verification-text", children: "Or, use a document to verify your identity" }), _jsx("span", { className: "cid-idp-selector-popup-manual-action", tabIndex: 0, onClick: () => onProceed(manualAuthorisationServer.AuthorisationServerId, manualAuthorisationServer.CustomerFriendlyName), "data-testid": "manual-verification-action", role: "link", children: "Verify with a document" }), _jsx("span", { className: "cid-idp-selector-popup-manual-description", children: "ConnectID does not collect, hold or store your personal information at any time." })] }) }))] }));
148
+ return (_jsxs(_Fragment, { children: [filteredAuthorisationServers.length > 0 ? (_jsxs("div", { className: "cid-idp-selector-popup-provider-wrapper", children: [_jsx("h3", { className: "cid-idp-selector-popup-subtitle", children: "Choose a provider" }), _jsx("ul", { className: "cid-idp-selector-popup-participants", "data-testid": "participants", children: filteredAuthorisationServers.map(({ AuthorisationServerId, CustomerFriendlyName, CustomerFriendlyLogoUri }) => (_jsxs("li", { "data-testid": "participant", className: "cid-idp-selector-popup-participant", tabIndex: 0, onClick: () => onProceed(AuthorisationServerId, CustomerFriendlyName), children: [_jsx("img", { className: "cid-idp-selector-popup-participant-icon", src: CustomerFriendlyLogoUri, alt: `${CustomerFriendlyName} logo` }), _jsx("div", { className: "cid-idp-selector-popup-participant-name", title: CustomerFriendlyName, "data-testid": "participant-name", children: CustomerFriendlyName })] }, AuthorisationServerId))) }), missingAuthorisationServerWithProfileRedirectFapi2 && (_jsxs("div", { className: "cid-idp-selector-popup-missing", "data-testid": "missing-auth-server", children: [_jsx("p", { className: "cid-idp-selector-popup-missing-title", children: "Can't find your provider?" }), _jsx("p", { className: "cid-idp-selector-popup-missing-text", children: "Not all of our identity providers are available for this verification." })] }))] })) : (_jsx("div", { className: "cid-idp-selector-popup-info-box-error-wrapper", "data-testid": "popup-error-info-box", children: _jsx(NoIdpError, { hasManualIdp: hasManualIdp }) })), enableManualVerification && manualAuthorisationServer && (_jsx(_Fragment, { children: _jsxs("p", { className: "cid-idp-selector-popup-manual", children: [_jsx("span", { className: "cid-idp-selector-popup-manual-title", "data-testid": "manual-verification-text", children: "Or, use a document to verify your identity" }), _jsx("span", { className: "cid-idp-selector-popup-manual-action", tabIndex: 0, onClick: () => onProceed(manualAuthorisationServer.AuthorisationServerId, manualAuthorisationServer.CustomerFriendlyName), "data-testid": "manual-verification-action", role: "link", children: "Verify with a document" }), _jsx("span", { className: "cid-idp-selector-popup-manual-description", children: "ConnectID does not collect, hold or store your personal information at any time." })] }) }))] }));
157
149
  };
158
150
  return ReactDOM.createPortal(_jsxs("div", { className: "cid-idp-selector-popup", tabIndex: 0, ref: popupRef, onKeyDown: handleEnterEsc, children: [_jsxs("div", { className: "cid-idp-selector-popup-logo-container", children: [_jsxs("div", { className: "cid-idp-selector-popup-logos", children: [_jsxs("svg", { role: "img", focusable: "false", className: "cid-idp-selector-popup-logo", viewBox: "0 0 132.37 157.84", "data-testid": "cid-logo", children: [_jsx("title", { children: "ConnectID logo" }), _jsx("path", { d: "M102.22,91.65c0,19.9-16.13,36.03-36.03,36.03s-36.03-16.13-36.03-36.03,16.13-36.03,36.03-36.03c9.95,0,18.96,4.03,25.48,10.55l40.71-40.71c-6.52-6.52-10.55-15.52-10.55-25.46h-30.14c0,13.45,4.02,25.95,10.92,36.39-10.45-6.9-22.96-10.93-36.42-10.93C29.63,25.47,0,55.1,0,91.65s29.63,66.19,66.19,66.19,66.19-29.63,66.19-66.19h-30.16Z" })] }), rpLogoUrl && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "cid-idp-selector-popup-logo-dots", children: [_jsx("div", { className: "cid-idp-selector-popup-logo-dot" }), _jsx("div", { className: "cid-idp-selector-popup-logo-dot" }), _jsx("div", { className: "cid-idp-selector-popup-logo-dot" })] }), _jsx("img", { className: "cid-idp-selector-popup-logo-rp", src: rpLogoUrl, alt: "RP logo", "data-testid": "rp-logo" })] }))] }), _jsxs("button", { "aria-label": "Close popup", "data-testid": "popup-close", className: "cid-idp-selector-popup-close", onClick: onCancel, tabIndex: 0, ref: closeButtonRef, children: [_jsx("span", { className: "cid-idp-selector-popup-close-label", children: "Close" }), _jsx("svg", { clipRule: "evenodd", fillRule: "evenodd", strokeLinejoin: "round", strokeMiterlimit: "2", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "m12 10.93 5.719-5.72c.146-.146.339-.219.531-.219.404 0 .75.324.75.749 0 .193-.073.385-.219.532l-5.72 5.719 5.719 5.719c.147.147.22.339.22.531 0 .427-.349.75-.75.75-.192 0-.385-.073-.531-.219l-5.719-5.719-5.719 5.719c-.146.146-.339.219-.531.219-.401 0-.75-.323-.75-.75 0-.192.073-.384.22-.531l5.719-5.719-5.72-5.719c-.146-.147-.219-.339-.219-.532 0-.425.346-.749.75-.749.192 0 .385.073.531.219z" }) })] })] }), _jsxs("div", { className: "cid-idp-selector-popup-title-description-container", children: [_jsx("h2", { className: "cid-idp-selector-popup-title", children: popupTitle }), _jsx("p", { className: "cid-idp-selector-popup-description", children: rpDataSharingDescription })] }), renderClaims(), renderAuthorisationServers(), _jsx("div", { className: "cid-idp-selector-popup-info-box-wrapper", children: _jsxs(InfoBox, { children: [_jsx("h4", { className: "cid-idp-selector-popup-info-box-title", children: "What is ConnectID?" }), _jsxs("p", { className: "cid-idp-selector-popup-info-box-text", "data-testid": "whats-cid-text", children: ["ConnectID is an Australian-owned digital identity solution which allows you to securely prove who you are. ConnectID does not see or store your personal data. Visit", ' ', _jsx("a", { className: "cid-idp-selector-popup-info-box-link", href: "https://www.connectid.com.au", onClick: handleConnectIdLinkClicked, target: "_blank", tabIndex: 0, "data-testid": "info-box-link", ref: infoboxLinkRef, children: "connectid.com.au" }), ' ', "to find out more."] })] }) })] }), document.querySelector('body'));
159
151
  };
package/README.md CHANGED
@@ -222,6 +222,9 @@ The SVG image below the ConnectID button has either option dark or light mode. B
222
222
 
223
223
  ## 🚀 Release Notes
224
224
 
225
+ ### 6.8.0 (May 7, 2025)
226
+ - Show message in the IDP list when any IDP with `ProfileType=Redirect` and `ProfileVariant=FAPI2 Adv. OP w/Private Key, PAR` is not being displayed.
227
+
225
228
  ### 6.7.0 (May 5, 2025)
226
229
  - Detect incognito.
227
230
 
@@ -3,6 +3,6 @@ export declare const filterAuthorisationServers: (authorisationServers: Authoris
3
3
  export declare const getManualAuthorisationServer: (authorisationServers: AuthorisationServer[], showAllParticipants: boolean) => AuthorisationServer | undefined;
4
4
  export declare const removeExpiredOrNotStartedCertifications: (authorisationServers: AuthorisationServer[]) => AuthorisationServer[];
5
5
  export declare const filterAuthorisationServerByClaims: (authorisationServers: AuthorisationServer[], claims: Claim[]) => AuthorisationServer[];
6
- export declare const mapAuthorisationServerToDeviceType: (authorisationServers: AuthorisationServer[], deviceType: Device) => Map<AuthorisationServer, Device>;
7
6
  export declare const filterAuthorisationServerByCertification: (authorisationServers: AuthorisationServer[], status: CertificationStatus, requiredCertifications?: RequiredCertification[]) => AuthorisationServer[];
7
+ export declare const filterAuthorisationServerByDevice: (authorisationServers: AuthorisationServer[], deviceType: Device) => AuthorisationServer[];
8
8
  export declare const hasStarted: (startDateStr: string) => boolean;
package/certification.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { getDeviceType } from './userAgent';
1
2
  const requiredCertificationsMap = {
2
3
  'TDIF.IDP': { type: 'TDIF Accreditation', variant: 'Identity Provider' },
3
4
  'Redirect.FAPI2': { type: 'Redirect', variant: 'FAPI2 Adv. OP w/Private Key, PAR' },
@@ -6,7 +7,9 @@ export const filterAuthorisationServers = (authorisationServers, showAllParticip
6
7
  if (showAllParticipants)
7
8
  return authorisationServers;
8
9
  const authorisationServersWithValidCertifications = removeExpiredOrNotStartedCertifications(authorisationServers);
9
- const filteredAuthorisationServersByClaims = filterAuthorisationServerByClaims(authorisationServersWithValidCertifications, claims);
10
+ const device = getDeviceType();
11
+ const filteredAuthorisationServersByDevice = filterAuthorisationServerByDevice(authorisationServersWithValidCertifications, device);
12
+ const filteredAuthorisationServersByClaims = filterAuthorisationServerByClaims(filteredAuthorisationServersByDevice, claims);
10
13
  const filteredAuthorisationServers = filterAuthorisationServerByCertification(filteredAuthorisationServersByClaims, certificationStatus, requiredCertifications);
11
14
  return filteredAuthorisationServers;
12
15
  };
@@ -37,20 +40,6 @@ export const filterAuthorisationServerByClaims = (authorisationServers, claims)
37
40
  return profileVariants.every((profileVariant) => authorisationServerProfileVariants.includes(profileVariant));
38
41
  });
39
42
  };
40
- export const mapAuthorisationServerToDeviceType = (authorisationServers, deviceType) => {
41
- const authServerMap = new Map();
42
- if (deviceType === 'mobile') {
43
- authorisationServers.forEach((authorisationServer) => {
44
- authServerMap.set(authorisationServer, 'mobile');
45
- });
46
- return authServerMap;
47
- }
48
- authorisationServers.map((authorisationServer) => {
49
- const channelCertifications = authorisationServer.AuthorisationServerCertifications.filter((cert) => cert.ProfileType === 'Channel');
50
- authServerMap.set(authorisationServer, channelCertifications.length === 1 && channelCertifications[0].ProfileVariant === 'app' ? 'desktop' : 'mobile');
51
- });
52
- return authServerMap;
53
- };
54
43
  export const filterAuthorisationServerByCertification = (authorisationServers, status, requiredCertifications) => {
55
44
  const filteredByStatus = filterByStatus(authorisationServers, status);
56
45
  const filteredByStatusAndRequiredCertifications = filterByRequiredCertifications(filteredByStatus, requiredCertifications);
@@ -81,6 +70,18 @@ const filterByRequiredCertifications = (authorisationServers, requiredCertificat
81
70
  return requiredCertificationsFound === requiredCertifications.length;
82
71
  });
83
72
  };
73
+ // mobile return all authorisation servers
74
+ // tablet and desktop return all authorisation servers but those ones with only one certification and that certification is app
75
+ export const filterAuthorisationServerByDevice = (authorisationServers, deviceType) => {
76
+ if (deviceType === 'mobile')
77
+ return authorisationServers;
78
+ const onlyAppAuthorisationServers = authorisationServers.filter((authorisationServer) => {
79
+ const channelCertifications = authorisationServer.AuthorisationServerCertifications.filter((cert) => cert.ProfileType === 'Channel');
80
+ return channelCertifications.length === 1 && channelCertifications[0].ProfileVariant === 'app';
81
+ });
82
+ const onlyAppAuthorisationServersIds = onlyAppAuthorisationServers.map((authorisationServer) => authorisationServer.AuthorisationServerId);
83
+ return authorisationServers.filter((authorisationServer) => !onlyAppAuthorisationServersIds.includes(authorisationServer.AuthorisationServerId));
84
+ };
84
85
  const isExpired = (expiryDateStr) => {
85
86
  const expiryDate = parseCertificationDate(expiryDateStr);
86
87
  expiryDate.setHours(23);
@@ -1,6 +1,6 @@
1
1
  import assert from 'node:assert';
2
2
  import { describe, it } from 'node:test';
3
- import { filterAuthorisationServerByClaims, filterAuthorisationServers, getManualAuthorisationServer, mapAuthorisationServerToDeviceType, removeExpiredOrNotStartedCertifications, } from './certification';
3
+ import { filterAuthorisationServerByClaims, filterAuthorisationServerByDevice, filterAuthorisationServers, getManualAuthorisationServer, removeExpiredOrNotStartedCertifications, } from './certification';
4
4
  describe('filterAuthorisationServers', () => {
5
5
  it('should return all authorisation servers if showAllParticipants is true regardless of certification status, required certifications and claims', () => {
6
6
  const authorisationServers = [
@@ -306,82 +306,93 @@ describe('removeExpiredCertifications', () => {
306
306
  });
307
307
  });
308
308
  describe('filterAuthorisationServerByDevice', () => {
309
- const authorisationServers = [
310
- {
311
- AuthorisationServerId: '71fe3927-f596-4192-ab9a-f6644cdb9b2b',
312
- CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankA.svg',
313
- CustomerFriendlyName: 'Mock Bank A',
314
- AuthorisationServerCertifications: [
315
- {
316
- CertificationStartDate: '10/04/1900',
317
- CertificationExpirationDate: '10/04/2024',
318
- Status: 'Certified',
319
- ProfileVariant: 'web',
320
- ProfileType: 'Channel',
321
- },
322
- ],
323
- },
324
- {
325
- AuthorisationServerId: '71fe3927-f596-4192-ab9a-f6644cdb9b2x',
326
- CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankA.svg',
327
- CustomerFriendlyName: 'Mock Bank B',
328
- AuthorisationServerCertifications: [
329
- {
330
- CertificationStartDate: '10/04/1900',
331
- CertificationExpirationDate: '10/04/2024',
332
- Status: 'Certified',
333
- ProfileVariant: 'web',
334
- ProfileType: 'Channel',
335
- },
336
- ],
337
- },
338
- {
339
- AuthorisationServerId: 'fa8573a1-953a-4085-b5f7-070a42a4d5a9',
340
- CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankC.svg',
341
- CustomerFriendlyName: 'Mock Bank C',
342
- AuthorisationServerCertifications: [
343
- {
344
- CertificationStartDate: '10/04/1900',
345
- CertificationExpirationDate: '10/04/2024',
346
- Status: 'Certified',
347
- ProfileVariant: 'app',
348
- ProfileType: 'Channel',
349
- },
350
- ],
351
- },
352
- {
353
- AuthorisationServerId: 'fa8573a1-953a-4085-b5f7-070a42a4d5a1',
354
- CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankC.svg',
355
- CustomerFriendlyName: 'Mock Bank D',
356
- AuthorisationServerCertifications: [],
357
- },
358
- ];
359
- it('should return all auth servers when device is mobile', () => {
360
- const authServers = mapAuthorisationServerToDeviceType(authorisationServers, 'mobile');
361
- const values = Array.from(authServers.values());
362
- assert.deepStrictEqual(values.every((value) => value === 'mobile'), true);
363
- });
364
- it('should not return auth servers with only app cert when device is desktop', () => {
365
- const authServers = mapAuthorisationServerToDeviceType(authorisationServers, 'desktop');
366
- const filteredAuthServers = Array.from(authServers)
367
- .filter(([_, device]) => device === 'mobile')
368
- .map(([key, _]) => key);
369
- assert.deepStrictEqual(filteredAuthServers, [
370
- authorisationServers[0],
371
- authorisationServers[1],
372
- authorisationServers[3],
373
- ]);
309
+ it('should return all authorisation servers for mobile', () => {
310
+ const authorisationServers = [
311
+ {
312
+ AuthorisationServerId: '1',
313
+ CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankA.svg',
314
+ CustomerFriendlyName: 'Mock Bank A',
315
+ AuthorisationServerCertifications: [
316
+ {
317
+ ProfileType: 'Channel',
318
+ ProfileVariant: 'app',
319
+ CertificationExpirationDate: '10/04/2099',
320
+ Status: 'Certified',
321
+ CertificationStartDate: '10/04/1900',
322
+ },
323
+ ],
324
+ },
325
+ {
326
+ AuthorisationServerId: '2',
327
+ CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankA.svg',
328
+ CustomerFriendlyName: 'Mock Bank B',
329
+ AuthorisationServerCertifications: [
330
+ {
331
+ ProfileType: 'Channel',
332
+ ProfileVariant: 'web',
333
+ CertificationExpirationDate: '10/04/2099',
334
+ Status: 'Certified',
335
+ CertificationStartDate: '10/04/1900',
336
+ },
337
+ ],
338
+ },
339
+ ];
340
+ assert.deepStrictEqual(filterAuthorisationServerByDevice(authorisationServers, 'mobile'), authorisationServers);
374
341
  });
375
- it('should not return auth servers with only app cert when device is tablet', () => {
376
- const authServers = mapAuthorisationServerToDeviceType(authorisationServers, 'tablet');
377
- console.log(authServers);
378
- const filteredAuthServers = Array.from(authServers)
379
- .filter(([_, device]) => device === 'mobile')
380
- .map(([key, _]) => key);
381
- assert.deepStrictEqual(filteredAuthServers, [
382
- authorisationServers[0],
383
- authorisationServers[1],
384
- authorisationServers[3],
385
- ]);
342
+ it('should return all authorisation servers except those with only app certification when desktop', () => {
343
+ const authorisationServers = [
344
+ {
345
+ AuthorisationServerId: '1',
346
+ CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankA.svg',
347
+ CustomerFriendlyName: 'Mock Bank A',
348
+ // has only app certification (removed)
349
+ AuthorisationServerCertifications: [
350
+ {
351
+ ProfileType: 'Channel',
352
+ ProfileVariant: 'app',
353
+ CertificationExpirationDate: '10/04/2099',
354
+ Status: 'Certified',
355
+ CertificationStartDate: '10/04/1900',
356
+ },
357
+ ],
358
+ },
359
+ {
360
+ AuthorisationServerId: '2',
361
+ CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankA.svg',
362
+ CustomerFriendlyName: 'Mock Bank B',
363
+ AuthorisationServerCertifications: [
364
+ {
365
+ ProfileType: 'Channel',
366
+ ProfileVariant: 'web',
367
+ CertificationExpirationDate: '10/04/2099',
368
+ Status: 'Certified',
369
+ CertificationStartDate: '10/04/1900',
370
+ },
371
+ ],
372
+ },
373
+ {
374
+ AuthorisationServerId: '3',
375
+ CustomerFriendlyLogoUri: 'https://static.sandbox.connectid.com.au/BankA.svg',
376
+ CustomerFriendlyName: 'Mock Bank C',
377
+ // has web and app certifications (okay)
378
+ AuthorisationServerCertifications: [
379
+ {
380
+ ProfileType: 'Channel',
381
+ ProfileVariant: 'app',
382
+ CertificationExpirationDate: '10/04/2099',
383
+ Status: 'Certified',
384
+ CertificationStartDate: '10/04/1900',
385
+ },
386
+ {
387
+ ProfileType: 'Channel',
388
+ ProfileVariant: 'web',
389
+ CertificationExpirationDate: '10/04/2099',
390
+ Status: 'Certified',
391
+ CertificationStartDate: '10/04/1900',
392
+ },
393
+ ],
394
+ },
395
+ ];
396
+ assert.deepStrictEqual(filterAuthorisationServerByDevice(authorisationServers, 'desktop'), [authorisationServers[1], authorisationServers[2]]);
386
397
  });
387
398
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@connectid-tools/idp-selector-react",
3
- "version": "6.7.0",
3
+ "version": "6.8.0",
4
4
  "description": "React component for IDP Selector.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -26,8 +26,8 @@
26
26
  "homepage": "https://github.com/connectid-tools/idp-selector-react",
27
27
  "devDependencies": {
28
28
  "@babel/preset-typescript": "^7.27.1",
29
- "@types/node": "^22.15.3",
30
- "@types/react": "^18.3.20",
29
+ "@types/node": "^22.15.14",
30
+ "@types/react": "^18.3.21",
31
31
  "@types/react-dom": "^18.3.7",
32
32
  "cypress": "^13.17.0",
33
33
  "jest-environment-jsdom": "^29.7.0",