@criipto/verify-react 6.0.0 → 6.0.2
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 +31 -0
- package/dist/index.css +4 -0
- package/dist/index.d.ts +45 -2
- package/dist/index.js +68 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,37 @@ To control eID methods from your code instead of the dashboard, pass `acrValues`
|
|
|
111
111
|
|
|
112
112
|
See the [Authorize URL Builder](https://docs.idura.app/verify/guides/authorize-url-builder) or individual eID pages for the full list of supported `acr_values`.
|
|
113
113
|
|
|
114
|
+
### Configure the request per eID
|
|
115
|
+
|
|
116
|
+
`login_hint` and `scope` values are eID specific, so a single provider-level setting rarely fits every button. Pass a `beforeAuthorize` function to `CriiptoVerifyProvider` to adjust the request for the eID the user actually picked:
|
|
117
|
+
|
|
118
|
+
```jsx
|
|
119
|
+
<CriiptoVerifyProvider
|
|
120
|
+
domain="{YOUR_IDURA_DOMAIN}"
|
|
121
|
+
clientID="{YOUR_IDURA_APPLICATION_CLIENT_ID}"
|
|
122
|
+
beforeAuthorize={({ acrValues }) => {
|
|
123
|
+
if (acrValues[0].startsWith('urn:grn:authn:dk:mitid')) {
|
|
124
|
+
return { scope: 'openid address' };
|
|
125
|
+
}
|
|
126
|
+
if (acrValues[0].startsWith('urn:grn:authn:se:bankid')) {
|
|
127
|
+
return { loginHint: 'stepUp:mrtd' };
|
|
128
|
+
}
|
|
129
|
+
}}
|
|
130
|
+
>
|
|
131
|
+
<App />
|
|
132
|
+
</CriiptoVerifyProvider>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`beforeAuthorize` runs just before every authorize request is built, whichever way the login was started: `AuthMethodSelector`, `AuthMethodButton`, `SEBankIDQRCode`, `loginWithRedirect` or `loginWithPopup`. Return the values you want to change for that one request, or nothing at all to leave it as configured on the provider.
|
|
136
|
+
|
|
137
|
+
- `acrValues` is always an array, and holds a single value for logins started from a button or `AuthMethodSelector`
|
|
138
|
+
- `options` holds the request as the SDK would otherwise send it, in case you want to inspect it
|
|
139
|
+
- you can override `loginHint`, `scope`, `prompt`, `uiLocales`, `state`, `nonce`, `extraUrlParams` and the `action`/`message` shorthands
|
|
140
|
+
- `loginHint` is appended to the hints the SDK already adds, so use `action` and `message` rather than writing `action:`/`message:` hints yourself
|
|
141
|
+
- `acrValues`, `redirectUri` and the PKCE and response parameters are managed by the SDK and cannot be overridden here. Use `redirectUri` on the button or selector to change where a single eID returns the user
|
|
142
|
+
|
|
143
|
+
The hint and scope values differ per eID, see the individual eID pages in the [Idura docs](https://docs.idura.app/verify/e-ids/) for what each one supports.
|
|
144
|
+
|
|
114
145
|
## Send the user directly to an eID login screen
|
|
115
146
|
|
|
116
147
|
If you don't need the method selector, use `loginWithRedirect` (or `loginWithPopup`) and pass a single eID method identifier in `acrValues`.
|
package/dist/index.css
CHANGED
|
@@ -74,6 +74,10 @@
|
|
|
74
74
|
background-color: hsl(15.07 100% calc(57.06% + var(--bg-lightness-mod)) / var(--bg-alpha-mod));
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
.criipto-eid-btn.criipto-eid-btn--no-vipps.criipto-eid-btn--market-FI, .criipto-eid-btn.criipto-eid-btn--no-vipps.criipto-eid-btn--market-DK {
|
|
78
|
+
background-color: hsl(229 100% calc(68% + var(--bg-lightness-mod)) / var(--bg-alpha-mod));
|
|
79
|
+
}
|
|
80
|
+
|
|
77
81
|
.criipto-eid-btn.criipto-eid-btn--itsme {
|
|
78
82
|
background-color: hsl(9.72 98.18% calc(56.86% + var(--bg-lightness-mod)) / var(--bg-alpha-mod));
|
|
79
83
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import * as _criipto_auth_js0 from "@criipto/auth-js";
|
|
3
|
-
import CriiptoAuth, { OAuth2Error, OAuth2Error as OAuth2Error$1, PKCEPublicPart, Prompt, ResponseType } from "@criipto/auth-js";
|
|
3
|
+
import CriiptoAuth, { AuthorizeUrlParamsOptional, OAuth2Error, OAuth2Error as OAuth2Error$1, PKCEPublicPart, Prompt, ResponseType } from "@criipto/auth-js";
|
|
4
4
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
5
|
|
|
6
6
|
//#region src/context.d.ts
|
|
@@ -26,6 +26,39 @@ type Claims = {
|
|
|
26
26
|
exp: number;
|
|
27
27
|
[key: string]: string | number;
|
|
28
28
|
};
|
|
29
|
+
interface BeforeAuthorizeParams {
|
|
30
|
+
/**
|
|
31
|
+
* The acr_values of the authorize request that is about to be made, always normalized to an array.
|
|
32
|
+
* For logins started from a button or `AuthMethodSelector` this will hold exactly one value.
|
|
33
|
+
*/
|
|
34
|
+
acrValues: string[];
|
|
35
|
+
/**
|
|
36
|
+
* The parameters the SDK is about to use, with `CriiptoVerifyProvider` configuration already applied.
|
|
37
|
+
*/
|
|
38
|
+
options: AuthorizeUrlParamsOptional;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parameters to override for a single authorize request. Any field left out (or set to `undefined`)
|
|
42
|
+
* keeps the value configured on `CriiptoVerifyProvider`.
|
|
43
|
+
*/
|
|
44
|
+
interface BeforeAuthorizeOverrides {
|
|
45
|
+
/**
|
|
46
|
+
* Appended to the login_hint of this request, just like a `loginHint` passed directly to
|
|
47
|
+
* `loginWithRedirect`. Use `action` and `message` rather than `action:`/`message:` hints,
|
|
48
|
+
* as those are managed by the SDK.
|
|
49
|
+
*/
|
|
50
|
+
loginHint?: string;
|
|
51
|
+
action?: Action;
|
|
52
|
+
message?: string;
|
|
53
|
+
scope?: string;
|
|
54
|
+
prompt?: Prompt;
|
|
55
|
+
uiLocales?: string;
|
|
56
|
+
state?: string;
|
|
57
|
+
nonce?: string;
|
|
58
|
+
extraUrlParams?: {
|
|
59
|
+
[key: string]: string | null;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
29
62
|
//#endregion
|
|
30
63
|
//#region src/provider.d.ts
|
|
31
64
|
interface CriiptoVerifyProviderOptions {
|
|
@@ -67,6 +100,14 @@ interface CriiptoVerifyProviderOptions {
|
|
|
67
100
|
*/
|
|
68
101
|
response?: 'token' | 'code';
|
|
69
102
|
completionStrategy?: 'client' | 'openidprovider';
|
|
103
|
+
/**
|
|
104
|
+
* Called just before each authorize request is built, for every login flow
|
|
105
|
+
* (`AuthMethodSelector`, `AuthMethodButton`, `SEBankIDQRCode`, `loginWithRedirect` and `loginWithPopup`).
|
|
106
|
+
* Return the parameters you wish to change for that particular request, for instance a
|
|
107
|
+
* `loginHint` that depends on the acr_value the user picked. Returning nothing leaves the
|
|
108
|
+
* request as configured on the provider.
|
|
109
|
+
*/
|
|
110
|
+
beforeAuthorize?: (params: BeforeAuthorizeParams) => BeforeAuthorizeOverrides | void;
|
|
70
111
|
/**
|
|
71
112
|
* @deprecated Criipto internal use
|
|
72
113
|
*/
|
|
@@ -88,6 +129,7 @@ type Language = 'en' | 'da' | 'sv' | 'nb' | 'fi' | 'de' | 'nl';
|
|
|
88
129
|
//#region src/components/AuthMethodButton/Logo.d.ts
|
|
89
130
|
interface AuthMethodButtonLogoProps {
|
|
90
131
|
acrValue: string;
|
|
132
|
+
loginHint?: string;
|
|
91
133
|
/**
|
|
92
134
|
* base64 image string, e.x. data:image/png;base64,
|
|
93
135
|
* or a ReactElement
|
|
@@ -123,6 +165,7 @@ interface AuthMethodButtonComponentProps {
|
|
|
123
165
|
action?: Action;
|
|
124
166
|
disabled?: boolean;
|
|
125
167
|
loading?: boolean;
|
|
168
|
+
loginHint?: string;
|
|
126
169
|
}
|
|
127
170
|
/**
|
|
128
171
|
* Display only components, does no state management and triggers no login flows on it's own
|
|
@@ -235,5 +278,5 @@ declare function useCriiptoVerify(): {
|
|
|
235
278
|
//#region src/utils.d.ts
|
|
236
279
|
declare function filterAcrValues(input: string[]): string[];
|
|
237
280
|
//#endregion
|
|
238
|
-
export { type Action, AuthMethodButtonContainer as AuthButton, AuthMethodButtonContainer as AuthMethodButton, AuthMethodButtonComponent as AuthButtonComponent, AuthButtonGroup, AuthMethodSelector, Sweden as AuthMethodSelectorSweden, CriiptoVerifyProvider, type Language, OAuth2Error, type Result, SEBankIDQrCode as SEBankIDQRCode, actions, filterAcrValues, useCriiptoVerify };
|
|
281
|
+
export { type Action, AuthMethodButtonContainer as AuthButton, AuthMethodButtonContainer as AuthMethodButton, AuthMethodButtonComponent as AuthButtonComponent, AuthButtonGroup, AuthMethodSelector, Sweden as AuthMethodSelectorSweden, type BeforeAuthorizeOverrides, type BeforeAuthorizeParams, CriiptoVerifyProvider, type Language, OAuth2Error, type Result, SEBankIDQrCode as SEBankIDQRCode, actions, filterAcrValues, useCriiptoVerify };
|
|
239
282
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ const CriiptoVerifyContext = createContext({
|
|
|
45
45
|
});
|
|
46
46
|
//#endregion
|
|
47
47
|
//#region package.json
|
|
48
|
-
var version = "6.0.
|
|
48
|
+
var version = "6.0.2";
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/i18n/en.ts
|
|
51
51
|
const en = {
|
|
@@ -251,7 +251,7 @@ function acrValueToProviderPrefix(value) {
|
|
|
251
251
|
else if (value.startsWith("itsme")) return "itsme";
|
|
252
252
|
else return value.split(":").slice(0, 2).join(":");
|
|
253
253
|
}
|
|
254
|
-
function acrValueToTitle(language, value, { disambiguate }) {
|
|
254
|
+
function acrValueToTitle(language, value, { disambiguate, loginHint }) {
|
|
255
255
|
const i18n = getI18n(language);
|
|
256
256
|
value = value.replace("urn:grn:authn:", "");
|
|
257
257
|
const provider = acrValueToProviderPrefix(value);
|
|
@@ -286,7 +286,11 @@ function acrValueToTitle(language, value, { disambiguate }) {
|
|
|
286
286
|
subtitle
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
|
-
if (provider === "no:vipps")
|
|
289
|
+
if (provider === "no:vipps") {
|
|
290
|
+
const marketHint = loginHint === null || loginHint === void 0 ? void 0 : loginHint.split(" ").find((s) => s.startsWith("market:"));
|
|
291
|
+
if (marketHint === "market:DK" || marketHint === "market:FI") return { title: "MobilePay" };
|
|
292
|
+
return { title: autoTitleCase(value).replace("NO ", "") };
|
|
293
|
+
}
|
|
290
294
|
if (provider === "se:frejaid") return { title: "FrejaID" };
|
|
291
295
|
if (provider === "uk:oneid") return { title: "OneID" };
|
|
292
296
|
if (provider === "de:personalausweis") return { title: "Personalausweis" };
|
|
@@ -464,10 +468,14 @@ const MESSAGE_SUPPORTING_ACR_VALUES = [
|
|
|
464
468
|
"urn:grn:authn:se:bankid:same-device",
|
|
465
469
|
"urn:grn:authn:se:bankid:another-device:qr"
|
|
466
470
|
];
|
|
471
|
+
function normalizeAcrValues(acrValues) {
|
|
472
|
+
if (!acrValues) return [];
|
|
473
|
+
return Array.isArray(acrValues) ? acrValues : [acrValues];
|
|
474
|
+
}
|
|
467
475
|
function buildLoginHint(loginHint, params) {
|
|
468
|
-
const { options, action, message } = params;
|
|
469
|
-
const acrValues = (options === null || options === void 0 ? void 0 : options.acrValues)
|
|
470
|
-
let hints = (loginHint ? loginHint.split(" ") : []).concat((options === null || options === void 0 ? void 0 : options.loginHint) ? options === null || options === void 0 ? void 0 : options.loginHint.split(" ") : []).filter((hint) => !hint.startsWith("message:") && !hint.startsWith("action:"));
|
|
476
|
+
const { options, action, message, extraLoginHint } = params;
|
|
477
|
+
const acrValues = normalizeAcrValues(options === null || options === void 0 ? void 0 : options.acrValues);
|
|
478
|
+
let hints = (loginHint ? loginHint.split(" ") : []).concat((options === null || options === void 0 ? void 0 : options.loginHint) ? options === null || options === void 0 ? void 0 : options.loginHint.split(" ") : []).concat(extraLoginHint ? extraLoginHint.split(" ") : []).filter((hint) => !hint.startsWith("message:") && !hint.startsWith("action:"));
|
|
471
479
|
if (action) {
|
|
472
480
|
hints = hints.filter((h) => !h.startsWith("action:"));
|
|
473
481
|
if (acrValues.length === 1) {
|
|
@@ -574,6 +582,10 @@ const CriiptoVerifyProvider = (props) => {
|
|
|
574
582
|
const action = (_ref = (_props$action = props.action) !== null && _props$action !== void 0 ? _props$action : parseAction(loginHint)) !== null && _ref !== void 0 ? _ref : "login";
|
|
575
583
|
const message = (_props$message = props.message) !== null && _props$message !== void 0 ? _props$message : parseMessage(loginHint);
|
|
576
584
|
const sessionStore = props.sessionStore;
|
|
585
|
+
const beforeAuthorizeRef = useRef(props.beforeAuthorize);
|
|
586
|
+
useEffect(() => {
|
|
587
|
+
beforeAuthorizeRef.current = props.beforeAuthorize;
|
|
588
|
+
}, [props.beforeAuthorize]);
|
|
577
589
|
const refreshPKCE = function() {
|
|
578
590
|
var _ref2 = _asyncToGenerator(function* () {
|
|
579
591
|
if (props.pkce) return props.pkce;
|
|
@@ -592,8 +604,8 @@ const CriiptoVerifyProvider = (props) => {
|
|
|
592
604
|
};
|
|
593
605
|
}();
|
|
594
606
|
const buildOptions = useCallback((options) => {
|
|
595
|
-
var _props$responseType, _props$state, _props$nonce, _props$prompt, _props$scope, _options$pkce;
|
|
596
|
-
|
|
607
|
+
var _props$responseType, _props$state, _props$nonce, _props$prompt, _props$scope, _options$pkce, _beforeAuthorizeRef$c, _overrides$state, _overrides$nonce, _overrides$prompt, _overrides$scope, _overrides$uiLocales, _overrides$action, _overrides$message;
|
|
608
|
+
const resolved = _objectSpread2(_objectSpread2({
|
|
597
609
|
redirectUri: defaultRedirectUri(props.redirectUri),
|
|
598
610
|
responseType: (_props$responseType = props.responseType) !== null && _props$responseType !== void 0 ? _props$responseType : "code",
|
|
599
611
|
responseMode: props.responseMode
|
|
@@ -611,6 +623,25 @@ const CriiptoVerifyProvider = (props) => {
|
|
|
611
623
|
}),
|
|
612
624
|
extraUrlParams: props.criiptoSdk !== void 0 ? { criipto_sdk: props.criiptoSdk } : { criipto_sdk: `@criipto/verify-react@${version}` }
|
|
613
625
|
});
|
|
626
|
+
const overrides = (_beforeAuthorizeRef$c = beforeAuthorizeRef.current) === null || _beforeAuthorizeRef$c === void 0 ? void 0 : _beforeAuthorizeRef$c.call(beforeAuthorizeRef, {
|
|
627
|
+
acrValues: normalizeAcrValues(resolved.acrValues),
|
|
628
|
+
options: resolved
|
|
629
|
+
});
|
|
630
|
+
if (!overrides) return resolved;
|
|
631
|
+
return _objectSpread2(_objectSpread2({}, resolved), {}, {
|
|
632
|
+
state: (_overrides$state = overrides.state) !== null && _overrides$state !== void 0 ? _overrides$state : resolved.state,
|
|
633
|
+
nonce: (_overrides$nonce = overrides.nonce) !== null && _overrides$nonce !== void 0 ? _overrides$nonce : resolved.nonce,
|
|
634
|
+
prompt: (_overrides$prompt = overrides.prompt) !== null && _overrides$prompt !== void 0 ? _overrides$prompt : resolved.prompt,
|
|
635
|
+
scope: (_overrides$scope = overrides.scope) !== null && _overrides$scope !== void 0 ? _overrides$scope : resolved.scope,
|
|
636
|
+
uiLocales: (_overrides$uiLocales = overrides.uiLocales) !== null && _overrides$uiLocales !== void 0 ? _overrides$uiLocales : resolved.uiLocales,
|
|
637
|
+
loginHint: buildLoginHint(props.loginHint, {
|
|
638
|
+
options,
|
|
639
|
+
action: (_overrides$action = overrides.action) !== null && _overrides$action !== void 0 ? _overrides$action : action,
|
|
640
|
+
message: (_overrides$message = overrides.message) !== null && _overrides$message !== void 0 ? _overrides$message : message,
|
|
641
|
+
extraLoginHint: overrides.loginHint
|
|
642
|
+
}),
|
|
643
|
+
extraUrlParams: _objectSpread2(_objectSpread2({}, resolved.extraUrlParams), overrides.extraUrlParams)
|
|
644
|
+
});
|
|
614
645
|
}, [
|
|
615
646
|
pkce,
|
|
616
647
|
props.state,
|
|
@@ -1553,6 +1584,9 @@ var nobankid_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAABICA
|
|
|
1553
1584
|
//#region src/components/AuthMethodButton/logos/novipps.png
|
|
1554
1585
|
var novipps_default = "data:image/png;base64,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";
|
|
1555
1586
|
//#endregion
|
|
1587
|
+
//#region src/components/AuthMethodButton/logos/mobilepay.png
|
|
1588
|
+
var mobilepay_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAAkCAYAAAANdf2OAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAAlhJREFUeAHtmu1R20AQhteZ/I86iDoIHVgdQAdxB04HIRXgVGBSQaACQQWmA7kDoIJll3uNj0PfYjg0t8/Mju37+OFXe7u3dyL6xDBzIbYVK8V+kjEdETITW0NU5d77/ouMccBbLyAoQ1QVOkP/Fn0ZGf0Rwc4Cb1WRlzXjCoz5TUY7CAPnnrdWKlyXd+JB7MhoRgTKIeghDCwHzF1hXkFGPQgBSk4Dgec/hxH8zhGn/+Oh+SsizVh9SFY0Epl7EuwymkgzVssfPx2zzGvidhcVpQpEKgeML/gYt4dQUGS+Uhw2YuqN2WKxeGgbyK64uPCadPyV2J3YrdeeBWO+iT1SimC5d8ZJhISXJc8u9vqJrStc7NjF/IJSg12SaqzM2CUzn6V6M/ePwSEVp7Sz4GNldtoypgwELnka3+mD+UKRkNh7Ix97sbYDnCuaOdEEBpdi6slFQ/8/cglrtsQW+C85AWvDBHYYG5oxUQWGgJdiq5YEdE0zJrYHKyqgilt7YyEPQfe7NzRToguMZKd21jLsD82UWJVciO4WNprsIPgrtE36fgTNGl507B7f915fLnbifaYNH48hy45xWr013Xic181nV/mtUGh8+D7408DuRoN5ZLXlFS4FGW+Bpymjz3F54CldcqAUnnIYf1gFORlvmbrMuecpXdJMXeaYvyWjHm+ZD9pesTve3GKuvWbVhLdl67XMEVZKCNt7XtLw8bai6TA+vAC95x4vrhjAS3brmvaDtzIPfHHF8IB4FUTVO7idees7gqRVBd66NmHfGXZ3cXZgYxhReAKtoA9h3jxwjgAAAABJRU5ErkJggg==";
|
|
1589
|
+
//#endregion
|
|
1556
1590
|
//#region src/components/AuthMethodButton/logos/sebankid.png
|
|
1557
1591
|
var sebankid_default = "data:image/png;base64,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";
|
|
1558
1592
|
//#endregion
|
|
@@ -1577,8 +1611,8 @@ function AuthMethodButtonLogo(props) {
|
|
|
1577
1611
|
const logo = typeof props.logo === "string" ? /* @__PURE__ */ jsx("img", {
|
|
1578
1612
|
src: props.logo,
|
|
1579
1613
|
alt: ""
|
|
1580
|
-
}) : (_props$logo = props.logo) !== null && _props$logo !== void 0 ? _props$logo : acrValueToLogo(props.acrValue) ? /* @__PURE__ */ jsx("img", {
|
|
1581
|
-
src: acrValueToLogo(props.acrValue),
|
|
1614
|
+
}) : (_props$logo = props.logo) !== null && _props$logo !== void 0 ? _props$logo : acrValueToLogo(props.acrValue, props.loginHint) ? /* @__PURE__ */ jsx("img", {
|
|
1615
|
+
src: acrValueToLogo(props.acrValue, props.loginHint),
|
|
1582
1616
|
alt: ""
|
|
1583
1617
|
}) : /* @__PURE__ */ jsx("span", { children: "\xA0" });
|
|
1584
1618
|
if (logo) return /* @__PURE__ */ jsx("div", {
|
|
@@ -1587,7 +1621,7 @@ function AuthMethodButtonLogo(props) {
|
|
|
1587
1621
|
});
|
|
1588
1622
|
return null;
|
|
1589
1623
|
}
|
|
1590
|
-
function acrValueToLogo(value) {
|
|
1624
|
+
function acrValueToLogo(value, loginHint) {
|
|
1591
1625
|
if (value.startsWith("urn:grn:authn:dk:mitid:business")) return dkmitiderhverv_default;
|
|
1592
1626
|
if (value.startsWith("urn:grn:authn:dk:mitid")) return dkmitid_default;
|
|
1593
1627
|
if (value.startsWith("urn:grn:authn:fi:mobile")) return ftnmobile_default;
|
|
@@ -1595,7 +1629,11 @@ function acrValueToLogo(value) {
|
|
|
1595
1629
|
if (value.startsWith("urn:grn:authn:itsme")) return itsme_default;
|
|
1596
1630
|
if (value.startsWith("urn:grn:authn:se:bankid")) return sebankid_default;
|
|
1597
1631
|
if (value.startsWith("urn:grn:authn:no:bankid")) return nobankid_default;
|
|
1598
|
-
if (value.startsWith("urn:grn:authn:no:vipps"))
|
|
1632
|
+
if (value.startsWith("urn:grn:authn:no:vipps")) {
|
|
1633
|
+
const marketHint = loginHint === null || loginHint === void 0 ? void 0 : loginHint.split(" ").find((s) => s.startsWith("market:"));
|
|
1634
|
+
if (marketHint === "market:DK" || marketHint === "market:FI") return mobilepay_default;
|
|
1635
|
+
return novipps_default;
|
|
1636
|
+
}
|
|
1599
1637
|
if (value.startsWith("urn:grn:authn:se:frejaid")) return sefrejaid_default;
|
|
1600
1638
|
if (value.startsWith("urn:grn:authn:uk:oneid")) return ukoneid_default;
|
|
1601
1639
|
if (value.startsWith("urn:grn:authn:de:personalausweis")) return depersonalausweis_default;
|
|
@@ -1638,7 +1676,10 @@ function AuthMethodButtonComponent(props) {
|
|
|
1638
1676
|
"criipto-eid-btn--disabled": disabled,
|
|
1639
1677
|
"criipto-eid-btn--loading": props.loading
|
|
1640
1678
|
});
|
|
1641
|
-
const { title, subtitle } = acrValueToTitle(language, acrValue, {
|
|
1679
|
+
const { title, subtitle } = acrValueToTitle(language, acrValue, {
|
|
1680
|
+
disambiguate: isAmbiguous(acrValue, group.acrValues),
|
|
1681
|
+
loginHint: props.loginHint
|
|
1682
|
+
});
|
|
1642
1683
|
const contents = (_props$children = props.children) !== null && _props$children !== void 0 ? _props$children : /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
1643
1684
|
stringifyAction(language, action) ? `${stringifyAction(language, action)} ` : "",
|
|
1644
1685
|
title,
|
|
@@ -1647,6 +1688,7 @@ function AuthMethodButtonComponent(props) {
|
|
|
1647
1688
|
] });
|
|
1648
1689
|
const inner = /* @__PURE__ */ jsxs(React.Fragment, { children: [/* @__PURE__ */ jsx(AuthMethodButtonLogo, {
|
|
1649
1690
|
acrValue,
|
|
1691
|
+
loginHint: props.loginHint,
|
|
1650
1692
|
logo: props.loading ? /* @__PURE__ */ jsx(Spinner, {}) : props.logo
|
|
1651
1693
|
}), /* @__PURE__ */ jsx("span", { children: contents })] });
|
|
1652
1694
|
const commonProps = _objectSpread2(_objectSpread2({}, props), {}, {
|
|
@@ -1659,7 +1701,7 @@ function AuthMethodButtonComponent(props) {
|
|
|
1659
1701
|
})) }) : /* @__PURE__ */ jsx(React.Fragment, { children: /* @__PURE__ */ jsx(Button, _objectSpread2(_objectSpread2({}, commonProps), {}, { children: inner })) });
|
|
1660
1702
|
}
|
|
1661
1703
|
function AuthMethodButtonContainer(props) {
|
|
1662
|
-
var _ref, _props$language2, _ref2, _props$action2, _props$loading, _props$children2;
|
|
1704
|
+
var _ref, _props$language2, _ref2, _props$action2, _context$loginHint, _props$loading, _props$children2;
|
|
1663
1705
|
const { acrValue } = props;
|
|
1664
1706
|
const group = useContext(AuthButtonGroupContext);
|
|
1665
1707
|
const standalone = !group.multiple || isSingle(props.acrValue, group.acrValues);
|
|
@@ -1667,7 +1709,7 @@ function AuthMethodButtonContainer(props) {
|
|
|
1667
1709
|
const { initializePAR } = context;
|
|
1668
1710
|
const language = (_ref = (_props$language2 = props.language) !== null && _props$language2 !== void 0 ? _props$language2 : context.uiLocales) !== null && _ref !== void 0 ? _ref : "en";
|
|
1669
1711
|
const action = (_ref2 = (_props$action2 = props.action) !== null && _props$action2 !== void 0 ? _props$action2 : context.action) !== null && _ref2 !== void 0 ? _ref2 : "login";
|
|
1670
|
-
const className = `criipto-eid-btn ${acrValueToClassName(acrValue)}${props.className ? ` ${props.className}` : ""}`;
|
|
1712
|
+
const className = `criipto-eid-btn ${acrValueToClassName(acrValue)} ${loginHintToClassName((_context$loginHint = context.loginHint) !== null && _context$loginHint !== void 0 ? _context$loginHint : "")} ${props.className ? ` ${props.className}` : ""}`;
|
|
1671
1713
|
const [backdrop, setBackdrop] = useState(null);
|
|
1672
1714
|
const [loading, setLoading] = useState((_props$loading = props.loading) !== null && _props$loading !== void 0 ? _props$loading : false);
|
|
1673
1715
|
useEffect(() => {
|
|
@@ -1721,7 +1763,10 @@ function AuthMethodButtonContainer(props) {
|
|
|
1721
1763
|
});
|
|
1722
1764
|
}
|
|
1723
1765
|
};
|
|
1724
|
-
const { title, subtitle } = acrValueToTitle(language, acrValue, {
|
|
1766
|
+
const { title, subtitle } = acrValueToTitle(language, acrValue, {
|
|
1767
|
+
disambiguate: isAmbiguous(acrValue, group.acrValues),
|
|
1768
|
+
loginHint: context.loginHint
|
|
1769
|
+
});
|
|
1725
1770
|
const contents = (_props$children2 = props.children) !== null && _props$children2 !== void 0 ? _props$children2 : /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
1726
1771
|
stringifyAction(language, action) ? `${stringifyAction(language, action)} ` : "",
|
|
1727
1772
|
title,
|
|
@@ -1731,7 +1776,8 @@ function AuthMethodButtonContainer(props) {
|
|
|
1731
1776
|
const button = /* @__PURE__ */ jsxs(React.Fragment, { children: [/* @__PURE__ */ jsx(AuthMethodButtonComponent, _objectSpread2(_objectSpread2({}, props), {}, {
|
|
1732
1777
|
className,
|
|
1733
1778
|
onClick: handleClick,
|
|
1734
|
-
loading
|
|
1779
|
+
loading,
|
|
1780
|
+
loginHint: context.loginHint
|
|
1735
1781
|
})), backdrop] });
|
|
1736
1782
|
if (!props.href && acrValue === "urn:grn:authn:se:bankid:same-device") return /* @__PURE__ */ jsx(SEBankIDSameDeviceButton, {
|
|
1737
1783
|
redirectUri: props.redirectUri,
|
|
@@ -1740,6 +1786,7 @@ function AuthMethodButtonContainer(props) {
|
|
|
1740
1786
|
userAgent: props.userAgent,
|
|
1741
1787
|
logo: /* @__PURE__ */ jsx(AuthMethodButtonLogo, {
|
|
1742
1788
|
acrValue,
|
|
1789
|
+
loginHint: props.loginHint,
|
|
1743
1790
|
logo: props.logo
|
|
1744
1791
|
}),
|
|
1745
1792
|
disabled: props.disabled,
|
|
@@ -1754,6 +1801,10 @@ function acrValueToClassName(value) {
|
|
|
1754
1801
|
else return memo.concat([segment]);
|
|
1755
1802
|
}, []).map((className) => `criipto-eid-btn--${className}`).join(" ");
|
|
1756
1803
|
}
|
|
1804
|
+
function loginHintToClassName(value) {
|
|
1805
|
+
const marketHint = value.split(" ").find((s) => s.startsWith("market:"));
|
|
1806
|
+
return [marketHint ? `criipto-eid-btn--${marketHint === null || marketHint === void 0 ? void 0 : marketHint.replace(":", "-")}` : void 0].filter((id) => id !== void 0);
|
|
1807
|
+
}
|
|
1757
1808
|
function lowercaseFirst(input) {
|
|
1758
1809
|
if (!input) return input;
|
|
1759
1810
|
return input.substring(0, 1).toLowerCase() + input.substr(1, input.length);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["OAuth2Error","usePoll","searchParamsToPOJO","logo","PollStrategy","ForegroundStrategy","ReloadStrategy","dkmitiderhverv","dkmitid","ftnmobile","ftn","itsme","sebankid","nobankid","novipps","sefrejaid","ukoneid","depersonalausweis","idin"],"sources":["../src/context.ts","../package.json","../src/i18n/en.ts","../src/i18n/da.ts","../src/i18n/sv.ts","../src/i18n/nb.ts","../src/i18n/fi.ts","../src/i18n/de.ts","../src/i18n/nl.ts","../src/i18n/index.ts","../src/utils.ts","../src/memory-storage.ts","../src/provider.tsx","../src/device.ts","../src/components/SEBankIDSameDeviceButton/usePoll.ts","../src/components/SEBankIDSameDeviceButton/Poll.tsx","../src/hooks/usePageVisibility.ts","../src/components/SEBankIDSameDeviceButton/Foreground.tsx","../src/components/SEBankIDSameDeviceButton/shared.ts","../src/components/SEBankIDSameDeviceButton/Reload.tsx","../src/components/SEBankIDQRCode/logo@2x.png","../src/components/SEBankIDQRCode.tsx","../src/components/AuthButtonGroup.tsx","../src/components/Spinner/Spinner.tsx","../src/components/SEBankIDSameDeviceButton.tsx","../src/components/AuthMethodButton/logos/dkmitid.png","../src/components/AuthMethodButton/logos/dkmitiderhverv.png","../src/components/AuthMethodButton/logos/ftnmobile.png","../src/components/AuthMethodButton/logos/itsme.png","../src/components/AuthMethodButton/logos/nobankid.png","../src/components/AuthMethodButton/logos/novipps.png","../src/components/AuthMethodButton/logos/sebankid.png","../src/components/AuthMethodButton/logos/sefrejaid.png","../src/components/AuthMethodButton/logos/depersonalausweis.png","../src/components/AuthMethodButton/logos/ukoneid.png","../src/components/AuthMethodButton/logos/idin.png","../src/components/AuthMethodButton/logos/ftn.png","../src/components/AuthMethodButton/Logo.tsx","../src/components/Button.tsx","../src/components/AuthMethodButton.tsx","../src/components/AuthMethodSelector.tsx","../src/use-criipto-verify.ts"],"sourcesContent":["import CriiptoAuth, {\n OpenIDConfiguration,\n type AuthorizeUrlParamsOptional,\n type PKCE,\n type AuthorizeResponse,\n OAuth2Error,\n type PKCEPublicPart,\n} from '@criipto/auth-js';\nimport type { PopupAuthorizeParams, RedirectAuthorizeParams } from '@criipto/auth-js';\nimport { createContext } from 'react';\n\nexport type ResultSource = 'SEBankIDQrCode' | 'SEBankIDSameDeviceButton' | 'redirect' | 'popup';\nexport type Result =\n | { id_token: string; state?: string; source?: ResultSource }\n | { code: string; state?: string; source?: ResultSource }\n | OAuth2Error\n | Error;\nexport const actions = ['confirm', 'accept', 'approve', 'sign', 'login'] as const;\nexport type Action = (typeof actions)[number];\nexport type Claims = {\n iss: string;\n aud: string;\n identityscheme: string;\n authenticationtype: string;\n sub: string;\n iat: number;\n exp: number;\n [key: string]: string | number;\n};\n\nexport interface CriiptoVerifyContextInterface {\n loginWithRedirect: (params?: RedirectAuthorizeParams) => Promise<void>;\n loginWithPopup: (params?: PopupAuthorizeParams) => Promise<void>;\n checkSession: () => Promise<void>;\n logout: (params?: { redirectUri?: string; state?: string }) => Promise<void>;\n fetchOpenIDConfiguration: () => Promise<OpenIDConfiguration>;\n buildAuthorizeUrl: (options?: AuthorizeUrlParamsOptional) => Promise<string>;\n initializePAR: (options?: AuthorizeUrlParamsOptional) => Promise<URL>;\n generatePKCE: () => Promise<PKCE | undefined>;\n buildOptions: (\n options?: AuthorizeUrlParamsOptional | RedirectAuthorizeParams,\n ) => AuthorizeUrlParamsOptional;\n handleResponse: (\n response: AuthorizeResponse | (Error | OAuth2Error),\n params?: { pkce?: PKCE; redirectUri?: string; source?: ResultSource },\n ) => Promise<void>;\n responseType: 'token' | 'code';\n completionStrategy: 'client' | 'openidprovider';\n result: Result | null;\n claims: Claims | null;\n domain: string;\n redirectUri?: string;\n action: Action;\n message?: string;\n pkce?: PKCE | PKCEPublicPart;\n store: Storage;\n isLoading: boolean;\n isInitializing: boolean;\n acrValues?: string[];\n uiLocales?: string;\n client: CriiptoAuth;\n loginHint?: string;\n}\n\n/**\n * @ignore\n */\nconst stub = (): never => {\n throw new Error('You forgot to wrap your component in <CriiptoVerifyProvider>.');\n};\n\n/**\n * @ignore\n */\nconst initialContext = {\n loginWithRedirect: stub,\n loginWithPopup: stub,\n checkSession: stub,\n logout: stub,\n fetchOpenIDConfiguration: stub,\n buildAuthorizeUrl: stub,\n initializePAR: stub,\n generatePKCE: stub,\n buildOptions: stub,\n handleResponse: stub,\n responseType: 'token' as 'token' | 'code',\n completionStrategy: 'client' as 'client' | 'openidprovider',\n result: null,\n claims: null,\n domain: '',\n action: 'login' as Action,\n pkce: undefined,\n store: null as any as Storage,\n isLoading: false,\n isInitializing: true,\n client: null as any as CriiptoAuth,\n loginHint: undefined,\n};\n\nconst CriiptoVerifyContext = createContext<CriiptoVerifyContextInterface>(initialContext);\n\nexport default CriiptoVerifyContext;\n","","export const en = {\n loginWith: 'Login with',\n approveWith: 'Approve with',\n signWith: 'Sign with',\n confirmWith: 'Confirm with',\n acceptWith: 'Accept with',\n sameDevice: 'On this device',\n anotherDevice: 'With your SSN',\n anotherDeviceQR: 'On another device',\n mitidBusiness: 'MitID Business',\n finnishMobileID: 'Finnish Mobile Certificate',\n finnishBankID: 'Finnish Bank ID',\n swedishBankID: 'Swedish BankID',\n norwegianBankID: 'Norwegian BankID',\n biometrics: 'Biometrics',\n openAndScan: 'Open the BankID app on your mobile device and scan the QR code.',\n thisIsTheQR: 'This is a BankID QR Code. You can click it to view it in full screen.',\n completingLogin: 'Completing your login.',\n} as const;\n","import { type I18N } from '.';\n\nexport const da = {\n loginWith: 'Login med',\n approveWith: 'Godkend med',\n signWith: 'Underskriv med',\n confirmWith: 'Bekræft med',\n acceptWith: 'Accepter med',\n sameDevice: 'På denne enhed',\n anotherDevice: 'Med dit personnummer',\n anotherDeviceQR: 'På anden enhed',\n mitidBusiness: 'MitID Erhverv',\n finnishMobileID: 'Finsk Mobilcertifikat',\n finnishBankID: 'Finsk Bank ID',\n swedishBankID: 'Svensk BankID',\n norwegianBankID: 'Norsk BankID',\n biometrics: 'Biometri',\n openAndScan: 'Åbn BankID appen på din telefon og scan QR koden.',\n thisIsTheQR: 'Dette er en BankID QR-kode. Du kan klikke på den for at se den i fuld skærm.',\n completingLogin: 'Fuldfører dit login.',\n} satisfies I18N;\n","import { type I18N } from '.';\n\nexport const sv = {\n loginWith: 'Logga in med',\n approveWith: 'Godkänn med',\n signWith: 'Signera med',\n confirmWith: 'Bekräfta med',\n acceptWith: 'Acceptera med',\n sameDevice: 'På denna enhet',\n anotherDevice: 'Med ditt personnummer',\n anotherDeviceQR: 'På annan enhet',\n mitidBusiness: 'MitID Erhverv',\n finnishMobileID: 'Finskt Mobilcertifikat',\n finnishBankID: 'Finskt Bank ID',\n swedishBankID: 'Svenskt BankID',\n norwegianBankID: 'Norska BankID',\n biometrics: 'Biometri',\n openAndScan: 'Öppna BankID-appen på din mobila enhet och skanna QR-koden.',\n thisIsTheQR: 'Detta är en QR-kod från BankID. Du kan klicka på den för att visa den i fullskärm.',\n completingLogin: 'Slutför din inloggning.',\n} satisfies I18N;\n","import { type I18N } from '.';\n\nexport const nb = {\n loginWith: 'Logg inn med',\n approveWith: 'Godkjenne med',\n signWith: 'Signer med',\n confirmWith: 'Bekreft med',\n acceptWith: 'Aksepterer med',\n sameDevice: 'På denne enhet',\n anotherDevice: 'Med personnummeret ditt',\n anotherDeviceQR: 'På annan enhet',\n mitidBusiness: 'MitID Erhverv',\n finnishMobileID: 'Finsk Mobilsertifikat',\n finnishBankID: 'Finsk Bank ID',\n swedishBankID: 'Svensk BankID',\n norwegianBankID: 'Norsk BankID',\n biometrics: 'Biometri',\n openAndScan: 'Åpne BankID-appen på mobilenheten din og skann QR-koden.',\n thisIsTheQR: 'Dette er en BankID QR-kode. Du kan klikke på den for å se den i fullskjerm.',\n completingLogin: 'Fullfører påloggingen.',\n} satisfies I18N;\n","import type { I18N } from '.';\n\nexport const fi = {\n loginWith: 'Kirjaudu sisään',\n approveWith: 'Hyväksy',\n signWith: 'Allekirjoita',\n confirmWith: 'Vahvista',\n acceptWith: 'Hyväksy',\n sameDevice: 'Tällä laitteella',\n anotherDevice: 'Henkilötunnuksellasi',\n anotherDeviceQR: 'Toisella laitteella',\n mitidBusiness: 'MitID Businessilla',\n finnishMobileID: 'Suomalaisella Mobiilivarmenteella',\n finnishBankID: 'Suomalaisella BankID:llä',\n swedishBankID: 'Ruotsalaisella BankID:llä',\n norwegianBankID: 'Norjalaisella BankID:llä',\n biometrics: 'Biometrisella tunnistautumisella',\n openAndScan: 'Avaa BankID-sovellus mobiililaitteellasi ja skannaa QR-koodi.',\n thisIsTheQR: 'Tämä on BankID-QR-koodi. Voit napsauttaa sitä nähdäksesi sen koko näytöllä',\n completingLogin: 'Sisäänkirjautumista viimeistellään.',\n} satisfies I18N;\n","import type { I18N } from '.';\n\nexport const de = {\n loginWith: 'Anmelden mit',\n approveWith: 'Genehmigen mit',\n signWith: 'Unterschreiben mit',\n confirmWith: 'Bestätigen mit',\n acceptWith: 'Akzeptieren mit',\n sameDevice: 'Auf diesem Gerät',\n anotherDevice: 'Mit Ihrer Sozialversicherungsnummer',\n anotherDeviceQR: 'Auf einem anderen Gerät',\n mitidBusiness: 'MitID Business',\n finnishMobileID: 'Finnischem Mobilfunkzertifikat',\n finnishBankID: 'Finnische BankID',\n swedishBankID: 'Schwedische BankID',\n norwegianBankID: 'Norwegische BankID',\n biometrics: 'Biometrie',\n openAndScan: 'Öffnen Sie die BankID-App auf Ihrem mobilen Endgerät und scannen Sie den QR-Code.',\n thisIsTheQR:\n 'Dies ist ein BankID QR-Code. Sie können darauf klicken, um ihn im Vollbildmodus anzuzeigen',\n completingLogin: 'Ihre Anmeldung wird abgeschlossen.',\n} satisfies I18N;\n","import type { I18N } from '.';\n\nexport const nl = {\n loginWith: 'Inloggen met',\n approveWith: 'Goedkeuren met',\n signWith: 'Ondertekenen met',\n confirmWith: 'Bevestigen met',\n acceptWith: 'Accepteren met',\n sameDevice: 'Op dit apparaat',\n anotherDevice: 'Met uw SSN',\n anotherDeviceQR: 'Op een ander apparaat',\n mitidBusiness: 'MitID Business',\n finnishMobileID: 'Finse mobiel certificaat',\n finnishBankID: 'Finse BankID',\n swedishBankID: 'Zweedse BankID',\n norwegianBankID: 'Noorse BankID',\n biometrics: 'Biometrie',\n openAndScan: 'Open de BankID-app op uw mobiele apparaat en scan de QR-code.',\n thisIsTheQR:\n 'Dit is een BankID QR-code. U kunt erop klikken om het in een volledig scherm te bekijken',\n completingLogin: 'Uw login voltooien.',\n} satisfies I18N;\n","import { en } from './en';\nimport { da } from './da';\nimport { sv } from './sv';\nimport { nb } from './nb';\nimport { fi } from './fi';\nimport { de } from './de';\nimport { nl } from './nl';\nimport { assertUnreachable } from '../utils';\n\nexport type Language = 'en' | 'da' | 'sv' | 'nb' | 'fi' | 'de' | 'nl';\nexport type I18N = Record<keyof typeof en, string>;\n\nexport function getI18n(language: Language): I18N {\n switch (language) {\n case 'en':\n return en;\n case 'da':\n return da;\n case 'sv':\n return sv;\n case 'nb':\n return nb;\n case 'fi':\n return fi;\n case 'de':\n return de;\n case 'nl':\n return nl;\n default:\n assertUnreachable(language);\n }\n}\n","import type { Action } from './context';\nimport { getI18n, type Language } from './i18n';\n\nexport const DKMITID_PREFIX = 'urn:grn:authn:dk:mitid';\nexport const DKMITID_BUSINESS = 'urn:grn:authn:dk:mitid:business';\nexport const FTN_PREFIX = 'urn:grn:authn:fi';\n\nexport function lowestMitIDValue(input: string[]): string | null {\n let dkmitidMethod: string | null = null;\n\n input.forEach((s) => {\n if (s.startsWith(DKMITID_PREFIX) && s !== DKMITID_BUSINESS) {\n if (!dkmitidMethod) {\n dkmitidMethod = s;\n } else {\n let newLevel = s.replace(DKMITID_PREFIX, '');\n let oldLevel = dkmitidMethod.replace(DKMITID_PREFIX, '');\n if (newLevel === ':low' && [':substantial', ':high'].includes(oldLevel)) {\n dkmitidMethod = s;\n } else if (newLevel === ':substantial' && oldLevel === ':high') {\n dkmitidMethod = s;\n }\n }\n }\n });\n\n return dkmitidMethod;\n}\n\nfunction autoTitleCase(input: string) {\n var segments = input.split(/:|-/).map((segment) => {\n segment = segment.replace(/id(\\s|$)/, 'ID');\n if (segment.length === 2) return segment.toUpperCase();\n return segment.substr(0, 1).toUpperCase() + segment.substr(1);\n });\n return segments.join(' ');\n}\n\nexport function assertUnreachable(x: never): never {\n throw new Error(\"Didn't expect to get here\");\n}\n\nexport function stringifyAction(language: Language, action: Action): string {\n const i18n = getI18n(language);\n\n switch (action) {\n case 'login':\n return i18n.loginWith;\n case 'approve':\n return i18n.approveWith;\n case 'sign':\n return i18n.signWith;\n case 'confirm':\n return i18n.confirmWith;\n case 'accept':\n return i18n.acceptWith;\n default:\n assertUnreachable(action);\n }\n}\n\nexport function acrValueToProviderPrefix(value: string) {\n value = value.replace('urn:grn:authn:', '');\n\n if (value.startsWith('fi')) {\n return 'fi';\n } else if (value.startsWith('itsme')) {\n return 'itsme';\n } else {\n return value.split(':').slice(0, 2).join(':');\n }\n}\n\nexport function acrValueToTitle(\n language: Language,\n value: string,\n { disambiguate }: { disambiguate: boolean },\n): { title: string; subtitle?: string } {\n const i18n = getI18n(language);\n value = value.replace('urn:grn:authn:', '');\n const provider = acrValueToProviderPrefix(value);\n\n if (provider === 'dk:mitid') {\n let suffix = value.replace('dk:mitid:', '');\n if (suffix === 'business') {\n return {\n title: i18n.mitidBusiness,\n };\n }\n\n return { title: 'MitID' };\n }\n if (value === 'fi:mobile-id') {\n return {\n title: i18n.finnishMobileID,\n };\n }\n if (value === 'fi:bank-id') {\n return {\n title: i18n.finnishBankID,\n };\n }\n if (provider === 'fi') {\n return { title: autoTitleCase(value).replace('FI', 'FTN') };\n }\n if (provider === 'itsme') {\n return { title: autoTitleCase(value).replace('me', 'ME') };\n }\n if (provider === 'se:bankid') {\n let subtitle: string | undefined = undefined;\n let suffix = value.replace('se:bankid:', '');\n let title = 'BankID';\n\n if (suffix === 'same-device') {\n subtitle = i18n.sameDevice;\n }\n if (suffix === 'another-device') {\n subtitle = i18n.anotherDevice;\n }\n if (suffix === 'another-device:qr') {\n subtitle = i18n.anotherDeviceQR;\n }\n if (disambiguate) {\n title = i18n.swedishBankID;\n }\n\n return { title, subtitle };\n }\n if (provider === 'no:bankid') {\n let subtitle: string | undefined = undefined;\n let title = 'BankID';\n if (value.endsWith(':substantial')) {\n subtitle = i18n.biometrics;\n }\n if (disambiguate) {\n title = i18n.norwegianBankID;\n }\n return { title, subtitle };\n }\n if (provider === 'no:vipps') {\n return { title: autoTitleCase(value).replace('NO ', '') };\n }\n if (provider === 'se:frejaid') {\n return { title: 'FrejaID' };\n }\n if (provider === 'uk:oneid') {\n return { title: 'OneID' };\n }\n if (provider === 'de:personalausweis') {\n return { title: 'Personalausweis' };\n }\n\n return { title: autoTitleCase(value) };\n}\n\nexport function filterAcrValues(input: string[]) {\n let original = input.slice();\n let dkmitidMethod: string | null = lowestMitIDValue(input);\n let reduced = input.slice();\n\n if (dkmitidMethod) {\n reduced = input\n .filter((s) => !s.startsWith(DKMITID_PREFIX) || s === DKMITID_BUSINESS)\n .concat([dkmitidMethod])\n .sort((a, b) => original.indexOf(a) - original.indexOf(b));\n }\n\n if (input.includes(`${FTN_PREFIX}:all`)) {\n if (!reduced.includes(`${FTN_PREFIX}:bank-id`)) reduced.push(`${FTN_PREFIX}:bank-id`);\n if (!reduced.includes(`${FTN_PREFIX}:mobile-id`)) reduced.push(`${FTN_PREFIX}:mobile-id`);\n reduced = reduced.filter((s) => s !== `${FTN_PREFIX}:all`);\n }\n return reduced;\n}\n\nexport function isSingle(acrValue: string, acrValues: string[]) {\n const provider = acrValueToProviderPrefix(acrValue);\n const count = acrValues.reduce(\n (memo, acrValue) => memo + (acrValueToProviderPrefix(acrValue) === provider ? 1 : 0),\n 0,\n );\n return count === 1;\n}\n\nconst ambigousProviders = ['se:bankid', 'no:bankid'];\n/**\n * A provider is considered ambiguous iff:\n * 1. It is in the list of ambiguous providers\n * 2. There is another ambiguous provider in the arc values list\n */\nexport function isAmbiguous(acrValue: string, acrValues: string[]) {\n const provider = acrValueToProviderPrefix(acrValue);\n const isProviderAmbiguous = ambigousProviders.includes(provider);\n const otherAmbiguousProvider =\n acrValues.find((otherAcrValue) => {\n const otherProvider = acrValueToProviderPrefix(otherAcrValue);\n return provider != otherProvider && ambigousProviders.includes(otherProvider);\n }) != null;\n\n return isProviderAmbiguous && otherAmbiguousProvider;\n}\n\nexport function trySessionStorage() {\n try {\n if (typeof sessionStorage === 'undefined') {\n return null;\n }\n return sessionStorage;\n } catch (err) {\n /**\n * Failed to read the 'sessionStorage' property from 'Window': Access is denied for this document.\n * (if storage is disabled in the browser)\n */\n return null;\n }\n}\n","export function createMemoryStorage(): Storage {\n let store: { [key: string]: string } = {};\n\n return {\n getItem(key: string) {\n return store[key] || null;\n },\n setItem(key: string, value: any) {\n store[key] = value.toString();\n },\n removeItem(key: string) {\n delete store[key];\n },\n clear() {\n store = {};\n },\n key(index) {\n return Object.keys(store)[index];\n },\n get length() {\n return Object.keys(store).length;\n },\n };\n}\n","import React, { useMemo, useState, useCallback, useEffect } from 'react';\nimport CriiptoAuth, {\n type AuthorizeUrlParamsOptional,\n clearPKCEState,\n generatePKCE,\n OAuth2Error,\n OpenIDConfiguration,\n type PKCE,\n type PKCEPublicPart,\n type Prompt,\n parseAuthorizeResponseFromLocation,\n} from '@criipto/auth-js';\n\nimport CriiptoVerifyContext, {\n type CriiptoVerifyContextInterface,\n type Action,\n type Result,\n type Claims,\n actions,\n type ResultSource,\n} from './context';\nimport type { AuthorizeResponse, RedirectAuthorizeParams, ResponseType } from '@criipto/auth-js';\n\nimport { version } from '../package.json';\nimport { filterAcrValues, trySessionStorage } from './utils';\nimport jwtDecode from 'jwt-decode';\nimport { createMemoryStorage } from './memory-storage';\n\nconst SESSION_KEY = `@criipto-verify-react/session`;\n\nexport interface CriiptoVerifyProviderOptions {\n domain: string;\n clientID: string;\n /**\n * @deprecated Development use only\n */\n protocol?: 'https' | 'http';\n\n redirectUri?: string;\n children: React.ReactNode;\n pkce?: PKCEPublicPart;\n state?: string;\n nonce?: string;\n prompt?: Prompt;\n scope?: string;\n uiLocales?: string;\n loginHint?: string;\n /**\n * Enables storage and automatic fetch of tokens\n * by utilizing browser storage and SSO silent logins.\n * Make sure \"SSO for OAuth2\" is enabled on your Criipto Domain.\n * Only works for `response: 'token'` (default)\n */\n sessionStore?: Storage;\n /**\n * Will ammend the login_hint parameter with `action:{action}` which will adjust texsts in certain flows.\n * Default: 'login'\n */\n action?: Action;\n /**\n * Will ammend the login_hint parameter with `message:{base64(message)}` which will set a login/aprove message where available (Danish MitID).\n */\n message?: string;\n /**\n * Note: In most cases modifying this setting **is not needed**. Defaults will work with almost all React SPA cases.\n * By default @criipto/verify-react will do PKCE on your behalf and return a jwt token.\n * However if you wish you can disable this and get the raw `code` response by setting `response` to 'code'.\n */\n response?: 'token' | 'code';\n /*\n * Note: In most cases modifying this setting **is not needed**. Defaults will work with almost all React SPA cases.\n * By default @criipto/verify-react will do as much as work on your behalf\n * by interpreting URL parameters and responses with `useCriiptoVerify()` via the default value 'client'.\n * If you wish to only render a UI and redirect to the Criipto IDP for server side code exchange, you can choose 'openidprovider'.\n */\n completionStrategy?: 'client' | 'openidprovider';\n\n /**\n * @deprecated Criipto internal use\n */\n criiptoSdk?: null | string;\n /**\n * @deprecated Criipto internal use\n */\n responseType?: ResponseType | 'code id_token';\n /**\n * @deprecated Criipto internal use\n */\n responseMode?: 'query' | 'form_post' | 'fragment' | 'json' | 'post_message';\n}\n\nexport const ACTION_SUPPORTING_ACR_VALUES = [\n 'urn:grn:authn:dk:mitid:low',\n 'urn:grn:authn:dk:mitid:substantial',\n 'urn:grn:authn:dk:mitid:high',\n 'urn:grn:authn:se:bankid:same-device',\n 'urn:grn:authn:se:bankid:another-device:qr',\n];\n\nexport const MESSAGE_SUPPORTING_ACR_VALUES = [\n 'urn:grn:authn:dk:mitid:low',\n 'urn:grn:authn:dk:mitid:substantial',\n 'urn:grn:authn:dk:mitid:high',\n 'urn:grn:authn:se:bankid:same-device',\n 'urn:grn:authn:se:bankid:another-device:qr',\n];\n\nexport function buildLoginHint(\n loginHint: string | undefined | null,\n params: { options?: AuthorizeUrlParamsOptional; action?: Action; message?: string },\n) {\n const { options, action, message } = params;\n const acrValues = options?.acrValues\n ? Array.isArray(options?.acrValues)\n ? options?.acrValues\n : [options?.acrValues]\n : [];\n let hints = (loginHint ? loginHint.split(' ') : [])\n .concat(options?.loginHint ? options?.loginHint.split(' ') : [])\n .filter((hint) => !hint.startsWith('message:') && !hint.startsWith('action:'));\n if (action) {\n hints = hints.filter((h) => !h.startsWith('action:'));\n if (acrValues.length === 1) {\n if (ACTION_SUPPORTING_ACR_VALUES.includes(acrValues[0])) {\n hints.push(`action:${action}`);\n }\n } else if (acrValues.length >= 2) {\n if (acrValues.some((v) => ACTION_SUPPORTING_ACR_VALUES.includes(v))) {\n hints.push(`action:${action}`);\n }\n } else {\n hints.push(`action:${action}`);\n }\n }\n\n if (message) {\n if (acrValues.length === 1) {\n if (MESSAGE_SUPPORTING_ACR_VALUES.includes(acrValues[0])) {\n hints.push(`message:${btoa(message)}`);\n }\n } else if (acrValues.length >= 2) {\n if (acrValues.some((v) => MESSAGE_SUPPORTING_ACR_VALUES.includes(v))) {\n hints.push(`message:${btoa(message)}`);\n }\n } else {\n hints.push(`message:${btoa(message)}`);\n }\n }\n\n return hints.length ? hints.join(' ') : undefined;\n}\n\nfunction parseAction(input?: string): Action | undefined {\n if (!input) return;\n\n const segments = input.split(' ');\n const actionCandidate = segments.find((s) => s.startsWith('action:'));\n if (!actionCandidate) return;\n const action = actionCandidate.replace('action:', '');\n if (actions.includes(action as any)) return action as Action;\n return;\n}\n\nfunction tryBase64Decode(input: string) {\n try {\n return atob(input);\n } catch {\n return null;\n }\n}\nfunction parseMessage(input?: string): string | undefined {\n if (!input) return;\n const segments = input.split(' ');\n const messageCandidate = segments.find((s) => s.startsWith('message:'));\n if (!messageCandidate) return;\n\n const message = messageCandidate.replace('message:', '');\n return tryBase64Decode(message) ?? message;\n}\n\nfunction defaultRedirectUri(input?: string): string {\n if (input) return input;\n if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {\n return window.location.origin + window.location.pathname;\n }\n\n throw new Error('Unable to determine default redirect uri, please provide a redirectUri');\n}\n\nconst pkceStore = (() => {\n const sessionStorage = trySessionStorage();\n if (sessionStorage === null) {\n console.warn(\n 'Creating memory store for PKCE values as no sessionStorage is available. Authentication may be broken.',\n );\n return createMemoryStorage();\n }\n return sessionStorage;\n})();\n\nconst CriiptoVerifyProvider = (props: CriiptoVerifyProviderOptions): React.ReactElement => {\n const client = useMemo(\n () =>\n new CriiptoAuth({\n domain: props.domain,\n clientID: props.clientID,\n store: pkceStore,\n redirectUri: defaultRedirectUri(props.redirectUri),\n protocol: props.protocol,\n }),\n [props.domain, props.clientID, props.redirectUri, props.protocol],\n );\n\n const [configuration, setConfiguration] = useState<OpenIDConfiguration | null>(null);\n useEffect(() => {\n let isSubscribed = true;\n (async () => {\n const configuration = await client.fetchOpenIDConfiguration();\n if (isSubscribed) setConfiguration(configuration);\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [client]);\n\n const [result, setResult] = useState<Result | null>(null);\n\n // Verify that domain and client id are valid; surface failures as the hook's `error`.\n useEffect(() => {\n let isSubscribed = true;\n (async () => {\n try {\n await client.fetchCriiptoConfiguration();\n } catch (error) {\n if (!isSubscribed) return;\n const err = error instanceof Error ? error : new Error(String(error));\n setResult((prev) => prev ?? err);\n }\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [client]);\n const claims = useMemo(() => {\n if (!result) return null;\n if (!('id_token' in result)) return null;\n return jwtDecode<Claims>(result.id_token);\n }, [result]);\n const [isLoading, setIsLoading] = useState(false);\n const [isInitializing, setIsInitializing] = useState(true);\n const [pkce, setPKCE] = useState<PKCE | PKCEPublicPart | undefined>(props.pkce);\n const responseType = props.response || 'token';\n const completionStrategy = props.completionStrategy || 'client';\n const uiLocales = props.uiLocales;\n const loginHint = props.loginHint;\n const action = props.action ?? parseAction(loginHint) ?? 'login';\n const message = props.message ?? parseMessage(loginHint);\n const sessionStore = props.sessionStore;\n\n const refreshPKCE = async () => {\n if (props.pkce) return props.pkce;\n if (responseType !== 'token' || completionStrategy !== 'client') {\n clearPKCEState(pkceStore);\n setPKCE(undefined);\n return undefined;\n }\n\n clearPKCEState(pkceStore);\n\n const pkce = await generatePKCE();\n setPKCE(pkce);\n return pkce;\n };\n\n const buildOptions = useCallback(\n (\n options?: AuthorizeUrlParamsOptional | RedirectAuthorizeParams,\n ): AuthorizeUrlParamsOptional => {\n return {\n redirectUri: defaultRedirectUri(props.redirectUri),\n responseType: (props.responseType ?? 'code') as ResponseType,\n responseMode: props.responseMode,\n ...(options || {}),\n state: props.state ?? options?.state,\n nonce: props.nonce ?? options?.nonce,\n prompt: props.prompt ?? options?.prompt,\n scope: props.scope ?? options?.scope,\n uiLocales: uiLocales ?? options?.uiLocales,\n pkce: options?.pkce ?? pkce,\n loginHint: buildLoginHint(props.loginHint, { options, action, message }),\n extraUrlParams:\n props.criiptoSdk !== undefined\n ? {\n criipto_sdk: props.criiptoSdk,\n }\n : {\n criipto_sdk: `@criipto/verify-react@${version}`,\n },\n };\n },\n [\n pkce,\n props.state,\n props.nonce,\n props.prompt,\n props.scope,\n uiLocales,\n action,\n message,\n props.redirectUri,\n props.criiptoSdk,\n props.loginHint,\n props.responseMode,\n props.responseType,\n ],\n );\n\n const buildAuthorizeUrl = useCallback(\n async (options?: AuthorizeUrlParamsOptional) => {\n return await client.buildAuthorizeUrl(client.buildAuthorizeParams(buildOptions(options)));\n },\n [client, buildOptions],\n );\n\n const initializePAR = useCallback(\n async (options?: AuthorizeUrlParamsOptional) => {\n return (\n await client.pushAuthorizationRequest(client.buildAuthorizeParams(buildOptions(options)))\n ).authorizeUrl;\n },\n [client, buildOptions],\n );\n\n const handleResponse = useCallback(\n async (\n response: AuthorizeResponse | (Error | OAuth2Error),\n params: { pkce?: PKCE; redirectUri?: string; source?: ResultSource } = {},\n ) => {\n if (response instanceof OAuth2Error) {\n setResult(response);\n } else if (response instanceof Error) {\n setResult(response);\n } else if (params.pkce && responseType === 'token') {\n let _redirectUri = params.redirectUri || defaultRedirectUri(props.redirectUri);\n if (!_redirectUri)\n throw new Error(\n 'redirectUri must be configured globally or per authentication component',\n );\n\n await client\n .processResponse(response, {\n code_verifier: params.pkce.code_verifier,\n redirect_uri: _redirectUri,\n })\n .then((response) => {\n if (response?.code)\n setResult({ code: response.code, state: response.state, source: params.source });\n else if (response?.id_token) {\n setResult({\n id_token: response.id_token,\n state: response.state,\n source: params.source,\n });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n } else setResult(null);\n })\n .catch((err: OAuth2Error) => {\n setResult(err);\n });\n } else {\n if (response?.code)\n setResult({ code: response.code, state: response.state, source: params.source });\n else if (response?.id_token) {\n setResult({ id_token: response.id_token, state: response.state, source: params.source });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n } else if (response?.error)\n setResult(new OAuth2Error(response.error, response.error_description, response.state));\n else setResult(null);\n }\n\n refreshPKCE(); // Clear out session storage and recreate PKCE values if being used\n },\n [refreshPKCE, responseType, setResult, client, sessionStore, props.redirectUri],\n );\n\n const checkSession = useCallback(async () => {\n return client\n .checkSession({ redirectUri: defaultRedirectUri(props.redirectUri) })\n .then((response) => {\n if (response?.code) setResult({ code: response.code });\n else if (response?.id_token) {\n setResult({ id_token: response.id_token });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n } else setResult(null);\n });\n }, [sessionStore, client, props.redirectUri]);\n\n const logout = useCallback(\n async (params?: { redirectUri?: string; state?: string }) => {\n sessionStore?.removeItem(SESSION_KEY);\n await client.logout({\n redirectUri: params?.redirectUri ?? defaultRedirectUri(props.redirectUri),\n state: params?.state,\n });\n },\n [sessionStore, client, props.redirectUri],\n );\n\n const context = useMemo<CriiptoVerifyContextInterface>(() => {\n return {\n loginWithRedirect: async (params) => {\n const pkce = await refreshPKCE();\n await client.redirect.authorize(buildOptions({ ...params, pkce }));\n },\n loginWithPopup: async (params) => {\n return client.popup\n .authorize(buildOptions(params))\n .then((response) => {\n if (response?.code)\n setResult({ code: response.code, state: response.state, source: 'popup' });\n else if (response?.id_token)\n setResult({ id_token: response.id_token, state: response.state, source: 'popup' });\n else setResult(null);\n })\n .catch((err: OAuth2Error) => {\n setResult(err);\n });\n },\n checkSession,\n logout,\n fetchOpenIDConfiguration: () => client.fetchOpenIDConfiguration(),\n buildAuthorizeUrl,\n initializePAR,\n generatePKCE: async () => {\n if (responseType !== 'token' || completionStrategy !== 'client') return;\n return await generatePKCE();\n },\n buildOptions,\n handleResponse,\n responseType,\n completionStrategy,\n result,\n claims,\n domain: client.domain,\n redirectUri: defaultRedirectUri(props.redirectUri),\n action,\n message,\n pkce,\n store: pkceStore,\n isLoading,\n isInitializing,\n acrValues: configuration ? filterAcrValues(configuration.acr_values_supported) : undefined,\n client,\n uiLocales,\n loginHint,\n };\n }, [\n client,\n props.redirectUri,\n responseType,\n completionStrategy,\n result,\n claims,\n action,\n message,\n pkce,\n props.state,\n props.prompt,\n isLoading,\n isInitializing,\n handleResponse,\n logout,\n configuration,\n uiLocales,\n checkSession,\n loginHint,\n ]);\n\n useEffect(() => {\n setIsInitializing(false);\n if (!client.redirect.hasMatch()) {\n refreshPKCE(); // Fresh request, setup PKCE\n return;\n }\n\n let isSubscribed = true;\n setIsLoading(true);\n\n const params = parseAuthorizeResponseFromLocation(window.location);\n if (params.code && responseType === 'code') {\n setIsLoading(false);\n setResult({ code: params.code, source: 'redirect', state: params.state });\n refreshPKCE(); // Clear out session storage and recreate PKCE values if being used\n return;\n }\n\n (async () => {\n await Promise.resolve(); // wait for the initial cleanup in Strict mode - avoids double mutation\n if (!isSubscribed) return;\n\n try {\n const response = await client.redirect.match();\n if (!isSubscribed) return;\n\n if (response?.code) {\n setResult({ code: response.code, source: 'redirect', state: response.state });\n } else if (response?.id_token) {\n setResult({ id_token: response.id_token, source: 'redirect', state: response.state });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n resetRedirectState(window);\n } else setResult(null);\n } catch (err: any) {\n if (!isSubscribed) return;\n if (err instanceof OAuth2Error) {\n setResult(err);\n } else if (err instanceof Error) {\n setResult(err);\n } else {\n setResult(new Error(err?.toString() ?? 'Unknown error ocurred'));\n }\n } finally {\n if (!isSubscribed) return;\n setIsLoading(false);\n refreshPKCE(); // Clear out session storage and recreate PKCE values if being used\n }\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [props.pkce, responseType]);\n\n /*\n * Fetch claims from session store if available\n */\n useEffect(() => {\n if (!sessionStore || claims) return;\n if (!claims) {\n // No result available, fetch from session store\n const token = sessionStore.getItem(SESSION_KEY);\n if (!token) return;\n\n setResult({ id_token: token });\n return;\n }\n }, [sessionStore, claims]);\n\n /*\n * Unset result if claims are expired\n */\n useEffect(() => {\n if (!claims) return;\n if (!sessionStore) return;\n\n const interval = setInterval(() => {\n const now = Date.now();\n if (claims.exp < now / 1000) {\n setResult(null);\n sessionStore?.removeItem(SESSION_KEY);\n return;\n }\n }, 5000);\n\n return () => clearInterval(interval);\n }, [sessionStore, claims, result]);\n\n /**\n * Fresh page load SSO check\n */\n useEffect(() => {\n setIsInitializing(false);\n if (!sessionStore) return;\n if (client.redirect.hasMatch()) return; // Do not issue SSO check if we're just being redirected back to\n if (sessionStore.getItem(SESSION_KEY)) return;\n let isSubscribed = true;\n\n setIsLoading(true);\n checkSession()\n .catch((err) => {\n console.error('session silent check error', err);\n })\n .finally(() => {\n if (isSubscribed) setIsLoading(false);\n });\n\n return () => {\n isSubscribed = false;\n };\n }, [sessionStore, client]);\n\n return (\n <CriiptoVerifyContext.Provider value={context}>{props.children}</CriiptoVerifyContext.Provider>\n );\n};\n\nexport default CriiptoVerifyProvider;\n\nexport function resetRedirectState(window: Window) {\n const url = new URL(window.location.href);\n url.searchParams.delete('code');\n url.searchParams.delete('state');\n\n window.history.replaceState({}, window.document.title, url.pathname + url.search);\n}\n","import { UAParser } from '@ua-parser-js/pro-enterprise';\n\nfunction testUA(userAgent: string, pattern: RegExp) {\n return pattern.test(navigator.userAgent);\n}\nexport function isiOS(userAgent: string) {\n return testUA(userAgent, /iPad|iPhone|iPod/) && !(window as any).MSStream;\n}\n\nexport function isiOSSafari(userAgent: string) {\n return isiOS(userAgent) && !testUA(userAgent, / CriOS\\/[.0-9]*/);\n}\n\nexport function isAndroid(userAgent: string) {\n return testUA(userAgent, /Android/);\n}\n\nexport type MobileOS = 'ios' | 'android';\n\nexport function getMobileOS(userAgent: string): MobileOS | null {\n if (isiOS(userAgent)) return 'ios';\n if (isAndroid(userAgent)) return 'android';\n\n return null;\n}\n\nexport function getUserAgent(userAgent?: string) {\n if (!userAgent) return null;\n return UAParser(userAgent);\n}\n","import { useEffect } from 'react';\n\nexport interface UsePollProps {\n shouldPoll: boolean;\n pollUrl: string;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => void;\n}\n\nexport function usePoll({ shouldPoll, pollUrl, onComplete, onError }: UsePollProps) {\n useEffect(() => {\n if (!shouldPoll) return;\n let isSubscribed = true;\n let timeout: string | undefined;\n const poll = async () => {\n if (!isSubscribed) return;\n const response = await fetch(pollUrl);\n\n if (response.status === 202) {\n setTimeout(poll, 1000);\n return;\n } else if (response.status >= 400) {\n if (!isSubscribed) return;\n const error = await response.text();\n onError(error);\n return;\n } else {\n if (!isSubscribed) return;\n const { targetUrl } = await response.json();\n onComplete(targetUrl);\n return;\n }\n };\n\n setTimeout(poll, 1000);\n return () => {\n isSubscribed = false;\n if (timeout) clearTimeout(timeout);\n };\n }, [shouldPoll, pollUrl]);\n}\n","import React, { useContext, useState } from 'react';\nimport CriiptoVerifyContext from '../../context';\nimport type { Links } from './shared';\nimport { usePoll } from './usePoll';\n\ninterface Props {\n children: React.ReactElement;\n links: Links;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => Promise<void>;\n onInitiate: () => void;\n onLog: (...statements: string[]) => void;\n}\n\n/*\n * Desktop: Polling scenario\n */\nexport default function SEBankIDSameDevicePoll(props: Props) {\n const { links, onError, onComplete, onInitiate } = props;\n const [initiated, setInitiated] = useState(false);\n const { domain } = useContext(CriiptoVerifyContext);\n\n usePoll({\n ...props,\n shouldPoll: initiated,\n pollUrl: links.pollUrl,\n });\n const handleInitiate = () => {\n onInitiate();\n setInitiated(true);\n };\n\n return React.cloneElement(props.children, {\n ...(props.children.props as any),\n onClick: handleInitiate,\n });\n}\n","import React, { useRef, useState, useEffect } from 'react';\n\nexport default function usePageVisibility(onVisible?: () => void, deps: React.DependencyList = []) {\n const visibilityState = useRef(document.visibilityState);\n const [state, setState] = useState(visibilityState.current);\n\n useEffect(() => {\n document.addEventListener('visibilitychange', _handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', _handleVisibilityChange);\n };\n }, deps);\n\n const _handleVisibilityChange = () => {\n const nextState = document.visibilityState;\n if (visibilityState.current === 'hidden' && nextState === 'visible') {\n if (onVisible) onVisible();\n }\n\n visibilityState.current = nextState;\n setState(visibilityState.current);\n };\n\n return state;\n}\n","import React, { useCallback, useEffect, useState } from 'react';\nimport usePageVisibility from '../../hooks/usePageVisibility';\nimport type { Links } from './shared';\nimport { usePoll } from './usePoll';\n\ninterface Props {\n children: React.ReactElement;\n links: Links;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => Promise<void>;\n onInitiate: () => void;\n onLog: (...statements: string[]) => void;\n}\n\n/*\n * Android + iOS Chrome: Background/Foreground scenario\n */\nexport default function SEBankIDSameDeviceForeground(props: Props) {\n const { links, onInitiate, onLog } = props;\n const [initiated, setInitiated] = useState(false);\n\n // Polling might complete while the browser is in the background, but we don't want to invoke the\n // complete callbacks before the browser is focused. So we store the result here.\n const [result, setResult] = useState<{ result: string } | { error: string } | null>(null);\n\n const onComplete = useCallback((completeUrl: string) => setResult({ result: completeUrl }), []);\n const onError = useCallback((error: string) => setResult({ error: error }), []);\n\n const visibility = usePageVisibility(() => {\n onLog('ForegroundStrategy', 'onForeground', initiated.toString());\n }, [initiated]);\n\n useEffect(() => {\n if (result && visibility === 'visible') {\n if ('result' in result) {\n props.onComplete(result.result);\n } else if ('error' in result) {\n props.onError(result.error);\n }\n // Clear result, so we don't call error / complete several times, if visibility changes\n setResult(null);\n }\n }, [result, visibility]);\n\n usePoll({\n shouldPoll: initiated,\n pollUrl: links.pollUrl,\n onComplete,\n onError,\n });\n\n const handleInitiate = () => {\n onLog('ForegroundStrategy', 'handleInitiate');\n onInitiate();\n setInitiated(true);\n };\n\n return React.cloneElement(props.children, {\n ...(props.children.props as any),\n onClick: handleInitiate,\n });\n}\n","import type { PKCE } from '@criipto/auth-js';\nimport { createMemoryStorage } from '../../memory-storage';\nimport { trySessionStorage } from '../../utils';\n\nexport interface Links {\n cancelUrl: string;\n completeUrl: string;\n pollUrl: string;\n launchLinks: {\n customFileHandlerUrl: string;\n universalLink: string;\n };\n}\n\nexport interface State {\n pkce: PKCE | undefined;\n redirectUri: string;\n links: Links;\n}\n\nconst STATE_KEY = '@criipto/verify-react:sebankid:state';\n\nconst stateStore = (() => {\n const sessionStorage = trySessionStorage();\n if (sessionStorage === null) {\n console.warn(\n 'Creating memory store for PKCE values as no sessionStorage is available. Authentication may be broken.',\n );\n return createMemoryStorage();\n }\n return sessionStorage;\n})();\n\nexport function hydrateState(): State | undefined {\n const rawState = stateStore.getItem(STATE_KEY);\n if (rawState) {\n return JSON.parse(rawState) as State;\n }\n\n return undefined;\n}\n\nexport const autoHydratedState = hydrateState();\n\nexport function clearState() {\n stateStore.removeItem(STATE_KEY);\n}\n\nexport function saveState(input: State): void {\n stateStore.setItem(STATE_KEY, JSON.stringify(input));\n}\n","import type { PKCE } from '@criipto/auth-js';\nimport React, { useEffect, useState } from 'react';\nimport { type Links, saveState, hydrateState, clearState } from './shared';\n\ninterface Props {\n children: React.ReactElement;\n links: Links;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => Promise<void>;\n onInitiate: () => void;\n onLog: (...statements: string[]) => void;\n pkce: PKCE | undefined;\n redirectUri: string;\n}\n\n/*\n * iOS Safari: Page reload on switch back scenario\n */\n\nexport default function SEBankIDSameDeviceReload(props: Props) {\n const { links, onError, onComplete, onInitiate, onLog, pkce, redirectUri } = props;\n\n const handleInitiate = () => {\n onLog('ReloadStrategy', 'handleInitiate');\n\n saveState({\n links,\n redirectUri,\n pkce,\n });\n\n onInitiate();\n };\n\n useEffect(() => {\n const hydratedState = hydrateState();\n if (!hydratedState) return;\n clearState();\n onComplete(hydratedState.links.completeUrl);\n }, []);\n\n return React.cloneElement(props.children, {\n ...(props.children.props as any),\n onClick: handleInitiate,\n });\n}\n","\"data:image/png;base64,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\"","import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { type AuthorizeResponse, OAuth2Error, type PKCE } from '@criipto/auth-js';\nimport QRCode from 'qrcode';\nimport { type Language } from '../i18n';\n\nimport CriiptoVerifyContext from '../context';\n\nimport logo from './SEBankIDQRCode/logo@2x.png';\nimport './SEBankIDQRCode/SEBankIDQRCode.css';\nimport { getI18n } from '../i18n';\n\ninterface Props {\n redirectUri?: string;\n qrMargin?: number;\n /**\n * Impacts the help text\n */\n language?: Language;\n children?: (props: {\n qrElement: React.ReactElement;\n /**\n * Can be rendered instead of `qrElement` if you only wish to render the qr code with no additional content.\n * Combine with `qrMargin`.\n */\n imageElement: React.ReactElement;\n /**\n * Will be true once the user has completed login in the app and the rest of the login flow is being processed\n */\n isCompleting: boolean;\n /**\n * The user has clicked on the qr image element to trigger fullscreen view per https://developers.bankid.com/getting-started/qr-code#accessibility\n */\n fullscreen: boolean;\n error: OAuth2Error | Error | null;\n retry: () => void;\n }) => React.ReactElement;\n\n /** Render fallback element while loading */\n fallback?: React.ReactElement;\n}\n\ninterface QrResponse {\n initialQrCode: string;\n pollUrl: string;\n}\ninterface PollResponse {\n qrCode?: string;\n targetUrl?: string;\n}\n\nfunction searchParamsToPOJO(input: URLSearchParams) {\n return Array.from(input.keys()).reduce((memo: { [key: string]: string }, key) => {\n memo[key] = input.get(key)!;\n return memo;\n }, {});\n}\n\nexport default function SEBankIDQrCode(props: Props) {\n const wrapperRef = useRef<HTMLButtonElement>(null);\n const {\n buildAuthorizeUrl,\n completionStrategy,\n handleResponse,\n generatePKCE,\n redirectUri: defaultRedirectURi,\n uiLocales,\n } = useContext(CriiptoVerifyContext);\n const language = (props.language ?? uiLocales ?? 'en') as Language;\n const redirectUri = props.redirectUri || defaultRedirectURi;\n const [qrCode, setQrCode] = useState<string | null>(null);\n const [pollUrl, setPollUrl] = useState<string | null>(null);\n const [error, setError] = useState<OAuth2Error | Error | null>(null);\n const [pkce, setPKCE] = useState<PKCE | undefined>(undefined);\n const [isCompleting, setCompleting] = useState(false);\n const [fullscreen, setFullscreen] = useState(false);\n\n const refresh = useCallback(async () => {\n setError(null);\n setQrCode(null);\n setPollUrl(null);\n setPKCE(undefined);\n\n const pkce = await generatePKCE();\n\n buildAuthorizeUrl({\n acrValues: 'urn:grn:authn:se:bankid:another-device:qr',\n responseMode: 'json',\n pkce,\n redirectUri,\n prompt: 'login', // Triggering SSO at this point would be a mistake\n })\n .then((url) => {\n return fetch(url).then((response) => response.json() as Promise<QrResponse>);\n })\n .then((response) => {\n setPKCE(pkce);\n setQrCode(response.initialQrCode);\n setPollUrl(response.pollUrl);\n })\n .catch(console.error);\n }, [buildAuthorizeUrl, redirectUri]);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n const handleRetry = () => {\n setCompleting(false);\n refresh();\n };\n\n const handleError = useCallback(\n (error: string) => {\n /* Timeout error */\n if (error === 'Collect failed: startFailed' || error === '\"Collect failed: startFailed\"') {\n handleRetry();\n return;\n }\n setError(new Error(error));\n handleResponse(new Error(error), {\n pkce,\n redirectUri,\n source: 'SEBankIDQrCode',\n });\n },\n [pkce, redirectUri],\n );\n\n const handleComplete = useCallback(\n async (completeUrl: string) => {\n setCompleting(true);\n const required = { pkce };\n const parsed = await parseCompleteUrl(completeUrl);\n\n if (parsed instanceof Error) {\n return handleError(parsed.message);\n }\n\n const { location, response } = parsed;\n\n if (completionStrategy === 'openidprovider') {\n window.location.href = location;\n return;\n }\n await handleResponse(response, {\n pkce: required.pkce,\n redirectUri,\n source: 'SEBankIDQrCode',\n });\n },\n [completionStrategy, pkce],\n );\n\n /**\n * Render QR codes\n */\n const qrDataURL = useDraw(qrCode, {\n width: fullscreen\n ? (window.innerHeight ?? wrapperRef.current?.offsetWidth)\n : wrapperRef.current?.offsetWidth,\n // 2 is half of the default 4, less margin is required in fullscreen\n qrMargin: props.qrMargin ?? (fullscreen ? 2 : undefined),\n });\n\n /**\n * Poll for response\n */\n usePoll(pollUrl, {\n enabled: !isCompleting,\n onQrCode: setQrCode,\n onComplete: handleComplete,\n onError: handleError,\n });\n\n const i18n = getI18n(language);\n\n const imageElement = (\n <button\n aria-label={i18n.thisIsTheQR}\n ref={wrapperRef}\n className=\"criipto-se-bankid-qr-canvas\"\n onClick={() => setFullscreen((val) => !val)}\n >\n {qrDataURL ? <img src={qrDataURL} /> : null}\n </button>\n );\n\n const qrElement = (\n <div className=\"criipto-se-bankid-qr\">\n <aside className=\"criipto-se-bankid-qr--help-text\">\n {isCompleting ? i18n.completingLogin : i18n.openAndScan}\n <img src={logo} />\n </aside>\n\n {imageElement}\n </div>\n );\n\n if (!qrCode && props.fallback) {\n return props.fallback;\n }\n\n if (props.children) {\n return props.children({\n qrElement,\n imageElement,\n error,\n isCompleting,\n retry: () => handleRetry(),\n fullscreen,\n });\n }\n\n if (fullscreen) {\n return (\n <dialog className=\"criipto-se-bankid-qr-fullscreen\" open>\n {imageElement}\n </dialog>\n );\n }\n\n return qrElement;\n}\n\nSEBankIDQrCode.acr_values = 'urn:grn:authn:se:bankid:another-device:qr';\n\ntype UseDrawOptions = {\n width?: number;\n qrMargin?: number;\n};\nexport function useDraw(qrCode: string | null, options: UseDrawOptions) {\n const { width, qrMargin } = options;\n const [dataURL, setDataURL] = useState<string | null>(null);\n\n useEffect(() => {\n if (!qrCode) return;\n\n let isSubscribed = true;\n (async () => {\n const qrImage = await QRCode.toDataURL(qrCode, {\n errorCorrectionLevel: 'low',\n scale: 10,\n width,\n margin: qrMargin ?? 4,\n });\n\n if (!isSubscribed) return;\n setDataURL(qrImage);\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [qrCode, qrMargin, width]);\n\n return dataURL;\n}\n\ntype UsePollOptions = {\n enabled: boolean;\n onQrCode: (code: string) => void;\n onComplete: (url: string) => void;\n onError: (error: string) => void;\n};\nexport function usePoll(pollUrl: string | null, options: UsePollOptions) {\n const { onQrCode, onComplete, onError, enabled } = options;\n useEffect(() => {\n if (!pollUrl) return;\n if (!enabled) return;\n\n const delay = 2500;\n let timeout: any;\n let isSubscribed = true;\n const poll = async () => {\n if (!isSubscribed) return;\n const response = await fetch(pollUrl);\n\n if (!isSubscribed) return;\n if (response.status < 400) {\n const payload = (await response.json()) as PollResponse;\n if (payload.qrCode) onQrCode(payload.qrCode);\n if (payload.targetUrl) {\n onComplete(payload.targetUrl);\n return;\n }\n } else {\n const text = await response.text();\n onError(text);\n }\n\n if (response.status === 202) {\n timeout = setTimeout(poll, delay);\n }\n };\n\n timeout = setTimeout(poll, delay);\n return () => {\n isSubscribed = false;\n clearTimeout(timeout);\n };\n }, [pollUrl, onQrCode, onComplete, onError, enabled]);\n}\n\nexport async function parseCompleteUrl(\n completeUrl: string,\n): Promise<{ location: string; response: AuthorizeResponse } | Error> {\n /**\n * Handle verify response inconsistencies\n */\n if (completeUrl.includes('error=')) {\n const url = new URL(completeUrl);\n const completeParams = searchParamsToPOJO(url.searchParams) as AuthorizeResponse;\n\n return { location: completeUrl, response: completeParams };\n }\n\n const completeResponse = await fetch(completeUrl);\n if (completeResponse.status >= 400) {\n return new Error(await completeResponse.text());\n }\n\n const { location }: { location: string } = await completeResponse.json();\n const url = new URL(location);\n const params = searchParamsToPOJO(url.searchParams) as AuthorizeResponse;\n return { location: location, response: params };\n}\n","import React, { createContext, useState } from 'react';\nimport {\n AuthMethodButtonContainer,\n type AuthMethodButtonContainerProps,\n AuthMethodButtonComponent,\n type AuthMethodButtonComponentProps,\n} from './AuthMethodButton';\nimport SEBankIDQrCode from './SEBankIDQRCode';\n\ninterface AuthButtonGroupContextInterface {\n multiple: boolean;\n acrValues: string[];\n disabled: boolean;\n setDisabled: (disabled: boolean) => void;\n}\nconst initialContext: AuthButtonGroupContextInterface = {\n multiple: false,\n acrValues: [],\n disabled: false,\n setDisabled: () => {},\n};\nexport const AuthButtonGroupContext =\n createContext<AuthButtonGroupContextInterface>(initialContext);\n\nexport default function AuthButtonGroup(props: { children: React.ReactNode }) {\n const acrValues = React.Children.toArray(props.children).flatMap((child) => {\n if (!child || typeof child !== 'object') return [];\n if ('type' in child) {\n if (child.type === AuthMethodButtonContainer) {\n const props = child.props as AuthMethodButtonContainerProps;\n return props.acrValue ? [props.acrValue] : [];\n }\n if (child.type === AuthMethodButtonComponent) {\n const props = child.props as AuthMethodButtonComponentProps;\n return props.acrValue ? [props.acrValue] : [];\n }\n if (child.type === SEBankIDQrCode) {\n return ['urn:grn:authn:se:bankid:another-device:qr'];\n }\n }\n return [];\n });\n const [disabled, setDisabled] = useState(false);\n\n const context: AuthButtonGroupContextInterface = {\n multiple: acrValues.length > 1,\n acrValues,\n disabled,\n setDisabled,\n };\n return (\n <AuthButtonGroupContext.Provider value={context}>\n {props.children}\n </AuthButtonGroupContext.Provider>\n );\n}\n","import type { ReactElement } from 'react';\nimport './Spinner.css';\n\nexport function Spinner(): ReactElement {\n return <div className=\"criipto-eid-loader\"></div>;\n}\n","import type { PKCE, AuthorizeResponse } from '@criipto/auth-js';\nimport React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport CriiptoVerifyContext from '../context';\nimport { getUserAgent } from '../device';\n\nimport PollStrategy from './SEBankIDSameDeviceButton/Poll';\nimport ForegroundStrategy from './SEBankIDSameDeviceButton/Foreground';\nimport ReloadStrategy from './SEBankIDSameDeviceButton/Reload';\n\nimport { autoHydratedState, type Links } from './SEBankIDSameDeviceButton/shared';\nimport { AuthButtonGroupContext } from './AuthButtonGroup';\nimport classNames from 'classnames';\nimport { Spinner } from './Spinner/Spinner';\n\ninterface Props {\n className: string;\n children: React.ReactNode;\n logo: React.ReactNode;\n fallback: React.ReactElement;\n redirectUri?: string;\n userAgent?: string;\n disabled?: boolean;\n}\n\nfunction searchParamsToPOJO(input: URLSearchParams) {\n return Array.from(input.keys()).reduce((memo: { [key: string]: string }, key) => {\n memo[key] = input.get(key)!;\n return memo;\n }, {});\n}\n\ntype Resume = 'Foreground' | 'Reload' | 'Poll';\ntype LinkType = 'universal' | 'scheme';\nexport function determineStrategy(\n input: string | undefined,\n loginHint?: string,\n): {\n resume: Resume;\n linkType: LinkType;\n redirect: boolean;\n} {\n const userAgent = getUserAgent(input);\n const mobileOS =\n userAgent?.os.name === 'iOS'\n ? 'iOS'\n : userAgent?.os.name === 'Android'\n ? 'android'\n : userAgent?.browser.name === 'Samsung Internet'\n ? 'android'\n : null;\n const iOSSafari =\n mobileOS === 'iOS' && userAgent?.browser.name?.includes('Safari') ? true : false;\n const androidChrome =\n mobileOS === 'android' && userAgent?.browser.name === 'Mobile Chrome' ? true : false;\n const redirect = iOSSafari && !loginHint?.includes('appswitch:resumeUrl:disable');\n\n const resume: Resume = mobileOS ? (iOSSafari && redirect ? 'Reload' : 'Foreground') : 'Poll';\n\n const linkType = mobileOS === 'iOS' || androidChrome ? 'universal' : 'scheme';\n\n return { resume, linkType, redirect };\n}\n\nexport class NotDoneError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotDoneError';\n }\n}\n\nasync function fetchComplete(completeUrl: string) {\n const completeResponse = await fetch(completeUrl);\n if (completeResponse.status >= 400) {\n const errorMessage = await completeResponse.text();\n const notDone = errorMessage.includes('Native-app driven authentication is not done');\n if (notDone) return new NotDoneError(errorMessage);\n return new Error(errorMessage);\n }\n\n const { location }: { location: string } = await completeResponse.json();\n return { location };\n}\nexport default function SEBankIDSameDeviceButton(props: Props) {\n const { loginHint } = useContext(CriiptoVerifyContext);\n const group = useContext(AuthButtonGroupContext);\n\n const rawUserAgent = typeof navigator !== 'undefined' ? navigator.userAgent : props.userAgent;\n const strategy = useMemo(\n () => determineStrategy(rawUserAgent, loginHint),\n [rawUserAgent, loginHint],\n );\n\n const [href, setHref] = useState<null | string>();\n const [links, setLinks] = useState<Links | null>(autoHydratedState?.links ?? null);\n const [pkce, setPKCE] = useState<PKCE | undefined>(autoHydratedState?.pkce ?? undefined);\n const [error, setError] = useState<string | null>(null);\n const [log, setLog] = useState<(string | string[])[]>([]);\n const [initiated, setInitiated] = useState(autoHydratedState ? true : false);\n const {\n buildAuthorizeUrl,\n completionStrategy,\n generatePKCE,\n handleResponse,\n redirectUri: defaultRedirectURi,\n domain,\n } = useContext(CriiptoVerifyContext);\n const redirectUri = props.redirectUri || defaultRedirectURi;\n\n const disabled = props.disabled || group.disabled || initiated;\n\n const reset = () => {\n setPKCE(undefined);\n setLinks(null);\n };\n\n const handleLog = (...statements: string[]) => {\n setLog((logs) => logs.concat([statements]));\n };\n\n const handleComplete = useCallback(\n async (completeUrl: string) => {\n const required = { pkce };\n reset();\n\n const result =\n completeUrl.startsWith(`https://${domain}`) || completeUrl.startsWith(`http://${domain}`)\n ? await fetchComplete(completeUrl)\n : {\n location: completeUrl,\n };\n if (result instanceof NotDoneError && strategy.resume === 'Reload') {\n await handleResponse(\n {\n error: 'access_denied',\n },\n {\n pkce: required.pkce,\n redirectUri,\n source: 'SEBankIDSameDeviceButton',\n },\n );\n return;\n }\n if (result instanceof Error) {\n setError(result.message);\n return;\n }\n const { location } = result;\n if (completionStrategy === 'openidprovider') {\n window.location.href = location;\n return;\n }\n const url = new URL(location);\n const params = searchParamsToPOJO(url.searchParams) as AuthorizeResponse;\n\n await handleResponse(params, {\n pkce: required.pkce,\n redirectUri,\n source: 'SEBankIDSameDeviceButton',\n });\n },\n [completionStrategy, pkce, domain, strategy],\n );\n\n const refresh = useCallback(async () => {\n handleLog('SEBankID: Refresh authorize url');\n const pkce = await generatePKCE();\n\n buildAuthorizeUrl({\n acrValues: 'urn:grn:authn:se:bankid:same-device',\n // When used on a mobile device, we might have already set appswitch login hints\n loginHint: loginHint?.includes('appswitch:') ? undefined : 'appswitch:browser',\n responseMode: 'json',\n pkce,\n redirectUri,\n prompt: 'login', // Triggering SSO at this point would be a mistake\n })\n .then((url) => {\n return fetch(url).then((response) => response.json() as Promise<Links>);\n })\n .then((links) => {\n setPKCE(pkce || undefined);\n setLinks(links);\n\n const redirect = strategy.redirect ? window.location.href : 'null';\n const newUrl = new URL(\n strategy.linkType === 'universal'\n ? links.launchLinks.universalLink\n : links.launchLinks.customFileHandlerUrl,\n );\n newUrl.searchParams.set('redirect', redirect);\n const newHref = newUrl.href;\n\n handleLog(window.location.href);\n handleLog(newHref);\n setHref(newHref);\n })\n .catch((err) => {\n setInitiated(false);\n });\n }, [buildAuthorizeUrl, redirectUri, strategy]);\n\n // Generate URL on first button render\n useEffect(() => {\n if (initiated) return;\n refresh();\n }, [refresh, initiated]);\n\n // Continously fetch new autostart token if UI is open for a long time\n useEffect(() => {\n if (initiated) return;\n\n const interval = setInterval(() => {\n if (initiated) return;\n refresh();\n }, 25000);\n return () => clearInterval(interval);\n }, [refresh, initiated]);\n\n // Track when the button is clicked to stop refreshing URL\n const handleInitiate = () => {\n group.setDisabled(true);\n handleLog('Initiated');\n setInitiated(true);\n setError(null);\n };\n\n const handleError = async (error: string) => {\n group.setDisabled(false);\n setInitiated(false);\n setError(error);\n\n if (error === 'access_denied' || error === '\"access_denied\"') {\n await handleResponse(\n {\n error: 'access_denied',\n },\n {\n pkce,\n redirectUri,\n source: 'SEBankIDSameDeviceButton',\n },\n );\n }\n };\n\n const element = href ? (\n <a\n className={classNames(props.className, { 'criipto-eid-btn--disabled': disabled })}\n href={href}\n onClick={handleInitiate}\n >\n {initiated ? (\n <div className=\"criipto-eid-logo\">\n <Spinner />\n </div>\n ) : (\n props.logo\n )}\n {props.children}\n </a>\n ) : (\n props.fallback\n );\n\n return (\n <React.Fragment>\n {links ? (\n <React.Fragment>\n {strategy.resume === 'Poll' ? (\n <PollStrategy\n links={links}\n onError={handleError}\n onComplete={handleComplete}\n onInitiate={handleInitiate}\n onLog={handleLog}\n >\n {element}\n </PollStrategy>\n ) : strategy.resume === 'Foreground' ? (\n <ForegroundStrategy\n links={links}\n onError={handleError}\n onComplete={handleComplete}\n onInitiate={handleInitiate}\n onLog={handleLog}\n >\n {element}\n </ForegroundStrategy>\n ) : strategy.resume === 'Reload' ? (\n <ReloadStrategy\n links={links}\n onError={handleError}\n onComplete={handleComplete}\n onInitiate={handleInitiate}\n onLog={handleLog}\n redirectUri={redirectUri!}\n pkce={pkce}\n >\n {element}\n </ReloadStrategy>\n ) : (\n element\n )}\n </React.Fragment>\n ) : (\n element\n )}\n {error && <p>{error}</p>}\n {/* {log && (\n <pre>\n {JSON.stringify(log, null, 2)}\n </pre>\n )} */}\n </React.Fragment>\n );\n}\n","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAABICAYAAABWdn8qAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAsKADAAQAAAABAAAASAAAAACoGQzqAAADbUlEQVR4Ae2agVHbMBSGSa8DMIJH6Ab1BmWEdgLSCWImgE4AjNAJmhE6gkdgg/R/xXAc957tEMeWrE93hvCkSL8+/XlIdi4uKBCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCJxG4HA4NLrWUupTaAjC9wBEc0q/qb33U2qC0PNKYPf6ihchAQwcolm8olYG3S6uInEBGDjtBdrJxJdpS1xWHQZelv/Q6GZethI9lD731K2p6q8m83viCZm5roM+b4L4+/AYc26VhR83m43NgbJmAlro6C7E/dTz1liVLreMHct9sx/8M7bPl3bqhrsQLzD4vTgBO9BdLa4iQQHsgRNclEDSrUxs2xbKGwIY+A2MRF620vHoaKkU2zrxokMYOM3lbyTryZF2rSxcOfFiQxg4waXXHYdWsn450mwLMfmB1BknmxAGTnep7iTNy8J2oKvTlT2vMgw8L+/RoykLm3m9LGx93HOge0aJgZ85pPozysKVBG9TFT2nLgw8J+0jxxrIwhzoxLMUA0dPpfSfeFSpj/TelM2jLHypQW6nHCjHvkoxcI5r819zl4Wj71Zc6eNXZzu5CYRj4AkgnrsLmdiy8D4Yp+gsjIEDVyQYjrLwF2XhYg90GDhBp3qSlIX3inuPmK35Tia2PXFxhe8Dj1vydlyzs7eyTPtN13uz2t9W1+gqqhRjYGWwJveVtQOdMq093PC+CG+31R7Ups19nsfoZwtxDK0E2nYfxNaRYlnYM7bTdD0hDJznWv4IZNv97iqoW2UYA2e4rMrCe8m2yytF3VbDwJ4F8ohZFn5ypBb1cAMDOw7IIdQd1qJvqxWzF8bAObg11ninqtaprhX76sRXF8LAGS+psrBtIcIDXcZTGy0dA49GlWbDgQNdmqInVIWBJ4S5YFdRFl5Q0jxDY+B5OJ91lO5Ad3PWQRLtHAMnujAfkGUHOu+22ge6yuctGDiftepV2h3ofvY2WmElBl7RosrED5rOfkVTGpwKBh5ElF2DovbCGDg7f/YL7m6rRU/o+t9MLQQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAuMI/AMbHRP0yohB0QAAAABJRU5ErkJggg==\"","import React from 'react';\nimport dkmitid from './logos/dkmitid.png';\nimport dkmitiderhverv from './logos/dkmitiderhverv.png';\nimport ftnmobile from './logos/ftnmobile.png';\nimport itsme from './logos/itsme.png';\nimport nobankid from './logos/nobankid.png';\nimport novipps from './logos/novipps.png';\nimport sebankid from './logos/sebankid.png';\nimport sefrejaid from './logos/sefrejaid.png';\nimport depersonalausweis from './logos/depersonalausweis.png';\nimport ukoneid from './logos/ukoneid.png';\nimport idin from './logos/idin.png';\nimport ftn from './logos/ftn.png';\n\nexport interface AuthMethodButtonLogoProps {\n acrValue: string;\n /**\n * base64 image string, e.x. data:image/png;base64,\n * or a ReactElement\n */\n logo?: React.ReactElement | string;\n}\nexport default function AuthMethodButtonLogo(props: AuthMethodButtonLogoProps) {\n const logo =\n typeof props.logo === 'string' ? (\n <img src={props.logo} alt=\"\" />\n ) : (\n (props.logo ??\n (acrValueToLogo(props.acrValue) ? (\n <img src={acrValueToLogo(props.acrValue)} alt=\"\" />\n ) : (\n <span> </span>\n )))\n );\n\n if (logo) return <div className=\"criipto-eid-logo\">{logo}</div>;\n return null;\n}\n\nfunction acrValueToLogo(value: string) {\n if (value.startsWith('urn:grn:authn:dk:mitid:business')) {\n return dkmitiderhverv;\n }\n if (value.startsWith('urn:grn:authn:dk:mitid')) {\n return dkmitid;\n }\n if (value.startsWith('urn:grn:authn:fi:mobile')) {\n return ftnmobile;\n }\n if (value.startsWith('urn:grn:authn:fi')) {\n return ftn;\n }\n if (value.startsWith('urn:grn:authn:itsme')) {\n return itsme;\n }\n if (value.startsWith('urn:grn:authn:se:bankid')) {\n return sebankid;\n }\n if (value.startsWith('urn:grn:authn:no:bankid')) {\n return nobankid;\n }\n if (value.startsWith('urn:grn:authn:no:vipps')) {\n return novipps;\n }\n if (value.startsWith('urn:grn:authn:se:frejaid')) {\n return sefrejaid;\n }\n if (value.startsWith('urn:grn:authn:uk:oneid')) {\n return ukoneid;\n }\n if (value.startsWith('urn:grn:authn:de:personalausweis')) {\n return depersonalausweis;\n }\n if (value.startsWith('urn:grn:authn:nl:idin')) {\n return idin;\n }\n}\n","import React from 'react';\nimport classNames from 'classnames';\n\ninterface ButtonProps {\n className?: string;\n children: React.ReactNode;\n onClick?: React.MouseEventHandler;\n disabled?: boolean;\n}\nexport function AnchorButton(props: AnchorButtonProps) {\n return (\n <a\n className={classNames(`criipto-verify-button`, props.className)}\n href={props.href}\n aria-disabled={props.disabled}\n onClick={props.onClick}\n >\n {props.children}\n </a>\n );\n}\n\ninterface AnchorButtonProps extends ButtonProps {\n href: string;\n}\nexport function Button(props: ButtonProps) {\n return (\n <button\n className={classNames(`criipto-verify-button`, props.className)}\n type=\"button\"\n disabled={props.disabled}\n onClick={props.onClick}\n >\n {props.children}\n </button>\n );\n}\n","import React, { useContext, useEffect, useState } from 'react';\n\nimport './AuthMethodButton/AuthMethodButton.css';\nimport CriiptoVerifyContext, { type Action } from '../context';\nimport SEBankIDSameDeviceButton from './SEBankIDSameDeviceButton';\nimport { savePKCEState } from '@criipto/auth-js';\nimport AuthMethodButtonLogo, { type AuthMethodButtonLogoProps } from './AuthMethodButton/Logo';\nimport { AnchorButton, Button } from './Button';\nimport { acrValueToTitle, isAmbiguous, isSingle, stringifyAction } from '../utils';\nimport { AuthButtonGroupContext } from './AuthButtonGroup';\nimport { type Language } from '../i18n';\nimport { Spinner } from './Spinner/Spinner';\nimport classNames from 'classnames';\n\nexport type PopupParams = {\n acrValue: string;\n onHide: () => void;\n};\nexport type PopupOption = boolean | ((options: PopupParams) => boolean | React.ReactElement);\n\nexport interface AuthMethodButtonComponentProps {\n acrValue: string;\n href?: string;\n onClick?: React.MouseEventHandler;\n children?: React.ReactNode;\n 'data-testid'?: string;\n className?: string;\n /**\n * base64 image string, e.x. data:image/png;base64,\n * or a ReactElement\n */\n logo?: AuthMethodButtonLogoProps['logo'];\n /**\n * Impacts the button text rendered if no text is provided via props.children\n */\n language?: Language;\n /**\n * Impacts the button text rendered if no text is provided via props.children\n */\n action?: Action;\n disabled?: boolean;\n loading?: boolean;\n}\n\n/**\n * Display only components, does no state management and triggers no login flows on it's own\n */\nexport function AuthMethodButtonComponent(props: AuthMethodButtonComponentProps) {\n const { acrValue, href } = props;\n const group = useContext(AuthButtonGroupContext);\n const standalone = !group.multiple || isSingle(props.acrValue, group.acrValues);\n const language = (props.language ?? 'en') as Language;\n const action = (props.action ?? 'login') as Action;\n\n const disabled = (props.disabled || group.disabled) && !props.loading;\n const className = classNames(`criipto-eid-btn`, acrValueToClassName(acrValue), props.className, {\n 'criipto-eid-btn--disabled': disabled,\n 'criipto-eid-btn--loading': props.loading,\n });\n\n const { title, subtitle } = acrValueToTitle(language, acrValue, {\n disambiguate: isAmbiguous(acrValue, group.acrValues),\n });\n const contents = props.children ?? (\n <React.Fragment>\n {stringifyAction(language, action) ? `${stringifyAction(language, action)} ` : ''}\n {title} \n {standalone ? null : lowercaseFirst(subtitle)}\n </React.Fragment>\n );\n\n const inner = (\n <React.Fragment>\n <AuthMethodButtonLogo acrValue={acrValue} logo={props.loading ? <Spinner /> : props.logo} />\n <span>{contents}</span>\n </React.Fragment>\n );\n\n const commonProps = {\n ...props,\n className,\n disabled,\n };\n const button = href ? (\n <React.Fragment>\n <AnchorButton {...commonProps} href={href}>\n {inner}\n </AnchorButton>\n </React.Fragment>\n ) : (\n <React.Fragment>\n <Button {...commonProps}>{inner}</Button>\n </React.Fragment>\n );\n\n return button;\n}\n\nexport type AuthMethodButtonContainerProps = AuthMethodButtonComponentProps & {\n redirectUri?: string;\n popup?: PopupOption;\n\n /**\n * Will ammend the login_hint parameter with `message:{base64(message)}` which will set a login/aprove message where available (Danish MitID).\n */\n message?: string;\n\n userAgent?: string;\n};\n\nexport function AuthMethodButtonContainer(props: AuthMethodButtonContainerProps) {\n const { acrValue } = props;\n const group = useContext(AuthButtonGroupContext);\n const standalone = !group.multiple || isSingle(props.acrValue, group.acrValues);\n const context = useContext(CriiptoVerifyContext);\n const { initializePAR } = context;\n const language = (props.language ?? context.uiLocales ?? 'en') as Language;\n const action = (props.action ?? context.action ?? 'login') as Action;\n const className = `criipto-eid-btn ${acrValueToClassName(acrValue)}${\n props.className ? ` ${props.className}` : ''\n }`;\n const [backdrop, setBackdrop] = useState<React.ReactElement | null>(null);\n const [loading, setLoading] = useState<boolean>(props.loading ?? false);\n useEffect(() => {\n setLoading(props.loading ?? false);\n }, [props.loading]);\n\n const redirectUri = props.redirectUri || context.redirectUri;\n\n const handleClick: React.MouseEventHandler = (event) => {\n if (props.href) return;\n\n if (context.pkce && 'code_verifier' in context.pkce) {\n // just-in-time saving of PKCE, in case of man-in-the-browser\n savePKCEState(context.store, {\n response_type: 'id_token',\n pkce_code_verifier: context.pkce.code_verifier,\n redirect_uri: redirectUri!,\n });\n }\n\n if (props.popup) {\n let willPopup =\n typeof props.popup === 'function'\n ? props.popup({\n acrValue,\n onHide: () => setBackdrop(null),\n })\n : props.popup === true;\n\n if (willPopup !== false) {\n event.preventDefault();\n\n if (typeof willPopup === 'boolean') {\n context.loginWithPopup({\n acrValues: [acrValue],\n redirectUri: redirectUri,\n backdrop: true,\n });\n } else {\n setBackdrop(willPopup);\n context.loginWithPopup({\n acrValues: [acrValue],\n redirectUri: redirectUri,\n backdrop: false,\n });\n }\n }\n }\n\n if (props.onClick) props.onClick(event);\n\n if (!event.isDefaultPrevented()) {\n setLoading(true);\n group.setDisabled(true);\n initializePAR({\n redirectUri,\n acrValues: acrValue,\n loginHint: '',\n })\n .then((authorizeUrl) => {\n window.location.href = authorizeUrl.toString();\n })\n .catch((error) => {\n setLoading(false);\n group.setDisabled(false);\n context.handleResponse(error);\n });\n }\n };\n\n const { title, subtitle } = acrValueToTitle(language, acrValue, {\n disambiguate: isAmbiguous(acrValue, group.acrValues),\n });\n\n const contents = props.children ?? (\n <React.Fragment>\n {stringifyAction(language, action) ? `${stringifyAction(language, action)} ` : ''}\n {title} \n {standalone ? null : lowercaseFirst(subtitle)}\n </React.Fragment>\n );\n\n const button = (\n <React.Fragment>\n <AuthMethodButtonComponent\n {...props}\n className={className}\n onClick={handleClick}\n loading={loading}\n />\n {backdrop}\n </React.Fragment>\n );\n\n if (!props.href && acrValue === 'urn:grn:authn:se:bankid:same-device') {\n return (\n <SEBankIDSameDeviceButton\n redirectUri={props.redirectUri}\n fallback={button}\n className={className}\n userAgent={props.userAgent}\n logo={<AuthMethodButtonLogo acrValue={acrValue} logo={props.logo} />}\n disabled={props.disabled}\n >\n <span>{contents}</span>\n </SEBankIDSameDeviceButton>\n );\n }\n\n return button;\n}\n\nfunction acrValueToClassName(value: string) {\n value = value.replace('urn:grn:authn:', '');\n const segments = value.split(':');\n const classNames = segments.reduce((memo: string[], segment: string) => {\n if (memo.length) {\n return memo.concat([`${memo[memo.length - 1]}-${segment}`]);\n } else {\n return memo.concat([segment]);\n }\n }, []);\n\n return classNames.map((className) => `criipto-eid-btn--${className}`).join(' ');\n}\n\nfunction lowercaseFirst(input?: string) {\n if (!input) return input;\n return input.substring(0, 1).toLowerCase() + input.substr(1, input.length);\n}\n","import { useContext } from 'react';\nimport CriiptoVerifyContext from '../context';\nimport { getUserAgent } from '../device';\nimport { filterAcrValues } from '../utils';\nimport { type Language } from '../i18n';\nimport { AuthMethodButtonContainer, type AuthMethodButtonContainerProps } from './AuthMethodButton';\n\nimport './AuthMethodSelector/AuthMethodSelector.css';\nimport SEBankIDQrCode from './SEBankIDQRCode';\nimport AuthButtonGroup from './AuthButtonGroup';\n\ninterface AuthMethodSelectorProps {\n acrValues?: string[];\n language?: Language;\n onSelect?: (acrValue: string) => void;\n redirectUri?: string;\n popup?: AuthMethodButtonContainerProps['popup'];\n userAgent?: string;\n}\n\nexport default function AuthMethodSelector(props: AuthMethodSelectorProps) {\n const { action, uiLocales, acrValues: configurationAcrValues } = useContext(CriiptoVerifyContext);\n const language = props.language || (uiLocales as Language) || 'en';\n\n const acrValues = filterAcrValues(props.acrValues ?? configurationAcrValues ?? []);\n const onlySweden =\n !!acrValues.length && acrValues.every((s) => s.startsWith('urn:grn:authn:se:bankid:'));\n\n if (onlySweden) {\n return <Sweden {...props} acrValues={acrValues} />;\n }\n\n return (\n <div className=\"criipto-eid-selector\">\n <AuthButtonGroup>\n {acrValues.map((acrValue) => (\n <AuthMethodButtonContainer\n acrValue={acrValue}\n key={acrValue}\n onClick={props.onSelect ? () => props.onSelect!(acrValue) : undefined}\n redirectUri={props.redirectUri}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n ))}\n </AuthButtonGroup>\n </div>\n );\n}\n\ntype SwedenProps = Omit<AuthMethodSelectorProps, 'acrValues'> & {\n acrValues: string[];\n};\n\nexport function Sweden(props: SwedenProps) {\n const { acrValues } = props;\n const { action, uiLocales } = useContext(CriiptoVerifyContext);\n const language = props.language || (uiLocales as Language) || 'en';\n const hasQR = acrValues.includes(SEBankIDQrCode.acr_values);\n const filteredAcrValues = acrValues.filter((s) => s !== SEBankIDQrCode.acr_values);\n\n const userAgent = getUserAgent(\n typeof navigator !== 'undefined' ? navigator.userAgent : props.userAgent,\n );\n const mobileOS =\n userAgent?.os.name === 'iOS' ? 'iOS' : userAgent?.os.name === 'Android' ? 'android' : null;\n const showQR = hasQR && !mobileOS;\n\n return (\n <div className=\"criipto-eid-selector\">\n <AuthButtonGroup>\n {filteredAcrValues.map((acrValue) => (\n <AuthMethodButtonContainer\n acrValue={acrValue}\n key={acrValue}\n onClick={props.onSelect ? () => props.onSelect!(acrValue) : undefined}\n redirectUri={props.redirectUri}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n ))}\n {showQR ? (\n <SEBankIDQrCode\n language={language}\n redirectUri={props.redirectUri}\n fallback={\n <AuthMethodButtonContainer\n acrValue={SEBankIDQrCode.acr_values}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n }\n />\n ) : hasQR && mobileOS ? (\n <AuthMethodButtonContainer\n acrValue={SEBankIDQrCode.acr_values}\n redirectUri={props.redirectUri}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n ) : null}\n </AuthButtonGroup>\n </div>\n );\n}\n","import { useContext } from 'react';\nimport CriiptoVerifyContext from './context';\n\nexport default function useCriiptoVerify() {\n const {\n result,\n claims,\n loginWithRedirect,\n loginWithPopup,\n acrValues,\n isLoading,\n isInitializing,\n logout,\n checkSession,\n } = useContext(CriiptoVerifyContext);\n\n return {\n result,\n /**\n * The claims of the decoded id_token (if available)\n */\n claims,\n /**\n * Set when the provider failed to fetch configuration (e.g. invalid `domain`/`clientID`,\n * or CORS), or when an authentication attempt failed (e.g. user cancellation, OAuth2 errors\n * from the IdP). Always render this in your UI — failures are otherwise silent.\n *\n * `OAuth2Error` for IdP-returned errors, `Error` for everything else.\n */\n error: result && ('error' in result || result instanceof Error) ? result : null,\n loginWithRedirect,\n loginWithPopup,\n acrValues,\n /**\n * Will be true when performing token exchange after redirect or during an initial SSO check\n */\n isLoading,\n /**\n * Will be true until the first set of useEffect hooks have been called\n */\n isInitializing,\n /**\n * Check if there is an existing SSO session.\n */\n checkSession,\n /**\n * Clear local session store and logout of any existing SSO session\n */\n logout,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["OAuth2Error","usePoll","searchParamsToPOJO","logo","PollStrategy","ForegroundStrategy","ReloadStrategy","dkmitiderhverv","dkmitid","ftnmobile","ftn","itsme","sebankid","nobankid","mobilepay","novipps","sefrejaid","ukoneid","depersonalausweis","idin"],"sources":["../src/context.ts","../package.json","../src/i18n/en.ts","../src/i18n/da.ts","../src/i18n/sv.ts","../src/i18n/nb.ts","../src/i18n/fi.ts","../src/i18n/de.ts","../src/i18n/nl.ts","../src/i18n/index.ts","../src/utils.ts","../src/memory-storage.ts","../src/provider.tsx","../src/device.ts","../src/components/SEBankIDSameDeviceButton/usePoll.ts","../src/components/SEBankIDSameDeviceButton/Poll.tsx","../src/hooks/usePageVisibility.ts","../src/components/SEBankIDSameDeviceButton/Foreground.tsx","../src/components/SEBankIDSameDeviceButton/shared.ts","../src/components/SEBankIDSameDeviceButton/Reload.tsx","../src/components/SEBankIDQRCode/logo@2x.png","../src/components/SEBankIDQRCode.tsx","../src/components/AuthButtonGroup.tsx","../src/components/Spinner/Spinner.tsx","../src/components/SEBankIDSameDeviceButton.tsx","../src/components/AuthMethodButton/logos/dkmitid.png","../src/components/AuthMethodButton/logos/dkmitiderhverv.png","../src/components/AuthMethodButton/logos/ftnmobile.png","../src/components/AuthMethodButton/logos/itsme.png","../src/components/AuthMethodButton/logos/nobankid.png","../src/components/AuthMethodButton/logos/novipps.png","../src/components/AuthMethodButton/logos/mobilepay.png","../src/components/AuthMethodButton/logos/sebankid.png","../src/components/AuthMethodButton/logos/sefrejaid.png","../src/components/AuthMethodButton/logos/depersonalausweis.png","../src/components/AuthMethodButton/logos/ukoneid.png","../src/components/AuthMethodButton/logos/idin.png","../src/components/AuthMethodButton/logos/ftn.png","../src/components/AuthMethodButton/Logo.tsx","../src/components/Button.tsx","../src/components/AuthMethodButton.tsx","../src/components/AuthMethodSelector.tsx","../src/use-criipto-verify.ts"],"sourcesContent":["import CriiptoAuth, {\n OpenIDConfiguration,\n type AuthorizeUrlParamsOptional,\n type PKCE,\n type AuthorizeResponse,\n OAuth2Error,\n type PKCEPublicPart,\n type Prompt,\n} from '@criipto/auth-js';\nimport type { PopupAuthorizeParams, RedirectAuthorizeParams } from '@criipto/auth-js';\nimport { createContext } from 'react';\n\nexport type ResultSource = 'SEBankIDQrCode' | 'SEBankIDSameDeviceButton' | 'redirect' | 'popup';\nexport type Result =\n | { id_token: string; state?: string; source?: ResultSource }\n | { code: string; state?: string; source?: ResultSource }\n | OAuth2Error\n | Error;\nexport const actions = ['confirm', 'accept', 'approve', 'sign', 'login'] as const;\nexport type Action = (typeof actions)[number];\nexport type Claims = {\n iss: string;\n aud: string;\n identityscheme: string;\n authenticationtype: string;\n sub: string;\n iat: number;\n exp: number;\n [key: string]: string | number;\n};\n\nexport interface BeforeAuthorizeParams {\n /**\n * The acr_values of the authorize request that is about to be made, always normalized to an array.\n * For logins started from a button or `AuthMethodSelector` this will hold exactly one value.\n */\n acrValues: string[];\n /**\n * The parameters the SDK is about to use, with `CriiptoVerifyProvider` configuration already applied.\n */\n options: AuthorizeUrlParamsOptional;\n}\n\n/**\n * Parameters to override for a single authorize request. Any field left out (or set to `undefined`)\n * keeps the value configured on `CriiptoVerifyProvider`.\n */\nexport interface BeforeAuthorizeOverrides {\n /**\n * Appended to the login_hint of this request, just like a `loginHint` passed directly to\n * `loginWithRedirect`. Use `action` and `message` rather than `action:`/`message:` hints,\n * as those are managed by the SDK.\n */\n loginHint?: string;\n action?: Action;\n message?: string;\n scope?: string;\n prompt?: Prompt;\n uiLocales?: string;\n state?: string;\n nonce?: string;\n extraUrlParams?: {\n [key: string]: string | null;\n };\n}\n\nexport interface CriiptoVerifyContextInterface {\n loginWithRedirect: (params?: RedirectAuthorizeParams) => Promise<void>;\n loginWithPopup: (params?: PopupAuthorizeParams) => Promise<void>;\n checkSession: () => Promise<void>;\n logout: (params?: { redirectUri?: string; state?: string }) => Promise<void>;\n fetchOpenIDConfiguration: () => Promise<OpenIDConfiguration>;\n buildAuthorizeUrl: (options?: AuthorizeUrlParamsOptional) => Promise<string>;\n initializePAR: (options?: AuthorizeUrlParamsOptional) => Promise<URL>;\n generatePKCE: () => Promise<PKCE | undefined>;\n buildOptions: (\n options?: AuthorizeUrlParamsOptional | RedirectAuthorizeParams,\n ) => AuthorizeUrlParamsOptional;\n handleResponse: (\n response: AuthorizeResponse | (Error | OAuth2Error),\n params?: { pkce?: PKCE; redirectUri?: string; source?: ResultSource },\n ) => Promise<void>;\n responseType: 'token' | 'code';\n completionStrategy: 'client' | 'openidprovider';\n result: Result | null;\n claims: Claims | null;\n domain: string;\n redirectUri?: string;\n action: Action;\n message?: string;\n pkce?: PKCE | PKCEPublicPart;\n store: Storage;\n isLoading: boolean;\n isInitializing: boolean;\n acrValues?: string[];\n uiLocales?: string;\n client: CriiptoAuth;\n loginHint?: string;\n}\n\n/**\n * @ignore\n */\nconst stub = (): never => {\n throw new Error('You forgot to wrap your component in <CriiptoVerifyProvider>.');\n};\n\n/**\n * @ignore\n */\nconst initialContext = {\n loginWithRedirect: stub,\n loginWithPopup: stub,\n checkSession: stub,\n logout: stub,\n fetchOpenIDConfiguration: stub,\n buildAuthorizeUrl: stub,\n initializePAR: stub,\n generatePKCE: stub,\n buildOptions: stub,\n handleResponse: stub,\n responseType: 'token' as 'token' | 'code',\n completionStrategy: 'client' as 'client' | 'openidprovider',\n result: null,\n claims: null,\n domain: '',\n action: 'login' as Action,\n pkce: undefined,\n store: null as any as Storage,\n isLoading: false,\n isInitializing: true,\n client: null as any as CriiptoAuth,\n loginHint: undefined,\n};\n\nconst CriiptoVerifyContext = createContext<CriiptoVerifyContextInterface>(initialContext);\n\nexport default CriiptoVerifyContext;\n","","export const en = {\n loginWith: 'Login with',\n approveWith: 'Approve with',\n signWith: 'Sign with',\n confirmWith: 'Confirm with',\n acceptWith: 'Accept with',\n sameDevice: 'On this device',\n anotherDevice: 'With your SSN',\n anotherDeviceQR: 'On another device',\n mitidBusiness: 'MitID Business',\n finnishMobileID: 'Finnish Mobile Certificate',\n finnishBankID: 'Finnish Bank ID',\n swedishBankID: 'Swedish BankID',\n norwegianBankID: 'Norwegian BankID',\n biometrics: 'Biometrics',\n openAndScan: 'Open the BankID app on your mobile device and scan the QR code.',\n thisIsTheQR: 'This is a BankID QR Code. You can click it to view it in full screen.',\n completingLogin: 'Completing your login.',\n} as const;\n","import { type I18N } from '.';\n\nexport const da = {\n loginWith: 'Login med',\n approveWith: 'Godkend med',\n signWith: 'Underskriv med',\n confirmWith: 'Bekræft med',\n acceptWith: 'Accepter med',\n sameDevice: 'På denne enhed',\n anotherDevice: 'Med dit personnummer',\n anotherDeviceQR: 'På anden enhed',\n mitidBusiness: 'MitID Erhverv',\n finnishMobileID: 'Finsk Mobilcertifikat',\n finnishBankID: 'Finsk Bank ID',\n swedishBankID: 'Svensk BankID',\n norwegianBankID: 'Norsk BankID',\n biometrics: 'Biometri',\n openAndScan: 'Åbn BankID appen på din telefon og scan QR koden.',\n thisIsTheQR: 'Dette er en BankID QR-kode. Du kan klikke på den for at se den i fuld skærm.',\n completingLogin: 'Fuldfører dit login.',\n} satisfies I18N;\n","import { type I18N } from '.';\n\nexport const sv = {\n loginWith: 'Logga in med',\n approveWith: 'Godkänn med',\n signWith: 'Signera med',\n confirmWith: 'Bekräfta med',\n acceptWith: 'Acceptera med',\n sameDevice: 'På denna enhet',\n anotherDevice: 'Med ditt personnummer',\n anotherDeviceQR: 'På annan enhet',\n mitidBusiness: 'MitID Erhverv',\n finnishMobileID: 'Finskt Mobilcertifikat',\n finnishBankID: 'Finskt Bank ID',\n swedishBankID: 'Svenskt BankID',\n norwegianBankID: 'Norska BankID',\n biometrics: 'Biometri',\n openAndScan: 'Öppna BankID-appen på din mobila enhet och skanna QR-koden.',\n thisIsTheQR: 'Detta är en QR-kod från BankID. Du kan klicka på den för att visa den i fullskärm.',\n completingLogin: 'Slutför din inloggning.',\n} satisfies I18N;\n","import { type I18N } from '.';\n\nexport const nb = {\n loginWith: 'Logg inn med',\n approveWith: 'Godkjenne med',\n signWith: 'Signer med',\n confirmWith: 'Bekreft med',\n acceptWith: 'Aksepterer med',\n sameDevice: 'På denne enhet',\n anotherDevice: 'Med personnummeret ditt',\n anotherDeviceQR: 'På annan enhet',\n mitidBusiness: 'MitID Erhverv',\n finnishMobileID: 'Finsk Mobilsertifikat',\n finnishBankID: 'Finsk Bank ID',\n swedishBankID: 'Svensk BankID',\n norwegianBankID: 'Norsk BankID',\n biometrics: 'Biometri',\n openAndScan: 'Åpne BankID-appen på mobilenheten din og skann QR-koden.',\n thisIsTheQR: 'Dette er en BankID QR-kode. Du kan klikke på den for å se den i fullskjerm.',\n completingLogin: 'Fullfører påloggingen.',\n} satisfies I18N;\n","import type { I18N } from '.';\n\nexport const fi = {\n loginWith: 'Kirjaudu sisään',\n approveWith: 'Hyväksy',\n signWith: 'Allekirjoita',\n confirmWith: 'Vahvista',\n acceptWith: 'Hyväksy',\n sameDevice: 'Tällä laitteella',\n anotherDevice: 'Henkilötunnuksellasi',\n anotherDeviceQR: 'Toisella laitteella',\n mitidBusiness: 'MitID Businessilla',\n finnishMobileID: 'Suomalaisella Mobiilivarmenteella',\n finnishBankID: 'Suomalaisella BankID:llä',\n swedishBankID: 'Ruotsalaisella BankID:llä',\n norwegianBankID: 'Norjalaisella BankID:llä',\n biometrics: 'Biometrisella tunnistautumisella',\n openAndScan: 'Avaa BankID-sovellus mobiililaitteellasi ja skannaa QR-koodi.',\n thisIsTheQR: 'Tämä on BankID-QR-koodi. Voit napsauttaa sitä nähdäksesi sen koko näytöllä',\n completingLogin: 'Sisäänkirjautumista viimeistellään.',\n} satisfies I18N;\n","import type { I18N } from '.';\n\nexport const de = {\n loginWith: 'Anmelden mit',\n approveWith: 'Genehmigen mit',\n signWith: 'Unterschreiben mit',\n confirmWith: 'Bestätigen mit',\n acceptWith: 'Akzeptieren mit',\n sameDevice: 'Auf diesem Gerät',\n anotherDevice: 'Mit Ihrer Sozialversicherungsnummer',\n anotherDeviceQR: 'Auf einem anderen Gerät',\n mitidBusiness: 'MitID Business',\n finnishMobileID: 'Finnischem Mobilfunkzertifikat',\n finnishBankID: 'Finnische BankID',\n swedishBankID: 'Schwedische BankID',\n norwegianBankID: 'Norwegische BankID',\n biometrics: 'Biometrie',\n openAndScan: 'Öffnen Sie die BankID-App auf Ihrem mobilen Endgerät und scannen Sie den QR-Code.',\n thisIsTheQR:\n 'Dies ist ein BankID QR-Code. Sie können darauf klicken, um ihn im Vollbildmodus anzuzeigen',\n completingLogin: 'Ihre Anmeldung wird abgeschlossen.',\n} satisfies I18N;\n","import type { I18N } from '.';\n\nexport const nl = {\n loginWith: 'Inloggen met',\n approveWith: 'Goedkeuren met',\n signWith: 'Ondertekenen met',\n confirmWith: 'Bevestigen met',\n acceptWith: 'Accepteren met',\n sameDevice: 'Op dit apparaat',\n anotherDevice: 'Met uw SSN',\n anotherDeviceQR: 'Op een ander apparaat',\n mitidBusiness: 'MitID Business',\n finnishMobileID: 'Finse mobiel certificaat',\n finnishBankID: 'Finse BankID',\n swedishBankID: 'Zweedse BankID',\n norwegianBankID: 'Noorse BankID',\n biometrics: 'Biometrie',\n openAndScan: 'Open de BankID-app op uw mobiele apparaat en scan de QR-code.',\n thisIsTheQR:\n 'Dit is een BankID QR-code. U kunt erop klikken om het in een volledig scherm te bekijken',\n completingLogin: 'Uw login voltooien.',\n} satisfies I18N;\n","import { en } from './en';\nimport { da } from './da';\nimport { sv } from './sv';\nimport { nb } from './nb';\nimport { fi } from './fi';\nimport { de } from './de';\nimport { nl } from './nl';\nimport { assertUnreachable } from '../utils';\n\nexport type Language = 'en' | 'da' | 'sv' | 'nb' | 'fi' | 'de' | 'nl';\nexport type I18N = Record<keyof typeof en, string>;\n\nexport function getI18n(language: Language): I18N {\n switch (language) {\n case 'en':\n return en;\n case 'da':\n return da;\n case 'sv':\n return sv;\n case 'nb':\n return nb;\n case 'fi':\n return fi;\n case 'de':\n return de;\n case 'nl':\n return nl;\n default:\n assertUnreachable(language);\n }\n}\n","import type { Action } from './context';\nimport { getI18n, type Language } from './i18n';\n\nexport const DKMITID_PREFIX = 'urn:grn:authn:dk:mitid';\nexport const DKMITID_BUSINESS = 'urn:grn:authn:dk:mitid:business';\nexport const FTN_PREFIX = 'urn:grn:authn:fi';\n\nexport function lowestMitIDValue(input: string[]): string | null {\n let dkmitidMethod: string | null = null;\n\n input.forEach((s) => {\n if (s.startsWith(DKMITID_PREFIX) && s !== DKMITID_BUSINESS) {\n if (!dkmitidMethod) {\n dkmitidMethod = s;\n } else {\n let newLevel = s.replace(DKMITID_PREFIX, '');\n let oldLevel = dkmitidMethod.replace(DKMITID_PREFIX, '');\n if (newLevel === ':low' && [':substantial', ':high'].includes(oldLevel)) {\n dkmitidMethod = s;\n } else if (newLevel === ':substantial' && oldLevel === ':high') {\n dkmitidMethod = s;\n }\n }\n }\n });\n\n return dkmitidMethod;\n}\n\nfunction autoTitleCase(input: string) {\n var segments = input.split(/:|-/).map((segment) => {\n segment = segment.replace(/id(\\s|$)/, 'ID');\n if (segment.length === 2) return segment.toUpperCase();\n return segment.substr(0, 1).toUpperCase() + segment.substr(1);\n });\n return segments.join(' ');\n}\n\nexport function assertUnreachable(x: never): never {\n throw new Error(\"Didn't expect to get here\");\n}\n\nexport function stringifyAction(language: Language, action: Action): string {\n const i18n = getI18n(language);\n\n switch (action) {\n case 'login':\n return i18n.loginWith;\n case 'approve':\n return i18n.approveWith;\n case 'sign':\n return i18n.signWith;\n case 'confirm':\n return i18n.confirmWith;\n case 'accept':\n return i18n.acceptWith;\n default:\n assertUnreachable(action);\n }\n}\n\nexport function acrValueToProviderPrefix(value: string) {\n value = value.replace('urn:grn:authn:', '');\n\n if (value.startsWith('fi')) {\n return 'fi';\n } else if (value.startsWith('itsme')) {\n return 'itsme';\n } else {\n return value.split(':').slice(0, 2).join(':');\n }\n}\n\nexport function acrValueToTitle(\n language: Language,\n value: string,\n { disambiguate, loginHint }: { disambiguate: boolean; loginHint?: string },\n): { title: string; subtitle?: string } {\n const i18n = getI18n(language);\n value = value.replace('urn:grn:authn:', '');\n const provider = acrValueToProviderPrefix(value);\n\n if (provider === 'dk:mitid') {\n let suffix = value.replace('dk:mitid:', '');\n if (suffix === 'business') {\n return {\n title: i18n.mitidBusiness,\n };\n }\n\n return { title: 'MitID' };\n }\n if (value === 'fi:mobile-id') {\n return {\n title: i18n.finnishMobileID,\n };\n }\n if (value === 'fi:bank-id') {\n return {\n title: i18n.finnishBankID,\n };\n }\n if (provider === 'fi') {\n return { title: autoTitleCase(value).replace('FI', 'FTN') };\n }\n if (provider === 'itsme') {\n return { title: autoTitleCase(value).replace('me', 'ME') };\n }\n if (provider === 'se:bankid') {\n let subtitle: string | undefined = undefined;\n let suffix = value.replace('se:bankid:', '');\n let title = 'BankID';\n\n if (suffix === 'same-device') {\n subtitle = i18n.sameDevice;\n }\n if (suffix === 'another-device') {\n subtitle = i18n.anotherDevice;\n }\n if (suffix === 'another-device:qr') {\n subtitle = i18n.anotherDeviceQR;\n }\n if (disambiguate) {\n title = i18n.swedishBankID;\n }\n\n return { title, subtitle };\n }\n if (provider === 'no:bankid') {\n let subtitle: string | undefined = undefined;\n let title = 'BankID';\n if (value.endsWith(':substantial')) {\n subtitle = i18n.biometrics;\n }\n if (disambiguate) {\n title = i18n.norwegianBankID;\n }\n return { title, subtitle };\n }\n if (provider === 'no:vipps') {\n const marketHint = loginHint?.split(' ').find((s) => s.startsWith('market:'));\n if (marketHint === 'market:DK' || marketHint === 'market:FI') {\n return { title: 'MobilePay' };\n }\n return { title: autoTitleCase(value).replace('NO ', '') };\n }\n if (provider === 'se:frejaid') {\n return { title: 'FrejaID' };\n }\n if (provider === 'uk:oneid') {\n return { title: 'OneID' };\n }\n if (provider === 'de:personalausweis') {\n return { title: 'Personalausweis' };\n }\n\n return { title: autoTitleCase(value) };\n}\n\nexport function filterAcrValues(input: string[]) {\n let original = input.slice();\n let dkmitidMethod: string | null = lowestMitIDValue(input);\n let reduced = input.slice();\n\n if (dkmitidMethod) {\n reduced = input\n .filter((s) => !s.startsWith(DKMITID_PREFIX) || s === DKMITID_BUSINESS)\n .concat([dkmitidMethod])\n .sort((a, b) => original.indexOf(a) - original.indexOf(b));\n }\n\n if (input.includes(`${FTN_PREFIX}:all`)) {\n if (!reduced.includes(`${FTN_PREFIX}:bank-id`)) reduced.push(`${FTN_PREFIX}:bank-id`);\n if (!reduced.includes(`${FTN_PREFIX}:mobile-id`)) reduced.push(`${FTN_PREFIX}:mobile-id`);\n reduced = reduced.filter((s) => s !== `${FTN_PREFIX}:all`);\n }\n return reduced;\n}\n\nexport function isSingle(acrValue: string, acrValues: string[]) {\n const provider = acrValueToProviderPrefix(acrValue);\n const count = acrValues.reduce(\n (memo, acrValue) => memo + (acrValueToProviderPrefix(acrValue) === provider ? 1 : 0),\n 0,\n );\n return count === 1;\n}\n\nconst ambigousProviders = ['se:bankid', 'no:bankid'];\n/**\n * A provider is considered ambiguous iff:\n * 1. It is in the list of ambiguous providers\n * 2. There is another ambiguous provider in the arc values list\n */\nexport function isAmbiguous(acrValue: string, acrValues: string[]) {\n const provider = acrValueToProviderPrefix(acrValue);\n const isProviderAmbiguous = ambigousProviders.includes(provider);\n const otherAmbiguousProvider =\n acrValues.find((otherAcrValue) => {\n const otherProvider = acrValueToProviderPrefix(otherAcrValue);\n return provider != otherProvider && ambigousProviders.includes(otherProvider);\n }) != null;\n\n return isProviderAmbiguous && otherAmbiguousProvider;\n}\n\nexport function trySessionStorage() {\n try {\n if (typeof sessionStorage === 'undefined') {\n return null;\n }\n return sessionStorage;\n } catch (err) {\n /**\n * Failed to read the 'sessionStorage' property from 'Window': Access is denied for this document.\n * (if storage is disabled in the browser)\n */\n return null;\n }\n}\n","export function createMemoryStorage(): Storage {\n let store: { [key: string]: string } = {};\n\n return {\n getItem(key: string) {\n return store[key] || null;\n },\n setItem(key: string, value: any) {\n store[key] = value.toString();\n },\n removeItem(key: string) {\n delete store[key];\n },\n clear() {\n store = {};\n },\n key(index) {\n return Object.keys(store)[index];\n },\n get length() {\n return Object.keys(store).length;\n },\n };\n}\n","import React, { useMemo, useState, useCallback, useEffect, useRef } from 'react';\nimport CriiptoAuth, {\n type AuthorizeUrlParamsOptional,\n clearPKCEState,\n generatePKCE,\n OAuth2Error,\n OpenIDConfiguration,\n type PKCE,\n type PKCEPublicPart,\n type Prompt,\n parseAuthorizeResponseFromLocation,\n} from '@criipto/auth-js';\n\nimport CriiptoVerifyContext, {\n type CriiptoVerifyContextInterface,\n type Action,\n type BeforeAuthorizeOverrides,\n type BeforeAuthorizeParams,\n type Result,\n type Claims,\n actions,\n type ResultSource,\n} from './context';\nimport type { AuthorizeResponse, RedirectAuthorizeParams, ResponseType } from '@criipto/auth-js';\n\nimport { version } from '../package.json';\nimport { filterAcrValues, trySessionStorage } from './utils';\nimport jwtDecode from 'jwt-decode';\nimport { createMemoryStorage } from './memory-storage';\n\nconst SESSION_KEY = `@criipto-verify-react/session`;\n\nexport interface CriiptoVerifyProviderOptions {\n domain: string;\n clientID: string;\n /**\n * @deprecated Development use only\n */\n protocol?: 'https' | 'http';\n\n redirectUri?: string;\n children: React.ReactNode;\n pkce?: PKCEPublicPart;\n state?: string;\n nonce?: string;\n prompt?: Prompt;\n scope?: string;\n uiLocales?: string;\n loginHint?: string;\n /**\n * Enables storage and automatic fetch of tokens\n * by utilizing browser storage and SSO silent logins.\n * Make sure \"SSO for OAuth2\" is enabled on your Criipto Domain.\n * Only works for `response: 'token'` (default)\n */\n sessionStore?: Storage;\n /**\n * Will ammend the login_hint parameter with `action:{action}` which will adjust texsts in certain flows.\n * Default: 'login'\n */\n action?: Action;\n /**\n * Will ammend the login_hint parameter with `message:{base64(message)}` which will set a login/aprove message where available (Danish MitID).\n */\n message?: string;\n /**\n * Note: In most cases modifying this setting **is not needed**. Defaults will work with almost all React SPA cases.\n * By default @criipto/verify-react will do PKCE on your behalf and return a jwt token.\n * However if you wish you can disable this and get the raw `code` response by setting `response` to 'code'.\n */\n response?: 'token' | 'code';\n /*\n * Note: In most cases modifying this setting **is not needed**. Defaults will work with almost all React SPA cases.\n * By default @criipto/verify-react will do as much as work on your behalf\n * by interpreting URL parameters and responses with `useCriiptoVerify()` via the default value 'client'.\n * If you wish to only render a UI and redirect to the Criipto IDP for server side code exchange, you can choose 'openidprovider'.\n */\n completionStrategy?: 'client' | 'openidprovider';\n\n /**\n * Called just before each authorize request is built, for every login flow\n * (`AuthMethodSelector`, `AuthMethodButton`, `SEBankIDQRCode`, `loginWithRedirect` and `loginWithPopup`).\n * Return the parameters you wish to change for that particular request, for instance a\n * `loginHint` that depends on the acr_value the user picked. Returning nothing leaves the\n * request as configured on the provider.\n */\n beforeAuthorize?: (params: BeforeAuthorizeParams) => BeforeAuthorizeOverrides | void;\n\n /**\n * @deprecated Criipto internal use\n */\n criiptoSdk?: null | string;\n /**\n * @deprecated Criipto internal use\n */\n responseType?: ResponseType | 'code id_token';\n /**\n * @deprecated Criipto internal use\n */\n responseMode?: 'query' | 'form_post' | 'fragment' | 'json' | 'post_message';\n}\n\nexport const ACTION_SUPPORTING_ACR_VALUES = [\n 'urn:grn:authn:dk:mitid:low',\n 'urn:grn:authn:dk:mitid:substantial',\n 'urn:grn:authn:dk:mitid:high',\n 'urn:grn:authn:se:bankid:same-device',\n 'urn:grn:authn:se:bankid:another-device:qr',\n];\n\nexport const MESSAGE_SUPPORTING_ACR_VALUES = [\n 'urn:grn:authn:dk:mitid:low',\n 'urn:grn:authn:dk:mitid:substantial',\n 'urn:grn:authn:dk:mitid:high',\n 'urn:grn:authn:se:bankid:same-device',\n 'urn:grn:authn:se:bankid:another-device:qr',\n];\n\nexport function normalizeAcrValues(acrValues?: string | string[]): string[] {\n if (!acrValues) return [];\n return Array.isArray(acrValues) ? acrValues : [acrValues];\n}\n\nexport function buildLoginHint(\n loginHint: string | undefined | null,\n params: {\n options?: AuthorizeUrlParamsOptional;\n action?: Action;\n message?: string;\n /**\n * Additional hints, e.x. contributed by `beforeAuthorize`\n */\n extraLoginHint?: string;\n },\n) {\n const { options, action, message, extraLoginHint } = params;\n const acrValues = normalizeAcrValues(options?.acrValues);\n let hints = (loginHint ? loginHint.split(' ') : [])\n .concat(options?.loginHint ? options?.loginHint.split(' ') : [])\n .concat(extraLoginHint ? extraLoginHint.split(' ') : [])\n .filter((hint) => !hint.startsWith('message:') && !hint.startsWith('action:'));\n if (action) {\n hints = hints.filter((h) => !h.startsWith('action:'));\n if (acrValues.length === 1) {\n if (ACTION_SUPPORTING_ACR_VALUES.includes(acrValues[0])) {\n hints.push(`action:${action}`);\n }\n } else if (acrValues.length >= 2) {\n if (acrValues.some((v) => ACTION_SUPPORTING_ACR_VALUES.includes(v))) {\n hints.push(`action:${action}`);\n }\n } else {\n hints.push(`action:${action}`);\n }\n }\n\n if (message) {\n if (acrValues.length === 1) {\n if (MESSAGE_SUPPORTING_ACR_VALUES.includes(acrValues[0])) {\n hints.push(`message:${btoa(message)}`);\n }\n } else if (acrValues.length >= 2) {\n if (acrValues.some((v) => MESSAGE_SUPPORTING_ACR_VALUES.includes(v))) {\n hints.push(`message:${btoa(message)}`);\n }\n } else {\n hints.push(`message:${btoa(message)}`);\n }\n }\n\n return hints.length ? hints.join(' ') : undefined;\n}\n\nfunction parseAction(input?: string): Action | undefined {\n if (!input) return;\n\n const segments = input.split(' ');\n const actionCandidate = segments.find((s) => s.startsWith('action:'));\n if (!actionCandidate) return;\n const action = actionCandidate.replace('action:', '');\n if (actions.includes(action as any)) return action as Action;\n return;\n}\n\nfunction tryBase64Decode(input: string) {\n try {\n return atob(input);\n } catch {\n return null;\n }\n}\nfunction parseMessage(input?: string): string | undefined {\n if (!input) return;\n const segments = input.split(' ');\n const messageCandidate = segments.find((s) => s.startsWith('message:'));\n if (!messageCandidate) return;\n\n const message = messageCandidate.replace('message:', '');\n return tryBase64Decode(message) ?? message;\n}\n\nfunction defaultRedirectUri(input?: string): string {\n if (input) return input;\n if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {\n return window.location.origin + window.location.pathname;\n }\n\n throw new Error('Unable to determine default redirect uri, please provide a redirectUri');\n}\n\nconst pkceStore = (() => {\n const sessionStorage = trySessionStorage();\n if (sessionStorage === null) {\n console.warn(\n 'Creating memory store for PKCE values as no sessionStorage is available. Authentication may be broken.',\n );\n return createMemoryStorage();\n }\n return sessionStorage;\n})();\n\nconst CriiptoVerifyProvider = (props: CriiptoVerifyProviderOptions): React.ReactElement => {\n const client = useMemo(\n () =>\n new CriiptoAuth({\n domain: props.domain,\n clientID: props.clientID,\n store: pkceStore,\n redirectUri: defaultRedirectUri(props.redirectUri),\n protocol: props.protocol,\n }),\n [props.domain, props.clientID, props.redirectUri, props.protocol],\n );\n\n const [configuration, setConfiguration] = useState<OpenIDConfiguration | null>(null);\n useEffect(() => {\n let isSubscribed = true;\n (async () => {\n const configuration = await client.fetchOpenIDConfiguration();\n if (isSubscribed) setConfiguration(configuration);\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [client]);\n\n const [result, setResult] = useState<Result | null>(null);\n\n // Verify that domain and client id are valid; surface failures as the hook's `error`.\n useEffect(() => {\n let isSubscribed = true;\n (async () => {\n try {\n await client.fetchCriiptoConfiguration();\n } catch (error) {\n if (!isSubscribed) return;\n const err = error instanceof Error ? error : new Error(String(error));\n setResult((prev) => prev ?? err);\n }\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [client]);\n const claims = useMemo(() => {\n if (!result) return null;\n if (!('id_token' in result)) return null;\n return jwtDecode<Claims>(result.id_token);\n }, [result]);\n const [isLoading, setIsLoading] = useState(false);\n const [isInitializing, setIsInitializing] = useState(true);\n const [pkce, setPKCE] = useState<PKCE | PKCEPublicPart | undefined>(props.pkce);\n const responseType = props.response || 'token';\n const completionStrategy = props.completionStrategy || 'client';\n const uiLocales = props.uiLocales;\n const loginHint = props.loginHint;\n const action = props.action ?? parseAction(loginHint) ?? 'login';\n const message = props.message ?? parseMessage(loginHint);\n const sessionStore = props.sessionStore;\n\n /*\n * `beforeAuthorize` is only ever called imperatively, when a login is started.\n * Keeping it in a ref (rather than in the `buildOptions` dependencies) means an inline\n * function does not invalidate `buildAuthorizeUrl`, which components like `SEBankIDQRCode`\n * memoize on and would otherwise restart their flow on every provider render.\n */\n const beforeAuthorizeRef = useRef(props.beforeAuthorize);\n useEffect(() => {\n beforeAuthorizeRef.current = props.beforeAuthorize;\n }, [props.beforeAuthorize]);\n\n const refreshPKCE = async () => {\n if (props.pkce) return props.pkce;\n if (responseType !== 'token' || completionStrategy !== 'client') {\n clearPKCEState(pkceStore);\n setPKCE(undefined);\n return undefined;\n }\n\n clearPKCEState(pkceStore);\n\n const pkce = await generatePKCE();\n setPKCE(pkce);\n return pkce;\n };\n\n const buildOptions = useCallback(\n (\n options?: AuthorizeUrlParamsOptional | RedirectAuthorizeParams,\n ): AuthorizeUrlParamsOptional => {\n const resolved: AuthorizeUrlParamsOptional = {\n redirectUri: defaultRedirectUri(props.redirectUri),\n responseType: (props.responseType ?? 'code') as ResponseType,\n responseMode: props.responseMode,\n ...(options || {}),\n state: props.state ?? options?.state,\n nonce: props.nonce ?? options?.nonce,\n prompt: props.prompt ?? options?.prompt,\n scope: props.scope ?? options?.scope,\n uiLocales: uiLocales ?? options?.uiLocales,\n pkce: options?.pkce ?? pkce,\n loginHint: buildLoginHint(props.loginHint, { options, action, message }),\n extraUrlParams:\n props.criiptoSdk !== undefined\n ? {\n criipto_sdk: props.criiptoSdk,\n }\n : {\n criipto_sdk: `@criipto/verify-react@${version}`,\n },\n };\n\n const overrides = beforeAuthorizeRef.current?.({\n acrValues: normalizeAcrValues(resolved.acrValues),\n options: resolved,\n });\n if (!overrides) return resolved;\n\n return {\n ...resolved,\n state: overrides.state ?? resolved.state,\n nonce: overrides.nonce ?? resolved.nonce,\n prompt: overrides.prompt ?? resolved.prompt,\n scope: overrides.scope ?? resolved.scope,\n uiLocales: overrides.uiLocales ?? resolved.uiLocales,\n loginHint: buildLoginHint(props.loginHint, {\n options,\n action: overrides.action ?? action,\n message: overrides.message ?? message,\n extraLoginHint: overrides.loginHint,\n }),\n extraUrlParams: {\n ...resolved.extraUrlParams,\n ...overrides.extraUrlParams,\n },\n };\n },\n [\n pkce,\n props.state,\n props.nonce,\n props.prompt,\n props.scope,\n uiLocales,\n action,\n message,\n props.redirectUri,\n props.criiptoSdk,\n props.loginHint,\n props.responseMode,\n props.responseType,\n ],\n );\n\n const buildAuthorizeUrl = useCallback(\n async (options?: AuthorizeUrlParamsOptional) => {\n return await client.buildAuthorizeUrl(client.buildAuthorizeParams(buildOptions(options)));\n },\n [client, buildOptions],\n );\n\n const initializePAR = useCallback(\n async (options?: AuthorizeUrlParamsOptional) => {\n return (\n await client.pushAuthorizationRequest(client.buildAuthorizeParams(buildOptions(options)))\n ).authorizeUrl;\n },\n [client, buildOptions],\n );\n\n const handleResponse = useCallback(\n async (\n response: AuthorizeResponse | (Error | OAuth2Error),\n params: { pkce?: PKCE; redirectUri?: string; source?: ResultSource } = {},\n ) => {\n if (response instanceof OAuth2Error) {\n setResult(response);\n } else if (response instanceof Error) {\n setResult(response);\n } else if (params.pkce && responseType === 'token') {\n let _redirectUri = params.redirectUri || defaultRedirectUri(props.redirectUri);\n if (!_redirectUri)\n throw new Error(\n 'redirectUri must be configured globally or per authentication component',\n );\n\n await client\n .processResponse(response, {\n code_verifier: params.pkce.code_verifier,\n redirect_uri: _redirectUri,\n })\n .then((response) => {\n if (response?.code)\n setResult({ code: response.code, state: response.state, source: params.source });\n else if (response?.id_token) {\n setResult({\n id_token: response.id_token,\n state: response.state,\n source: params.source,\n });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n } else setResult(null);\n })\n .catch((err: OAuth2Error) => {\n setResult(err);\n });\n } else {\n if (response?.code)\n setResult({ code: response.code, state: response.state, source: params.source });\n else if (response?.id_token) {\n setResult({ id_token: response.id_token, state: response.state, source: params.source });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n } else if (response?.error)\n setResult(new OAuth2Error(response.error, response.error_description, response.state));\n else setResult(null);\n }\n\n refreshPKCE(); // Clear out session storage and recreate PKCE values if being used\n },\n [refreshPKCE, responseType, setResult, client, sessionStore, props.redirectUri],\n );\n\n const checkSession = useCallback(async () => {\n return client\n .checkSession({ redirectUri: defaultRedirectUri(props.redirectUri) })\n .then((response) => {\n if (response?.code) setResult({ code: response.code });\n else if (response?.id_token) {\n setResult({ id_token: response.id_token });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n } else setResult(null);\n });\n }, [sessionStore, client, props.redirectUri]);\n\n const logout = useCallback(\n async (params?: { redirectUri?: string; state?: string }) => {\n sessionStore?.removeItem(SESSION_KEY);\n await client.logout({\n redirectUri: params?.redirectUri ?? defaultRedirectUri(props.redirectUri),\n state: params?.state,\n });\n },\n [sessionStore, client, props.redirectUri],\n );\n\n const context = useMemo<CriiptoVerifyContextInterface>(() => {\n return {\n loginWithRedirect: async (params) => {\n const pkce = await refreshPKCE();\n await client.redirect.authorize(buildOptions({ ...params, pkce }));\n },\n loginWithPopup: async (params) => {\n return client.popup\n .authorize(buildOptions(params))\n .then((response) => {\n if (response?.code)\n setResult({ code: response.code, state: response.state, source: 'popup' });\n else if (response?.id_token)\n setResult({ id_token: response.id_token, state: response.state, source: 'popup' });\n else setResult(null);\n })\n .catch((err: OAuth2Error) => {\n setResult(err);\n });\n },\n checkSession,\n logout,\n fetchOpenIDConfiguration: () => client.fetchOpenIDConfiguration(),\n buildAuthorizeUrl,\n initializePAR,\n generatePKCE: async () => {\n if (responseType !== 'token' || completionStrategy !== 'client') return;\n return await generatePKCE();\n },\n buildOptions,\n handleResponse,\n responseType,\n completionStrategy,\n result,\n claims,\n domain: client.domain,\n redirectUri: defaultRedirectUri(props.redirectUri),\n action,\n message,\n pkce,\n store: pkceStore,\n isLoading,\n isInitializing,\n acrValues: configuration ? filterAcrValues(configuration.acr_values_supported) : undefined,\n client,\n uiLocales,\n loginHint,\n };\n }, [\n client,\n props.redirectUri,\n responseType,\n completionStrategy,\n result,\n claims,\n action,\n message,\n pkce,\n props.state,\n props.prompt,\n isLoading,\n isInitializing,\n handleResponse,\n logout,\n configuration,\n uiLocales,\n checkSession,\n loginHint,\n ]);\n\n useEffect(() => {\n setIsInitializing(false);\n if (!client.redirect.hasMatch()) {\n refreshPKCE(); // Fresh request, setup PKCE\n return;\n }\n\n let isSubscribed = true;\n setIsLoading(true);\n\n const params = parseAuthorizeResponseFromLocation(window.location);\n if (params.code && responseType === 'code') {\n setIsLoading(false);\n setResult({ code: params.code, source: 'redirect', state: params.state });\n refreshPKCE(); // Clear out session storage and recreate PKCE values if being used\n return;\n }\n\n (async () => {\n await Promise.resolve(); // wait for the initial cleanup in Strict mode - avoids double mutation\n if (!isSubscribed) return;\n\n try {\n const response = await client.redirect.match();\n if (!isSubscribed) return;\n\n if (response?.code) {\n setResult({ code: response.code, source: 'redirect', state: response.state });\n } else if (response?.id_token) {\n setResult({ id_token: response.id_token, source: 'redirect', state: response.state });\n sessionStore?.setItem(SESSION_KEY, response.id_token);\n resetRedirectState(window);\n } else setResult(null);\n } catch (err: any) {\n if (!isSubscribed) return;\n if (err instanceof OAuth2Error) {\n setResult(err);\n } else if (err instanceof Error) {\n setResult(err);\n } else {\n setResult(new Error(err?.toString() ?? 'Unknown error ocurred'));\n }\n } finally {\n if (!isSubscribed) return;\n setIsLoading(false);\n refreshPKCE(); // Clear out session storage and recreate PKCE values if being used\n }\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [props.pkce, responseType]);\n\n /*\n * Fetch claims from session store if available\n */\n useEffect(() => {\n if (!sessionStore || claims) return;\n if (!claims) {\n // No result available, fetch from session store\n const token = sessionStore.getItem(SESSION_KEY);\n if (!token) return;\n\n setResult({ id_token: token });\n return;\n }\n }, [sessionStore, claims]);\n\n /*\n * Unset result if claims are expired\n */\n useEffect(() => {\n if (!claims) return;\n if (!sessionStore) return;\n\n const interval = setInterval(() => {\n const now = Date.now();\n if (claims.exp < now / 1000) {\n setResult(null);\n sessionStore?.removeItem(SESSION_KEY);\n return;\n }\n }, 5000);\n\n return () => clearInterval(interval);\n }, [sessionStore, claims, result]);\n\n /**\n * Fresh page load SSO check\n */\n useEffect(() => {\n setIsInitializing(false);\n if (!sessionStore) return;\n if (client.redirect.hasMatch()) return; // Do not issue SSO check if we're just being redirected back to\n if (sessionStore.getItem(SESSION_KEY)) return;\n let isSubscribed = true;\n\n setIsLoading(true);\n checkSession()\n .catch((err) => {\n console.error('session silent check error', err);\n })\n .finally(() => {\n if (isSubscribed) setIsLoading(false);\n });\n\n return () => {\n isSubscribed = false;\n };\n }, [sessionStore, client]);\n\n return (\n <CriiptoVerifyContext.Provider value={context}>{props.children}</CriiptoVerifyContext.Provider>\n );\n};\n\nexport default CriiptoVerifyProvider;\n\nexport function resetRedirectState(window: Window) {\n const url = new URL(window.location.href);\n url.searchParams.delete('code');\n url.searchParams.delete('state');\n\n window.history.replaceState({}, window.document.title, url.pathname + url.search);\n}\n","import { UAParser } from '@ua-parser-js/pro-enterprise';\n\nfunction testUA(userAgent: string, pattern: RegExp) {\n return pattern.test(navigator.userAgent);\n}\nexport function isiOS(userAgent: string) {\n return testUA(userAgent, /iPad|iPhone|iPod/) && !(window as any).MSStream;\n}\n\nexport function isiOSSafari(userAgent: string) {\n return isiOS(userAgent) && !testUA(userAgent, / CriOS\\/[.0-9]*/);\n}\n\nexport function isAndroid(userAgent: string) {\n return testUA(userAgent, /Android/);\n}\n\nexport type MobileOS = 'ios' | 'android';\n\nexport function getMobileOS(userAgent: string): MobileOS | null {\n if (isiOS(userAgent)) return 'ios';\n if (isAndroid(userAgent)) return 'android';\n\n return null;\n}\n\nexport function getUserAgent(userAgent?: string) {\n if (!userAgent) return null;\n return UAParser(userAgent);\n}\n","import { useEffect } from 'react';\n\nexport interface UsePollProps {\n shouldPoll: boolean;\n pollUrl: string;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => void;\n}\n\nexport function usePoll({ shouldPoll, pollUrl, onComplete, onError }: UsePollProps) {\n useEffect(() => {\n if (!shouldPoll) return;\n let isSubscribed = true;\n let timeout: string | undefined;\n const poll = async () => {\n if (!isSubscribed) return;\n const response = await fetch(pollUrl);\n\n if (response.status === 202) {\n setTimeout(poll, 1000);\n return;\n } else if (response.status >= 400) {\n if (!isSubscribed) return;\n const error = await response.text();\n onError(error);\n return;\n } else {\n if (!isSubscribed) return;\n const { targetUrl } = await response.json();\n onComplete(targetUrl);\n return;\n }\n };\n\n setTimeout(poll, 1000);\n return () => {\n isSubscribed = false;\n if (timeout) clearTimeout(timeout);\n };\n }, [shouldPoll, pollUrl]);\n}\n","import React, { useContext, useState } from 'react';\nimport CriiptoVerifyContext from '../../context';\nimport type { Links } from './shared';\nimport { usePoll } from './usePoll';\n\ninterface Props {\n children: React.ReactElement;\n links: Links;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => Promise<void>;\n onInitiate: () => void;\n onLog: (...statements: string[]) => void;\n}\n\n/*\n * Desktop: Polling scenario\n */\nexport default function SEBankIDSameDevicePoll(props: Props) {\n const { links, onError, onComplete, onInitiate } = props;\n const [initiated, setInitiated] = useState(false);\n const { domain } = useContext(CriiptoVerifyContext);\n\n usePoll({\n ...props,\n shouldPoll: initiated,\n pollUrl: links.pollUrl,\n });\n const handleInitiate = () => {\n onInitiate();\n setInitiated(true);\n };\n\n return React.cloneElement(props.children, {\n ...(props.children.props as any),\n onClick: handleInitiate,\n });\n}\n","import React, { useRef, useState, useEffect } from 'react';\n\nexport default function usePageVisibility(onVisible?: () => void, deps: React.DependencyList = []) {\n const visibilityState = useRef(document.visibilityState);\n const [state, setState] = useState(visibilityState.current);\n\n useEffect(() => {\n document.addEventListener('visibilitychange', _handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', _handleVisibilityChange);\n };\n }, deps);\n\n const _handleVisibilityChange = () => {\n const nextState = document.visibilityState;\n if (visibilityState.current === 'hidden' && nextState === 'visible') {\n if (onVisible) onVisible();\n }\n\n visibilityState.current = nextState;\n setState(visibilityState.current);\n };\n\n return state;\n}\n","import React, { useCallback, useEffect, useState } from 'react';\nimport usePageVisibility from '../../hooks/usePageVisibility';\nimport type { Links } from './shared';\nimport { usePoll } from './usePoll';\n\ninterface Props {\n children: React.ReactElement;\n links: Links;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => Promise<void>;\n onInitiate: () => void;\n onLog: (...statements: string[]) => void;\n}\n\n/*\n * Android + iOS Chrome: Background/Foreground scenario\n */\nexport default function SEBankIDSameDeviceForeground(props: Props) {\n const { links, onInitiate, onLog } = props;\n const [initiated, setInitiated] = useState(false);\n\n // Polling might complete while the browser is in the background, but we don't want to invoke the\n // complete callbacks before the browser is focused. So we store the result here.\n const [result, setResult] = useState<{ result: string } | { error: string } | null>(null);\n\n const onComplete = useCallback((completeUrl: string) => setResult({ result: completeUrl }), []);\n const onError = useCallback((error: string) => setResult({ error: error }), []);\n\n const visibility = usePageVisibility(() => {\n onLog('ForegroundStrategy', 'onForeground', initiated.toString());\n }, [initiated]);\n\n useEffect(() => {\n if (result && visibility === 'visible') {\n if ('result' in result) {\n props.onComplete(result.result);\n } else if ('error' in result) {\n props.onError(result.error);\n }\n // Clear result, so we don't call error / complete several times, if visibility changes\n setResult(null);\n }\n }, [result, visibility]);\n\n usePoll({\n shouldPoll: initiated,\n pollUrl: links.pollUrl,\n onComplete,\n onError,\n });\n\n const handleInitiate = () => {\n onLog('ForegroundStrategy', 'handleInitiate');\n onInitiate();\n setInitiated(true);\n };\n\n return React.cloneElement(props.children, {\n ...(props.children.props as any),\n onClick: handleInitiate,\n });\n}\n","import type { PKCE } from '@criipto/auth-js';\nimport { createMemoryStorage } from '../../memory-storage';\nimport { trySessionStorage } from '../../utils';\n\nexport interface Links {\n cancelUrl: string;\n completeUrl: string;\n pollUrl: string;\n launchLinks: {\n customFileHandlerUrl: string;\n universalLink: string;\n };\n}\n\nexport interface State {\n pkce: PKCE | undefined;\n redirectUri: string;\n links: Links;\n}\n\nconst STATE_KEY = '@criipto/verify-react:sebankid:state';\n\nconst stateStore = (() => {\n const sessionStorage = trySessionStorage();\n if (sessionStorage === null) {\n console.warn(\n 'Creating memory store for PKCE values as no sessionStorage is available. Authentication may be broken.',\n );\n return createMemoryStorage();\n }\n return sessionStorage;\n})();\n\nexport function hydrateState(): State | undefined {\n const rawState = stateStore.getItem(STATE_KEY);\n if (rawState) {\n return JSON.parse(rawState) as State;\n }\n\n return undefined;\n}\n\nexport const autoHydratedState = hydrateState();\n\nexport function clearState() {\n stateStore.removeItem(STATE_KEY);\n}\n\nexport function saveState(input: State): void {\n stateStore.setItem(STATE_KEY, JSON.stringify(input));\n}\n","import type { PKCE } from '@criipto/auth-js';\nimport React, { useEffect, useState } from 'react';\nimport { type Links, saveState, hydrateState, clearState } from './shared';\n\ninterface Props {\n children: React.ReactElement;\n links: Links;\n onError: (error: string) => void;\n onComplete: (completeUrl: string) => Promise<void>;\n onInitiate: () => void;\n onLog: (...statements: string[]) => void;\n pkce: PKCE | undefined;\n redirectUri: string;\n}\n\n/*\n * iOS Safari: Page reload on switch back scenario\n */\n\nexport default function SEBankIDSameDeviceReload(props: Props) {\n const { links, onError, onComplete, onInitiate, onLog, pkce, redirectUri } = props;\n\n const handleInitiate = () => {\n onLog('ReloadStrategy', 'handleInitiate');\n\n saveState({\n links,\n redirectUri,\n pkce,\n });\n\n onInitiate();\n };\n\n useEffect(() => {\n const hydratedState = hydrateState();\n if (!hydratedState) return;\n clearState();\n onComplete(hydratedState.links.completeUrl);\n }, []);\n\n return React.cloneElement(props.children, {\n ...(props.children.props as any),\n onClick: handleInitiate,\n });\n}\n","\"data:image/png;base64,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\"","import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';\nimport { type AuthorizeResponse, OAuth2Error, type PKCE } from '@criipto/auth-js';\nimport QRCode from 'qrcode';\nimport { type Language } from '../i18n';\n\nimport CriiptoVerifyContext from '../context';\n\nimport logo from './SEBankIDQRCode/logo@2x.png';\nimport './SEBankIDQRCode/SEBankIDQRCode.css';\nimport { getI18n } from '../i18n';\n\ninterface Props {\n redirectUri?: string;\n qrMargin?: number;\n /**\n * Impacts the help text\n */\n language?: Language;\n children?: (props: {\n qrElement: React.ReactElement;\n /**\n * Can be rendered instead of `qrElement` if you only wish to render the qr code with no additional content.\n * Combine with `qrMargin`.\n */\n imageElement: React.ReactElement;\n /**\n * Will be true once the user has completed login in the app and the rest of the login flow is being processed\n */\n isCompleting: boolean;\n /**\n * The user has clicked on the qr image element to trigger fullscreen view per https://developers.bankid.com/getting-started/qr-code#accessibility\n */\n fullscreen: boolean;\n error: OAuth2Error | Error | null;\n retry: () => void;\n }) => React.ReactElement;\n\n /** Render fallback element while loading */\n fallback?: React.ReactElement;\n}\n\ninterface QrResponse {\n initialQrCode: string;\n pollUrl: string;\n}\ninterface PollResponse {\n qrCode?: string;\n targetUrl?: string;\n}\n\nfunction searchParamsToPOJO(input: URLSearchParams) {\n return Array.from(input.keys()).reduce((memo: { [key: string]: string }, key) => {\n memo[key] = input.get(key)!;\n return memo;\n }, {});\n}\n\nexport default function SEBankIDQrCode(props: Props) {\n const wrapperRef = useRef<HTMLButtonElement>(null);\n const {\n buildAuthorizeUrl,\n completionStrategy,\n handleResponse,\n generatePKCE,\n redirectUri: defaultRedirectURi,\n uiLocales,\n } = useContext(CriiptoVerifyContext);\n const language = (props.language ?? uiLocales ?? 'en') as Language;\n const redirectUri = props.redirectUri || defaultRedirectURi;\n const [qrCode, setQrCode] = useState<string | null>(null);\n const [pollUrl, setPollUrl] = useState<string | null>(null);\n const [error, setError] = useState<OAuth2Error | Error | null>(null);\n const [pkce, setPKCE] = useState<PKCE | undefined>(undefined);\n const [isCompleting, setCompleting] = useState(false);\n const [fullscreen, setFullscreen] = useState(false);\n\n const refresh = useCallback(async () => {\n setError(null);\n setQrCode(null);\n setPollUrl(null);\n setPKCE(undefined);\n\n const pkce = await generatePKCE();\n\n buildAuthorizeUrl({\n acrValues: 'urn:grn:authn:se:bankid:another-device:qr',\n responseMode: 'json',\n pkce,\n redirectUri,\n prompt: 'login', // Triggering SSO at this point would be a mistake\n })\n .then((url) => {\n return fetch(url).then((response) => response.json() as Promise<QrResponse>);\n })\n .then((response) => {\n setPKCE(pkce);\n setQrCode(response.initialQrCode);\n setPollUrl(response.pollUrl);\n })\n .catch(console.error);\n }, [buildAuthorizeUrl, redirectUri]);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n const handleRetry = () => {\n setCompleting(false);\n refresh();\n };\n\n const handleError = useCallback(\n (error: string) => {\n /* Timeout error */\n if (error === 'Collect failed: startFailed' || error === '\"Collect failed: startFailed\"') {\n handleRetry();\n return;\n }\n setError(new Error(error));\n handleResponse(new Error(error), {\n pkce,\n redirectUri,\n source: 'SEBankIDQrCode',\n });\n },\n [pkce, redirectUri],\n );\n\n const handleComplete = useCallback(\n async (completeUrl: string) => {\n setCompleting(true);\n const required = { pkce };\n const parsed = await parseCompleteUrl(completeUrl);\n\n if (parsed instanceof Error) {\n return handleError(parsed.message);\n }\n\n const { location, response } = parsed;\n\n if (completionStrategy === 'openidprovider') {\n window.location.href = location;\n return;\n }\n await handleResponse(response, {\n pkce: required.pkce,\n redirectUri,\n source: 'SEBankIDQrCode',\n });\n },\n [completionStrategy, pkce],\n );\n\n /**\n * Render QR codes\n */\n const qrDataURL = useDraw(qrCode, {\n width: fullscreen\n ? (window.innerHeight ?? wrapperRef.current?.offsetWidth)\n : wrapperRef.current?.offsetWidth,\n // 2 is half of the default 4, less margin is required in fullscreen\n qrMargin: props.qrMargin ?? (fullscreen ? 2 : undefined),\n });\n\n /**\n * Poll for response\n */\n usePoll(pollUrl, {\n enabled: !isCompleting,\n onQrCode: setQrCode,\n onComplete: handleComplete,\n onError: handleError,\n });\n\n const i18n = getI18n(language);\n\n const imageElement = (\n <button\n aria-label={i18n.thisIsTheQR}\n ref={wrapperRef}\n className=\"criipto-se-bankid-qr-canvas\"\n onClick={() => setFullscreen((val) => !val)}\n >\n {qrDataURL ? <img src={qrDataURL} /> : null}\n </button>\n );\n\n const qrElement = (\n <div className=\"criipto-se-bankid-qr\">\n <aside className=\"criipto-se-bankid-qr--help-text\">\n {isCompleting ? i18n.completingLogin : i18n.openAndScan}\n <img src={logo} />\n </aside>\n\n {imageElement}\n </div>\n );\n\n if (!qrCode && props.fallback) {\n return props.fallback;\n }\n\n if (props.children) {\n return props.children({\n qrElement,\n imageElement,\n error,\n isCompleting,\n retry: () => handleRetry(),\n fullscreen,\n });\n }\n\n if (fullscreen) {\n return (\n <dialog className=\"criipto-se-bankid-qr-fullscreen\" open>\n {imageElement}\n </dialog>\n );\n }\n\n return qrElement;\n}\n\nSEBankIDQrCode.acr_values = 'urn:grn:authn:se:bankid:another-device:qr';\n\ntype UseDrawOptions = {\n width?: number;\n qrMargin?: number;\n};\nexport function useDraw(qrCode: string | null, options: UseDrawOptions) {\n const { width, qrMargin } = options;\n const [dataURL, setDataURL] = useState<string | null>(null);\n\n useEffect(() => {\n if (!qrCode) return;\n\n let isSubscribed = true;\n (async () => {\n const qrImage = await QRCode.toDataURL(qrCode, {\n errorCorrectionLevel: 'low',\n scale: 10,\n width,\n margin: qrMargin ?? 4,\n });\n\n if (!isSubscribed) return;\n setDataURL(qrImage);\n })();\n\n return () => {\n isSubscribed = false;\n };\n }, [qrCode, qrMargin, width]);\n\n return dataURL;\n}\n\ntype UsePollOptions = {\n enabled: boolean;\n onQrCode: (code: string) => void;\n onComplete: (url: string) => void;\n onError: (error: string) => void;\n};\nexport function usePoll(pollUrl: string | null, options: UsePollOptions) {\n const { onQrCode, onComplete, onError, enabled } = options;\n useEffect(() => {\n if (!pollUrl) return;\n if (!enabled) return;\n\n const delay = 2500;\n let timeout: any;\n let isSubscribed = true;\n const poll = async () => {\n if (!isSubscribed) return;\n const response = await fetch(pollUrl);\n\n if (!isSubscribed) return;\n if (response.status < 400) {\n const payload = (await response.json()) as PollResponse;\n if (payload.qrCode) onQrCode(payload.qrCode);\n if (payload.targetUrl) {\n onComplete(payload.targetUrl);\n return;\n }\n } else {\n const text = await response.text();\n onError(text);\n }\n\n if (response.status === 202) {\n timeout = setTimeout(poll, delay);\n }\n };\n\n timeout = setTimeout(poll, delay);\n return () => {\n isSubscribed = false;\n clearTimeout(timeout);\n };\n }, [pollUrl, onQrCode, onComplete, onError, enabled]);\n}\n\nexport async function parseCompleteUrl(\n completeUrl: string,\n): Promise<{ location: string; response: AuthorizeResponse } | Error> {\n /**\n * Handle verify response inconsistencies\n */\n if (completeUrl.includes('error=')) {\n const url = new URL(completeUrl);\n const completeParams = searchParamsToPOJO(url.searchParams) as AuthorizeResponse;\n\n return { location: completeUrl, response: completeParams };\n }\n\n const completeResponse = await fetch(completeUrl);\n if (completeResponse.status >= 400) {\n return new Error(await completeResponse.text());\n }\n\n const { location }: { location: string } = await completeResponse.json();\n const url = new URL(location);\n const params = searchParamsToPOJO(url.searchParams) as AuthorizeResponse;\n return { location: location, response: params };\n}\n","import React, { createContext, useState } from 'react';\nimport {\n AuthMethodButtonContainer,\n type AuthMethodButtonContainerProps,\n AuthMethodButtonComponent,\n type AuthMethodButtonComponentProps,\n} from './AuthMethodButton';\nimport SEBankIDQrCode from './SEBankIDQRCode';\n\ninterface AuthButtonGroupContextInterface {\n multiple: boolean;\n acrValues: string[];\n disabled: boolean;\n setDisabled: (disabled: boolean) => void;\n}\nconst initialContext: AuthButtonGroupContextInterface = {\n multiple: false,\n acrValues: [],\n disabled: false,\n setDisabled: () => {},\n};\nexport const AuthButtonGroupContext =\n createContext<AuthButtonGroupContextInterface>(initialContext);\n\nexport default function AuthButtonGroup(props: { children: React.ReactNode }) {\n const acrValues = React.Children.toArray(props.children).flatMap((child) => {\n if (!child || typeof child !== 'object') return [];\n if ('type' in child) {\n if (child.type === AuthMethodButtonContainer) {\n const props = child.props as AuthMethodButtonContainerProps;\n return props.acrValue ? [props.acrValue] : [];\n }\n if (child.type === AuthMethodButtonComponent) {\n const props = child.props as AuthMethodButtonComponentProps;\n return props.acrValue ? [props.acrValue] : [];\n }\n if (child.type === SEBankIDQrCode) {\n return ['urn:grn:authn:se:bankid:another-device:qr'];\n }\n }\n return [];\n });\n const [disabled, setDisabled] = useState(false);\n\n const context: AuthButtonGroupContextInterface = {\n multiple: acrValues.length > 1,\n acrValues,\n disabled,\n setDisabled,\n };\n return (\n <AuthButtonGroupContext.Provider value={context}>\n {props.children}\n </AuthButtonGroupContext.Provider>\n );\n}\n","import type { ReactElement } from 'react';\nimport './Spinner.css';\n\nexport function Spinner(): ReactElement {\n return <div className=\"criipto-eid-loader\"></div>;\n}\n","import type { PKCE, AuthorizeResponse } from '@criipto/auth-js';\nimport React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';\nimport CriiptoVerifyContext from '../context';\nimport { getUserAgent } from '../device';\n\nimport PollStrategy from './SEBankIDSameDeviceButton/Poll';\nimport ForegroundStrategy from './SEBankIDSameDeviceButton/Foreground';\nimport ReloadStrategy from './SEBankIDSameDeviceButton/Reload';\n\nimport { autoHydratedState, type Links } from './SEBankIDSameDeviceButton/shared';\nimport { AuthButtonGroupContext } from './AuthButtonGroup';\nimport classNames from 'classnames';\nimport { Spinner } from './Spinner/Spinner';\n\ninterface Props {\n className: string;\n children: React.ReactNode;\n logo: React.ReactNode;\n fallback: React.ReactElement;\n redirectUri?: string;\n userAgent?: string;\n disabled?: boolean;\n}\n\nfunction searchParamsToPOJO(input: URLSearchParams) {\n return Array.from(input.keys()).reduce((memo: { [key: string]: string }, key) => {\n memo[key] = input.get(key)!;\n return memo;\n }, {});\n}\n\ntype Resume = 'Foreground' | 'Reload' | 'Poll';\ntype LinkType = 'universal' | 'scheme';\nexport function determineStrategy(\n input: string | undefined,\n loginHint?: string,\n): {\n resume: Resume;\n linkType: LinkType;\n redirect: boolean;\n} {\n const userAgent = getUserAgent(input);\n const mobileOS =\n userAgent?.os.name === 'iOS'\n ? 'iOS'\n : userAgent?.os.name === 'Android'\n ? 'android'\n : userAgent?.browser.name === 'Samsung Internet'\n ? 'android'\n : null;\n const iOSSafari =\n mobileOS === 'iOS' && userAgent?.browser.name?.includes('Safari') ? true : false;\n const androidChrome =\n mobileOS === 'android' && userAgent?.browser.name === 'Mobile Chrome' ? true : false;\n const redirect = iOSSafari && !loginHint?.includes('appswitch:resumeUrl:disable');\n\n const resume: Resume = mobileOS ? (iOSSafari && redirect ? 'Reload' : 'Foreground') : 'Poll';\n\n const linkType = mobileOS === 'iOS' || androidChrome ? 'universal' : 'scheme';\n\n return { resume, linkType, redirect };\n}\n\nexport class NotDoneError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotDoneError';\n }\n}\n\nasync function fetchComplete(completeUrl: string) {\n const completeResponse = await fetch(completeUrl);\n if (completeResponse.status >= 400) {\n const errorMessage = await completeResponse.text();\n const notDone = errorMessage.includes('Native-app driven authentication is not done');\n if (notDone) return new NotDoneError(errorMessage);\n return new Error(errorMessage);\n }\n\n const { location }: { location: string } = await completeResponse.json();\n return { location };\n}\nexport default function SEBankIDSameDeviceButton(props: Props) {\n const { loginHint } = useContext(CriiptoVerifyContext);\n const group = useContext(AuthButtonGroupContext);\n\n const rawUserAgent = typeof navigator !== 'undefined' ? navigator.userAgent : props.userAgent;\n const strategy = useMemo(\n () => determineStrategy(rawUserAgent, loginHint),\n [rawUserAgent, loginHint],\n );\n\n const [href, setHref] = useState<null | string>();\n const [links, setLinks] = useState<Links | null>(autoHydratedState?.links ?? null);\n const [pkce, setPKCE] = useState<PKCE | undefined>(autoHydratedState?.pkce ?? undefined);\n const [error, setError] = useState<string | null>(null);\n const [log, setLog] = useState<(string | string[])[]>([]);\n const [initiated, setInitiated] = useState(autoHydratedState ? true : false);\n const {\n buildAuthorizeUrl,\n completionStrategy,\n generatePKCE,\n handleResponse,\n redirectUri: defaultRedirectURi,\n domain,\n } = useContext(CriiptoVerifyContext);\n const redirectUri = props.redirectUri || defaultRedirectURi;\n\n const disabled = props.disabled || group.disabled || initiated;\n\n const reset = () => {\n setPKCE(undefined);\n setLinks(null);\n };\n\n const handleLog = (...statements: string[]) => {\n setLog((logs) => logs.concat([statements]));\n };\n\n const handleComplete = useCallback(\n async (completeUrl: string) => {\n const required = { pkce };\n reset();\n\n const result =\n completeUrl.startsWith(`https://${domain}`) || completeUrl.startsWith(`http://${domain}`)\n ? await fetchComplete(completeUrl)\n : {\n location: completeUrl,\n };\n if (result instanceof NotDoneError && strategy.resume === 'Reload') {\n await handleResponse(\n {\n error: 'access_denied',\n },\n {\n pkce: required.pkce,\n redirectUri,\n source: 'SEBankIDSameDeviceButton',\n },\n );\n return;\n }\n if (result instanceof Error) {\n setError(result.message);\n return;\n }\n const { location } = result;\n if (completionStrategy === 'openidprovider') {\n window.location.href = location;\n return;\n }\n const url = new URL(location);\n const params = searchParamsToPOJO(url.searchParams) as AuthorizeResponse;\n\n await handleResponse(params, {\n pkce: required.pkce,\n redirectUri,\n source: 'SEBankIDSameDeviceButton',\n });\n },\n [completionStrategy, pkce, domain, strategy],\n );\n\n const refresh = useCallback(async () => {\n handleLog('SEBankID: Refresh authorize url');\n const pkce = await generatePKCE();\n\n buildAuthorizeUrl({\n acrValues: 'urn:grn:authn:se:bankid:same-device',\n // When used on a mobile device, we might have already set appswitch login hints\n loginHint: loginHint?.includes('appswitch:') ? undefined : 'appswitch:browser',\n responseMode: 'json',\n pkce,\n redirectUri,\n prompt: 'login', // Triggering SSO at this point would be a mistake\n })\n .then((url) => {\n return fetch(url).then((response) => response.json() as Promise<Links>);\n })\n .then((links) => {\n setPKCE(pkce || undefined);\n setLinks(links);\n\n const redirect = strategy.redirect ? window.location.href : 'null';\n const newUrl = new URL(\n strategy.linkType === 'universal'\n ? links.launchLinks.universalLink\n : links.launchLinks.customFileHandlerUrl,\n );\n newUrl.searchParams.set('redirect', redirect);\n const newHref = newUrl.href;\n\n handleLog(window.location.href);\n handleLog(newHref);\n setHref(newHref);\n })\n .catch((err) => {\n setInitiated(false);\n });\n }, [buildAuthorizeUrl, redirectUri, strategy]);\n\n // Generate URL on first button render\n useEffect(() => {\n if (initiated) return;\n refresh();\n }, [refresh, initiated]);\n\n // Continously fetch new autostart token if UI is open for a long time\n useEffect(() => {\n if (initiated) return;\n\n const interval = setInterval(() => {\n if (initiated) return;\n refresh();\n }, 25000);\n return () => clearInterval(interval);\n }, [refresh, initiated]);\n\n // Track when the button is clicked to stop refreshing URL\n const handleInitiate = () => {\n group.setDisabled(true);\n handleLog('Initiated');\n setInitiated(true);\n setError(null);\n };\n\n const handleError = async (error: string) => {\n group.setDisabled(false);\n setInitiated(false);\n setError(error);\n\n if (error === 'access_denied' || error === '\"access_denied\"') {\n await handleResponse(\n {\n error: 'access_denied',\n },\n {\n pkce,\n redirectUri,\n source: 'SEBankIDSameDeviceButton',\n },\n );\n }\n };\n\n const element = href ? (\n <a\n className={classNames(props.className, { 'criipto-eid-btn--disabled': disabled })}\n href={href}\n onClick={handleInitiate}\n >\n {initiated ? (\n <div className=\"criipto-eid-logo\">\n <Spinner />\n </div>\n ) : (\n props.logo\n )}\n {props.children}\n </a>\n ) : (\n props.fallback\n );\n\n return (\n <React.Fragment>\n {links ? (\n <React.Fragment>\n {strategy.resume === 'Poll' ? (\n <PollStrategy\n links={links}\n onError={handleError}\n onComplete={handleComplete}\n onInitiate={handleInitiate}\n onLog={handleLog}\n >\n {element}\n </PollStrategy>\n ) : strategy.resume === 'Foreground' ? (\n <ForegroundStrategy\n links={links}\n onError={handleError}\n onComplete={handleComplete}\n onInitiate={handleInitiate}\n onLog={handleLog}\n >\n {element}\n </ForegroundStrategy>\n ) : strategy.resume === 'Reload' ? (\n <ReloadStrategy\n links={links}\n onError={handleError}\n onComplete={handleComplete}\n onInitiate={handleInitiate}\n onLog={handleLog}\n redirectUri={redirectUri!}\n pkce={pkce}\n >\n {element}\n </ReloadStrategy>\n ) : (\n element\n )}\n </React.Fragment>\n ) : (\n element\n )}\n {error && <p>{error}</p>}\n {/* {log && (\n <pre>\n {JSON.stringify(log, null, 2)}\n </pre>\n )} */}\n </React.Fragment>\n );\n}\n","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAAkCAYAAAANdf2OAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAAlhJREFUeAHtmu1R20AQhteZ/I86iDoIHVgdQAdxB04HIRXgVGBSQaACQQWmA7kDoIJll3uNj0PfYjg0t8/Mju37+OFXe7u3dyL6xDBzIbYVK8V+kjEdETITW0NU5d77/ouMccBbLyAoQ1QVOkP/Fn0ZGf0Rwc4Cb1WRlzXjCoz5TUY7CAPnnrdWKlyXd+JB7MhoRgTKIeghDCwHzF1hXkFGPQgBSk4Dgec/hxH8zhGn/+Oh+SsizVh9SFY0Epl7EuwymkgzVssfPx2zzGvidhcVpQpEKgeML/gYt4dQUGS+Uhw2YuqN2WKxeGgbyK64uPCadPyV2J3YrdeeBWO+iT1SimC5d8ZJhISXJc8u9vqJrStc7NjF/IJSg12SaqzM2CUzn6V6M/ePwSEVp7Sz4GNldtoypgwELnka3+mD+UKRkNh7Ix97sbYDnCuaOdEEBpdi6slFQ/8/cglrtsQW+C85AWvDBHYYG5oxUQWGgJdiq5YEdE0zJrYHKyqgilt7YyEPQfe7NzRToguMZKd21jLsD82UWJVciO4WNprsIPgrtE36fgTNGl507B7f915fLnbifaYNH48hy45xWr013Xic181nV/mtUGh8+D7408DuRoN5ZLXlFS4FGW+Bpymjz3F54CldcqAUnnIYf1gFORlvmbrMuecpXdJMXeaYvyWjHm+ZD9pesTve3GKuvWbVhLdl67XMEVZKCNt7XtLw8bai6TA+vAC95x4vrhjAS3brmvaDtzIPfHHF8IB4FUTVO7idees7gqRVBd66NmHfGXZ3cXZgYxhReAKtoA9h3jxwjgAAAABJRU5ErkJggg==\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,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\"","\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAABICAYAAABWdn8qAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAsKADAAQAAAABAAAASAAAAACoGQzqAAADbUlEQVR4Ae2agVHbMBSGSa8DMIJH6Ab1BmWEdgLSCWImgE4AjNAJmhE6gkdgg/R/xXAc957tEMeWrE93hvCkSL8+/XlIdi4uKBCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCJxG4HA4NLrWUupTaAjC9wBEc0q/qb33U2qC0PNKYPf6ihchAQwcolm8olYG3S6uInEBGDjtBdrJxJdpS1xWHQZelv/Q6GZethI9lD731K2p6q8m83viCZm5roM+b4L4+/AYc26VhR83m43NgbJmAlro6C7E/dTz1liVLreMHct9sx/8M7bPl3bqhrsQLzD4vTgBO9BdLa4iQQHsgRNclEDSrUxs2xbKGwIY+A2MRF620vHoaKkU2zrxokMYOM3lbyTryZF2rSxcOfFiQxg4waXXHYdWsn450mwLMfmB1BknmxAGTnep7iTNy8J2oKvTlT2vMgw8L+/RoykLm3m9LGx93HOge0aJgZ85pPozysKVBG9TFT2nLgw8J+0jxxrIwhzoxLMUA0dPpfSfeFSpj/TelM2jLHypQW6nHCjHvkoxcI5r819zl4Wj71Zc6eNXZzu5CYRj4AkgnrsLmdiy8D4Yp+gsjIEDVyQYjrLwF2XhYg90GDhBp3qSlIX3inuPmK35Tia2PXFxhe8Dj1vydlyzs7eyTPtN13uz2t9W1+gqqhRjYGWwJveVtQOdMq093PC+CG+31R7Ups19nsfoZwtxDK0E2nYfxNaRYlnYM7bTdD0hDJznWv4IZNv97iqoW2UYA2e4rMrCe8m2yytF3VbDwJ4F8ohZFn5ypBb1cAMDOw7IIdQd1qJvqxWzF8bAObg11ninqtaprhX76sRXF8LAGS+psrBtIcIDXcZTGy0dA49GlWbDgQNdmqInVIWBJ4S5YFdRFl5Q0jxDY+B5OJ91lO5Ad3PWQRLtHAMnujAfkGUHOu+22ge6yuctGDiftepV2h3ofvY2WmElBl7RosrED5rOfkVTGpwKBh5ElF2DovbCGDg7f/YL7m6rRU/o+t9MLQQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAuMI/AMbHRP0yohB0QAAAABJRU5ErkJggg==\"","import React from 'react';\nimport dkmitid from './logos/dkmitid.png';\nimport dkmitiderhverv from './logos/dkmitiderhverv.png';\nimport ftnmobile from './logos/ftnmobile.png';\nimport itsme from './logos/itsme.png';\nimport nobankid from './logos/nobankid.png';\nimport novipps from './logos/novipps.png';\nimport mobilepay from './logos/mobilepay.png';\nimport sebankid from './logos/sebankid.png';\nimport sefrejaid from './logos/sefrejaid.png';\nimport depersonalausweis from './logos/depersonalausweis.png';\nimport ukoneid from './logos/ukoneid.png';\nimport idin from './logos/idin.png';\nimport ftn from './logos/ftn.png';\n\nexport interface AuthMethodButtonLogoProps {\n acrValue: string;\n loginHint?: string;\n /**\n * base64 image string, e.x. data:image/png;base64,\n * or a ReactElement\n */\n logo?: React.ReactElement | string;\n}\nexport default function AuthMethodButtonLogo(props: AuthMethodButtonLogoProps) {\n const logo =\n typeof props.logo === 'string' ? (\n <img src={props.logo} alt=\"\" />\n ) : (\n (props.logo ??\n (acrValueToLogo(props.acrValue, props.loginHint) ? (\n <img src={acrValueToLogo(props.acrValue, props.loginHint)} alt=\"\" />\n ) : (\n <span> </span>\n )))\n );\n\n if (logo) return <div className=\"criipto-eid-logo\">{logo}</div>;\n return null;\n}\n\nfunction acrValueToLogo(value: string, loginHint: string | undefined) {\n if (value.startsWith('urn:grn:authn:dk:mitid:business')) {\n return dkmitiderhverv;\n }\n if (value.startsWith('urn:grn:authn:dk:mitid')) {\n return dkmitid;\n }\n if (value.startsWith('urn:grn:authn:fi:mobile')) {\n return ftnmobile;\n }\n if (value.startsWith('urn:grn:authn:fi')) {\n return ftn;\n }\n if (value.startsWith('urn:grn:authn:itsme')) {\n return itsme;\n }\n if (value.startsWith('urn:grn:authn:se:bankid')) {\n return sebankid;\n }\n if (value.startsWith('urn:grn:authn:no:bankid')) {\n return nobankid;\n }\n if (value.startsWith('urn:grn:authn:no:vipps')) {\n const marketHint = loginHint?.split(' ').find((s) => s.startsWith('market:'));\n if (marketHint === 'market:DK' || marketHint === 'market:FI') {\n return mobilepay;\n }\n return novipps;\n }\n if (value.startsWith('urn:grn:authn:se:frejaid')) {\n return sefrejaid;\n }\n if (value.startsWith('urn:grn:authn:uk:oneid')) {\n return ukoneid;\n }\n if (value.startsWith('urn:grn:authn:de:personalausweis')) {\n return depersonalausweis;\n }\n if (value.startsWith('urn:grn:authn:nl:idin')) {\n return idin;\n }\n}\n","import React from 'react';\nimport classNames from 'classnames';\n\ninterface ButtonProps {\n className?: string;\n children: React.ReactNode;\n onClick?: React.MouseEventHandler;\n disabled?: boolean;\n}\nexport function AnchorButton(props: AnchorButtonProps) {\n return (\n <a\n className={classNames(`criipto-verify-button`, props.className)}\n href={props.href}\n aria-disabled={props.disabled}\n onClick={props.onClick}\n >\n {props.children}\n </a>\n );\n}\n\ninterface AnchorButtonProps extends ButtonProps {\n href: string;\n}\nexport function Button(props: ButtonProps) {\n return (\n <button\n className={classNames(`criipto-verify-button`, props.className)}\n type=\"button\"\n disabled={props.disabled}\n onClick={props.onClick}\n >\n {props.children}\n </button>\n );\n}\n","import React, { useContext, useEffect, useState } from 'react';\n\nimport './AuthMethodButton/AuthMethodButton.css';\nimport CriiptoVerifyContext, { type Action } from '../context';\nimport SEBankIDSameDeviceButton from './SEBankIDSameDeviceButton';\nimport { savePKCEState } from '@criipto/auth-js';\nimport AuthMethodButtonLogo, { type AuthMethodButtonLogoProps } from './AuthMethodButton/Logo';\nimport { AnchorButton, Button } from './Button';\nimport { acrValueToTitle, isAmbiguous, isSingle, stringifyAction } from '../utils';\nimport { AuthButtonGroupContext } from './AuthButtonGroup';\nimport { type Language } from '../i18n';\nimport { Spinner } from './Spinner/Spinner';\nimport classNames from 'classnames';\n\nexport type PopupParams = {\n acrValue: string;\n onHide: () => void;\n};\nexport type PopupOption = boolean | ((options: PopupParams) => boolean | React.ReactElement);\n\nexport interface AuthMethodButtonComponentProps {\n acrValue: string;\n href?: string;\n onClick?: React.MouseEventHandler;\n children?: React.ReactNode;\n 'data-testid'?: string;\n className?: string;\n /**\n * base64 image string, e.x. data:image/png;base64,\n * or a ReactElement\n */\n logo?: AuthMethodButtonLogoProps['logo'];\n /**\n * Impacts the button text rendered if no text is provided via props.children\n */\n language?: Language;\n /**\n * Impacts the button text rendered if no text is provided via props.children\n */\n action?: Action;\n disabled?: boolean;\n loading?: boolean;\n loginHint?: string;\n}\n\n/**\n * Display only components, does no state management and triggers no login flows on it's own\n */\nexport function AuthMethodButtonComponent(props: AuthMethodButtonComponentProps) {\n const { acrValue, href } = props;\n const group = useContext(AuthButtonGroupContext);\n const standalone = !group.multiple || isSingle(props.acrValue, group.acrValues);\n const language = (props.language ?? 'en') as Language;\n const action = (props.action ?? 'login') as Action;\n\n const disabled = (props.disabled || group.disabled) && !props.loading;\n const className = classNames(`criipto-eid-btn`, acrValueToClassName(acrValue), props.className, {\n 'criipto-eid-btn--disabled': disabled,\n 'criipto-eid-btn--loading': props.loading,\n });\n\n const { title, subtitle } = acrValueToTitle(language, acrValue, {\n disambiguate: isAmbiguous(acrValue, group.acrValues),\n loginHint: props.loginHint,\n });\n const contents = props.children ?? (\n <React.Fragment>\n {stringifyAction(language, action) ? `${stringifyAction(language, action)} ` : ''}\n {title} \n {standalone ? null : lowercaseFirst(subtitle)}\n </React.Fragment>\n );\n\n const inner = (\n <React.Fragment>\n <AuthMethodButtonLogo\n acrValue={acrValue}\n loginHint={props.loginHint}\n logo={props.loading ? <Spinner /> : props.logo}\n />\n <span>{contents}</span>\n </React.Fragment>\n );\n\n const commonProps = {\n ...props,\n className,\n disabled,\n };\n const button = href ? (\n <React.Fragment>\n <AnchorButton {...commonProps} href={href}>\n {inner}\n </AnchorButton>\n </React.Fragment>\n ) : (\n <React.Fragment>\n <Button {...commonProps}>{inner}</Button>\n </React.Fragment>\n );\n\n return button;\n}\n\nexport type AuthMethodButtonContainerProps = AuthMethodButtonComponentProps & {\n redirectUri?: string;\n popup?: PopupOption;\n\n /**\n * Will ammend the login_hint parameter with `message:{base64(message)}` which will set a login/aprove message where available (Danish MitID).\n */\n message?: string;\n\n userAgent?: string;\n};\n\nexport function AuthMethodButtonContainer(props: AuthMethodButtonContainerProps) {\n const { acrValue } = props;\n const group = useContext(AuthButtonGroupContext);\n const standalone = !group.multiple || isSingle(props.acrValue, group.acrValues);\n const context = useContext(CriiptoVerifyContext);\n const { initializePAR } = context;\n const language = (props.language ?? context.uiLocales ?? 'en') as Language;\n const action = (props.action ?? context.action ?? 'login') as Action;\n const className = `criipto-eid-btn ${acrValueToClassName(acrValue)} ${loginHintToClassName(context.loginHint ?? '')} ${\n props.className ? ` ${props.className}` : ''\n }`;\n const [backdrop, setBackdrop] = useState<React.ReactElement | null>(null);\n const [loading, setLoading] = useState<boolean>(props.loading ?? false);\n useEffect(() => {\n setLoading(props.loading ?? false);\n }, [props.loading]);\n\n const redirectUri = props.redirectUri || context.redirectUri;\n\n const handleClick: React.MouseEventHandler = (event) => {\n if (props.href) return;\n\n if (context.pkce && 'code_verifier' in context.pkce) {\n // just-in-time saving of PKCE, in case of man-in-the-browser\n savePKCEState(context.store, {\n response_type: 'id_token',\n pkce_code_verifier: context.pkce.code_verifier,\n redirect_uri: redirectUri!,\n });\n }\n\n if (props.popup) {\n let willPopup =\n typeof props.popup === 'function'\n ? props.popup({\n acrValue,\n onHide: () => setBackdrop(null),\n })\n : props.popup === true;\n\n if (willPopup !== false) {\n event.preventDefault();\n\n if (typeof willPopup === 'boolean') {\n context.loginWithPopup({\n acrValues: [acrValue],\n redirectUri: redirectUri,\n backdrop: true,\n });\n } else {\n setBackdrop(willPopup);\n context.loginWithPopup({\n acrValues: [acrValue],\n redirectUri: redirectUri,\n backdrop: false,\n });\n }\n }\n }\n\n if (props.onClick) props.onClick(event);\n\n if (!event.isDefaultPrevented()) {\n setLoading(true);\n group.setDisabled(true);\n initializePAR({\n redirectUri,\n acrValues: acrValue,\n loginHint: '',\n })\n .then((authorizeUrl) => {\n window.location.href = authorizeUrl.toString();\n })\n .catch((error) => {\n setLoading(false);\n group.setDisabled(false);\n context.handleResponse(error);\n });\n }\n };\n\n const { title, subtitle } = acrValueToTitle(language, acrValue, {\n disambiguate: isAmbiguous(acrValue, group.acrValues),\n loginHint: context.loginHint,\n });\n\n const contents = props.children ?? (\n <React.Fragment>\n {stringifyAction(language, action) ? `${stringifyAction(language, action)} ` : ''}\n {title} \n {standalone ? null : lowercaseFirst(subtitle)}\n </React.Fragment>\n );\n\n const button = (\n <React.Fragment>\n <AuthMethodButtonComponent\n {...props}\n className={className}\n onClick={handleClick}\n loading={loading}\n loginHint={context.loginHint}\n />\n {backdrop}\n </React.Fragment>\n );\n\n if (!props.href && acrValue === 'urn:grn:authn:se:bankid:same-device') {\n return (\n <SEBankIDSameDeviceButton\n redirectUri={props.redirectUri}\n fallback={button}\n className={className}\n userAgent={props.userAgent}\n logo={\n <AuthMethodButtonLogo acrValue={acrValue} loginHint={props.loginHint} logo={props.logo} />\n }\n disabled={props.disabled}\n >\n <span>{contents}</span>\n </SEBankIDSameDeviceButton>\n );\n }\n\n return button;\n}\n\nfunction acrValueToClassName(value: string) {\n value = value.replace('urn:grn:authn:', '');\n const segments = value.split(':');\n const classNames = segments.reduce((memo: string[], segment: string) => {\n if (memo.length) {\n return memo.concat([`${memo[memo.length - 1]}-${segment}`]);\n } else {\n return memo.concat([segment]);\n }\n }, []);\n\n return classNames.map((className) => `criipto-eid-btn--${className}`).join(' ');\n}\n\nfunction loginHintToClassName(value: string) {\n const hints = value.split(' ');\n const marketHint = hints.find((s) => s.startsWith('market:'));\n\n return [marketHint ? `criipto-eid-btn--${marketHint?.replace(':', '-')}` : undefined].filter(\n (id) => id !== undefined,\n );\n}\n\nfunction lowercaseFirst(input?: string) {\n if (!input) return input;\n return input.substring(0, 1).toLowerCase() + input.substr(1, input.length);\n}\n","import { useContext } from 'react';\nimport CriiptoVerifyContext from '../context';\nimport { getUserAgent } from '../device';\nimport { filterAcrValues } from '../utils';\nimport { type Language } from '../i18n';\nimport { AuthMethodButtonContainer, type AuthMethodButtonContainerProps } from './AuthMethodButton';\n\nimport './AuthMethodSelector/AuthMethodSelector.css';\nimport SEBankIDQrCode from './SEBankIDQRCode';\nimport AuthButtonGroup from './AuthButtonGroup';\n\ninterface AuthMethodSelectorProps {\n acrValues?: string[];\n language?: Language;\n onSelect?: (acrValue: string) => void;\n redirectUri?: string;\n popup?: AuthMethodButtonContainerProps['popup'];\n userAgent?: string;\n}\n\nexport default function AuthMethodSelector(props: AuthMethodSelectorProps) {\n const { action, uiLocales, acrValues: configurationAcrValues } = useContext(CriiptoVerifyContext);\n const language = props.language || (uiLocales as Language) || 'en';\n\n const acrValues = filterAcrValues(props.acrValues ?? configurationAcrValues ?? []);\n const onlySweden =\n !!acrValues.length && acrValues.every((s) => s.startsWith('urn:grn:authn:se:bankid:'));\n\n if (onlySweden) {\n return <Sweden {...props} acrValues={acrValues} />;\n }\n\n return (\n <div className=\"criipto-eid-selector\">\n <AuthButtonGroup>\n {acrValues.map((acrValue) => (\n <AuthMethodButtonContainer\n acrValue={acrValue}\n key={acrValue}\n onClick={props.onSelect ? () => props.onSelect!(acrValue) : undefined}\n redirectUri={props.redirectUri}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n ))}\n </AuthButtonGroup>\n </div>\n );\n}\n\ntype SwedenProps = Omit<AuthMethodSelectorProps, 'acrValues'> & {\n acrValues: string[];\n};\n\nexport function Sweden(props: SwedenProps) {\n const { acrValues } = props;\n const { action, uiLocales } = useContext(CriiptoVerifyContext);\n const language = props.language || (uiLocales as Language) || 'en';\n const hasQR = acrValues.includes(SEBankIDQrCode.acr_values);\n const filteredAcrValues = acrValues.filter((s) => s !== SEBankIDQrCode.acr_values);\n\n const userAgent = getUserAgent(\n typeof navigator !== 'undefined' ? navigator.userAgent : props.userAgent,\n );\n const mobileOS =\n userAgent?.os.name === 'iOS' ? 'iOS' : userAgent?.os.name === 'Android' ? 'android' : null;\n const showQR = hasQR && !mobileOS;\n\n return (\n <div className=\"criipto-eid-selector\">\n <AuthButtonGroup>\n {filteredAcrValues.map((acrValue) => (\n <AuthMethodButtonContainer\n acrValue={acrValue}\n key={acrValue}\n onClick={props.onSelect ? () => props.onSelect!(acrValue) : undefined}\n redirectUri={props.redirectUri}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n ))}\n {showQR ? (\n <SEBankIDQrCode\n language={language}\n redirectUri={props.redirectUri}\n fallback={\n <AuthMethodButtonContainer\n acrValue={SEBankIDQrCode.acr_values}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n }\n />\n ) : hasQR && mobileOS ? (\n <AuthMethodButtonContainer\n acrValue={SEBankIDQrCode.acr_values}\n redirectUri={props.redirectUri}\n popup={props.popup}\n language={language}\n action={action}\n userAgent={props.userAgent}\n />\n ) : null}\n </AuthButtonGroup>\n </div>\n );\n}\n","import { useContext } from 'react';\nimport CriiptoVerifyContext from './context';\n\nexport default function useCriiptoVerify() {\n const {\n result,\n claims,\n loginWithRedirect,\n loginWithPopup,\n acrValues,\n isLoading,\n isInitializing,\n logout,\n checkSession,\n } = useContext(CriiptoVerifyContext);\n\n return {\n result,\n /**\n * The claims of the decoded id_token (if available)\n */\n claims,\n /**\n * Set when the provider failed to fetch configuration (e.g. invalid `domain`/`clientID`,\n * or CORS), or when an authentication attempt failed (e.g. user cancellation, OAuth2 errors\n * from the IdP). Always render this in your UI — failures are otherwise silent.\n *\n * `OAuth2Error` for IdP-returned errors, `Error` for everything else.\n */\n error: result && ('error' in result || result instanceof Error) ? result : null,\n loginWithRedirect,\n loginWithPopup,\n acrValues,\n /**\n * Will be true when performing token exchange after redirect or during an initial SSO check\n */\n isLoading,\n /**\n * Will be true until the first set of useEffect hooks have been called\n */\n isInitializing,\n /**\n * Check if there is an existing SSO session.\n */\n checkSession,\n /**\n * Clear local session store and logout of any existing SSO session\n */\n logout,\n };\n}\n"],"mappings":"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"}
|