@criipto/verify-react 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{criipto-verify-react.cjs.css → criipto-verify-react.css} +0 -0
- package/package.json +1 -1
- package/.storybook/addons/client/preset.js +0 -5
- package/.storybook/addons/client/register.js +0 -47
- package/.storybook/main.js +0 -17
- package/.storybook/preview.js +0 -21
- package/.vscode/settings.json +0 -3
- package/dist/criipto-verify-react.esm.css +0 -75
- package/netlify.toml +0 -3
- package/src/components/AuthMethodButton/AuthMethodButton.css +0 -75
- package/src/components/AuthMethodButton/AuthMethodButton.tsx +0 -128
- package/src/components/AuthMethodButton/logos/beeid.png +0 -0
- package/src/components/AuthMethodButton/logos/digid.png +0 -0
- package/src/components/AuthMethodButton/logos/dkmitid.png +0 -0
- package/src/components/AuthMethodButton/logos/dknemid.png +0 -0
- package/src/components/AuthMethodButton/logos/ftnmobile.png +0 -0
- package/src/components/AuthMethodButton/logos/itsme.png +0 -0
- package/src/components/AuthMethodButton/logos/nobankid.png +0 -0
- package/src/components/AuthMethodButton/logos/novipps.png +0 -0
- package/src/components/AuthMethodButton/logos/sebankid.png +0 -0
- package/src/components/AuthMethodButton/logos/sofort.png +0 -0
- package/src/components/AuthMethodButton/package.json +0 -3
- package/src/components/AuthMethodSelector/AuthMethodSelector.stories.tsx +0 -21
- package/src/components/AuthMethodSelector/AuthMethodSelector.tsx +0 -43
- package/src/components/AuthMethodSelector/package.json +0 -3
- package/src/context.ts +0 -28
- package/src/global.d.ts +0 -4
- package/src/index.ts +0 -5
- package/src/provider.tsx +0 -45
- package/src/utils.ts +0 -129
- package/webpack.config.js +0 -72
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const { Fragment } = require('react');
|
|
3
|
-
const { FORCE_RE_RENDER } = require('@storybook/core-events');
|
|
4
|
-
const { addons, types, useEffect } = require('@storybook/addons');
|
|
5
|
-
const { Separator, Form } = require('@storybook/components');
|
|
6
|
-
const { useGlobals } = require('@storybook/api');
|
|
7
|
-
|
|
8
|
-
addons.register("criipto/client-toolbar", () => {
|
|
9
|
-
addons.add("client-toolbar/toolbar", {
|
|
10
|
-
title: "Custom Client Toolbar",
|
|
11
|
-
//👇 Sets the type of UI element in Storybook
|
|
12
|
-
type: types.TOOL,
|
|
13
|
-
//👇 Shows the Toolbar UI element if either the Canvas or Docs tab is active
|
|
14
|
-
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
|
|
15
|
-
render: ({ active }) => {
|
|
16
|
-
const [globals, updateGlobals] = useGlobals();
|
|
17
|
-
const domain = globals.domain;
|
|
18
|
-
const clientID = globals.clientID;
|
|
19
|
-
|
|
20
|
-
const handleDomainChange = (event) => {
|
|
21
|
-
updateGlobals({
|
|
22
|
-
domain: event.target.value,
|
|
23
|
-
});
|
|
24
|
-
// Invokes Storybook's addon API method (with the FORCE_RE_RENDER) event to trigger a UI refresh
|
|
25
|
-
addons.getChannel().emit(FORCE_RE_RENDER);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const handleClientIDChange = (event) => {
|
|
29
|
-
updateGlobals({
|
|
30
|
-
clientID: event.target.value,
|
|
31
|
-
});
|
|
32
|
-
// Invokes Storybook's addon API method (with the FORCE_RE_RENDER) event to trigger a UI refresh
|
|
33
|
-
addons.getChannel().emit(FORCE_RE_RENDER);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<Fragment>
|
|
38
|
-
<Separator />
|
|
39
|
-
<div style={{display: 'flex', alignItems: 'center', gap: '5px'}}>
|
|
40
|
-
<Form.Input style={{minHeight: '20px', padding: '3px 6px', minWidth: '250px'}} value={domain} placeholder="Domain" onChange={handleDomainChange} />
|
|
41
|
-
<Form.Input style={{minHeight: '20px', padding: '3px 6px', minWidth: '250px'}} value={clientID} placeholder="Client ID" onChange={handleClientIDChange} />
|
|
42
|
-
</div>
|
|
43
|
-
</Fragment>
|
|
44
|
-
)
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
});
|
package/.storybook/main.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
"stories": [
|
|
3
|
-
"../src/**/*.stories.mdx",
|
|
4
|
-
"../src/**/*.stories.@(js|jsx|ts|tsx)",
|
|
5
|
-
"../src/**/**/*.stories.@(js|jsx|ts|tsx)"
|
|
6
|
-
],
|
|
7
|
-
"addons": [
|
|
8
|
-
"@storybook/addon-links",
|
|
9
|
-
"@storybook/addon-essentials",
|
|
10
|
-
"@storybook/addon-interactions",
|
|
11
|
-
"./addons/client/preset.js"
|
|
12
|
-
],
|
|
13
|
-
"framework": "@storybook/react",
|
|
14
|
-
"core": {
|
|
15
|
-
"builder": "@storybook/builder-webpack5"
|
|
16
|
-
}
|
|
17
|
-
}
|
package/.storybook/preview.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export const parameters = {
|
|
2
|
-
actions: { argTypesRegex: "^on[A-Z].*" },
|
|
3
|
-
controls: {
|
|
4
|
-
matchers: {
|
|
5
|
-
color: /(background|color)$/i,
|
|
6
|
-
date: /Date$/,
|
|
7
|
-
},
|
|
8
|
-
},
|
|
9
|
-
globalTypes: {
|
|
10
|
-
domain: {
|
|
11
|
-
name: 'Domain',
|
|
12
|
-
description: 'Criipto Verify domain',
|
|
13
|
-
defaultValue: 'samples.criipto.id'
|
|
14
|
-
},
|
|
15
|
-
clientID: {
|
|
16
|
-
name: 'Client ID',
|
|
17
|
-
description: 'Criipto Verify Client ID',
|
|
18
|
-
defaultValue: 'urn:criipto:samples:criipto-verify-react'
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
package/.vscode/settings.json
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
.criipto-verify-button.criipto-verify-button-eid {
|
|
2
|
-
background: #F9F8F4;
|
|
3
|
-
box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.25);
|
|
4
|
-
border-radius: 3px;
|
|
5
|
-
color: black;
|
|
6
|
-
display: flex;
|
|
7
|
-
flex-direction: row;
|
|
8
|
-
align-items: center;
|
|
9
|
-
width: calc(100% - 10px);
|
|
10
|
-
box-sizing: border-box;
|
|
11
|
-
text-decoration: none;
|
|
12
|
-
min-height: 70px;
|
|
13
|
-
border: 0;
|
|
14
|
-
text-align: left;
|
|
15
|
-
|
|
16
|
-
margin: 12px 5px; /* Side margins to preserve drop shadow */
|
|
17
|
-
padding: 12px 24px;
|
|
18
|
-
|
|
19
|
-
font-family: "Raleway", sans-serif;
|
|
20
|
-
font-style: normal;
|
|
21
|
-
font-size: 13px;
|
|
22
|
-
line-height: 18px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.criipto-verify-button.criipto-verify-button-eid strong {
|
|
26
|
-
font-weight: 700;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.criipto-verify-button.criipto-verify-button-eid img {
|
|
30
|
-
height: 24px;
|
|
31
|
-
padding-right: 20px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-no-bankid img {
|
|
35
|
-
height: 18px;
|
|
36
|
-
}
|
|
37
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-nemid {
|
|
38
|
-
color: #0B6062;
|
|
39
|
-
}
|
|
40
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-nemid img {
|
|
41
|
-
width: 66px;
|
|
42
|
-
height: auto;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-mitid {
|
|
46
|
-
background: #0060E6;
|
|
47
|
-
box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.25);
|
|
48
|
-
color: white;
|
|
49
|
-
font-family: "IBM Plex Sans", "Raleway", sans-serif;
|
|
50
|
-
font-style: normal;
|
|
51
|
-
font-weight: 500;
|
|
52
|
-
font-size: 14px;
|
|
53
|
-
line-height: 124%;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-mitid img {
|
|
57
|
-
width: 66px;
|
|
58
|
-
height: auto;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-se-bankid {
|
|
62
|
-
color: #235971;
|
|
63
|
-
}
|
|
64
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-se-bankid img {
|
|
65
|
-
width: 40px;
|
|
66
|
-
height: auto;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-no-bankid img {
|
|
70
|
-
height: 13px;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-fi img {
|
|
74
|
-
height: 40px;
|
|
75
|
-
}
|
package/netlify.toml
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
.criipto-verify-button.criipto-verify-button-eid {
|
|
2
|
-
background: #F9F8F4;
|
|
3
|
-
box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.25);
|
|
4
|
-
border-radius: 3px;
|
|
5
|
-
color: black;
|
|
6
|
-
display: flex;
|
|
7
|
-
flex-direction: row;
|
|
8
|
-
align-items: center;
|
|
9
|
-
width: calc(100% - 10px);
|
|
10
|
-
box-sizing: border-box;
|
|
11
|
-
text-decoration: none;
|
|
12
|
-
min-height: 70px;
|
|
13
|
-
border: 0;
|
|
14
|
-
text-align: left;
|
|
15
|
-
|
|
16
|
-
margin: 12px 5px; /* Side margins to preserve drop shadow */
|
|
17
|
-
padding: 12px 24px;
|
|
18
|
-
|
|
19
|
-
font-family: "Raleway", sans-serif;
|
|
20
|
-
font-style: normal;
|
|
21
|
-
font-size: 13px;
|
|
22
|
-
line-height: 18px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.criipto-verify-button.criipto-verify-button-eid strong {
|
|
26
|
-
font-weight: 700;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.criipto-verify-button.criipto-verify-button-eid img {
|
|
30
|
-
height: 24px;
|
|
31
|
-
padding-right: 20px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-no-bankid img {
|
|
35
|
-
height: 18px;
|
|
36
|
-
}
|
|
37
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-nemid {
|
|
38
|
-
color: #0B6062;
|
|
39
|
-
}
|
|
40
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-nemid img {
|
|
41
|
-
width: 66px;
|
|
42
|
-
height: auto;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-mitid {
|
|
46
|
-
background: #0060E6;
|
|
47
|
-
box-shadow: 0px 1px 6px rgba(0, 0, 0, 0.25);
|
|
48
|
-
color: white;
|
|
49
|
-
font-family: "IBM Plex Sans", "Raleway", sans-serif;
|
|
50
|
-
font-style: normal;
|
|
51
|
-
font-weight: 500;
|
|
52
|
-
font-size: 14px;
|
|
53
|
-
line-height: 124%;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-dk-mitid img {
|
|
57
|
-
width: 66px;
|
|
58
|
-
height: auto;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-se-bankid {
|
|
62
|
-
color: #235971;
|
|
63
|
-
}
|
|
64
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-se-bankid img {
|
|
65
|
-
width: 40px;
|
|
66
|
-
height: auto;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-no-bankid img {
|
|
70
|
-
height: 13px;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.criipto-verify-button.criipto-verify-button-eid.criipto-verify-button-fi img {
|
|
74
|
-
height: 40px;
|
|
75
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import React, {useContext, useEffect, useState} from 'react';
|
|
2
|
-
|
|
3
|
-
import beeid from './logos/beeid.png';
|
|
4
|
-
import digid from './logos/digid.png';
|
|
5
|
-
import dkmitid from './logos/dkmitid.png';
|
|
6
|
-
import dknemid from './logos/dknemid.png';
|
|
7
|
-
import ftnmobile from './logos/ftnmobile.png';
|
|
8
|
-
import itsme from './logos/itsme.png';
|
|
9
|
-
import nobankid from './logos/nobankid.png';
|
|
10
|
-
import novipps from './logos/novipps.png';
|
|
11
|
-
import sebankid from './logos/sebankid.png';
|
|
12
|
-
import sofort from './logos/sofort.png';
|
|
13
|
-
|
|
14
|
-
import './AuthMethodButton.css';
|
|
15
|
-
import CriiptoVerifyContext from '../../context';
|
|
16
|
-
|
|
17
|
-
interface ButtonProps {
|
|
18
|
-
className?: string,
|
|
19
|
-
children: React.ReactNode,
|
|
20
|
-
onClick?: React.MouseEventHandler
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface AnchorButtonProps extends ButtonProps {
|
|
24
|
-
href: string
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function AnchorButton(props: AnchorButtonProps) {
|
|
28
|
-
return (
|
|
29
|
-
<a className={`criipto-verify-button ${props.className}`} href={props.href} onClick={props.onClick}>{props.children}</a>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function Button(props: ButtonProps) {
|
|
34
|
-
return (
|
|
35
|
-
<button className={`criipto-verify-button ${props.className}`} type="button" onClick={props.onClick}>{props.children}</button>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
interface AuthMethodButtonProps {
|
|
40
|
-
acrValue: string,
|
|
41
|
-
href?: string;
|
|
42
|
-
onClick?: React.MouseEventHandler,
|
|
43
|
-
children?: React.ReactNode,
|
|
44
|
-
'data-testid'?: string,
|
|
45
|
-
className?: string,
|
|
46
|
-
redirectUri?: string
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export default function AuthMethodButton(props: AuthMethodButtonProps) {
|
|
50
|
-
const {acrValue} = props;
|
|
51
|
-
const context = useContext(CriiptoVerifyContext);
|
|
52
|
-
const className = `criipto-verify-button-eid ${acrValueToClassName(acrValue)}${props.className ? ` ${props.className}` : ''}`;
|
|
53
|
-
|
|
54
|
-
const [href, setHref] = useState(props.href);
|
|
55
|
-
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
if (props.href) return;
|
|
58
|
-
|
|
59
|
-
context.buildAuthorizeUrl({
|
|
60
|
-
redirectUri: props.redirectUri,
|
|
61
|
-
acrValues: acrValue
|
|
62
|
-
}).then(setHref)
|
|
63
|
-
.catch(console.error);
|
|
64
|
-
}, [props.href, acrValue]);
|
|
65
|
-
|
|
66
|
-
if (href) {
|
|
67
|
-
return (
|
|
68
|
-
<AnchorButton {...props} href={href} className={className}>
|
|
69
|
-
{acrValueToLogo(acrValue) ? <img src={acrValueToLogo(acrValue)} alt="" /> : null}
|
|
70
|
-
<span>{props.children}</span>
|
|
71
|
-
</AnchorButton>
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<Button {...props} className={className}>
|
|
77
|
-
{acrValueToLogo(acrValue) ? <img src={acrValueToLogo(acrValue)} alt="" /> : null}
|
|
78
|
-
<span>{props.children}</span>
|
|
79
|
-
</Button>
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function acrValueToClassName(value: string) {
|
|
84
|
-
value = value.replace('urn:grn:authn:', '');
|
|
85
|
-
const segments = value.split(':');
|
|
86
|
-
const classNames = segments.reduce((memo: string[], segment: string) => {
|
|
87
|
-
if (memo.length) {
|
|
88
|
-
return memo.concat([`${memo[memo.length-1]}-${segment}`])
|
|
89
|
-
} else {
|
|
90
|
-
return memo.concat([segment]);
|
|
91
|
-
}
|
|
92
|
-
}, []);
|
|
93
|
-
|
|
94
|
-
return classNames.map(className => `criipto-verify-button-${className}`).join(' ');
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function acrValueToLogo(value : string) {
|
|
98
|
-
if (value.startsWith('urn:grn:authn:be:eid')) {
|
|
99
|
-
return beeid;
|
|
100
|
-
}
|
|
101
|
-
if (value.startsWith('urn:grn:authn:nl:digid')) {
|
|
102
|
-
return digid;
|
|
103
|
-
}
|
|
104
|
-
if (value.startsWith('urn:grn:authn:dk:mitid')) {
|
|
105
|
-
return dkmitid;
|
|
106
|
-
}
|
|
107
|
-
if (value.startsWith('urn:grn:authn:dk:nemid')) {
|
|
108
|
-
return dknemid;
|
|
109
|
-
}
|
|
110
|
-
if (value.startsWith('urn:grn:authn:fi')) {
|
|
111
|
-
return ftnmobile;
|
|
112
|
-
}
|
|
113
|
-
if (value.startsWith('urn:grn:authn:itsme')) {
|
|
114
|
-
return itsme;
|
|
115
|
-
}
|
|
116
|
-
if (value.startsWith('urn:grn:authn:se:bankid')) {
|
|
117
|
-
return sebankid;
|
|
118
|
-
}
|
|
119
|
-
if (value.startsWith('urn:grn:authn:de:sofort')) {
|
|
120
|
-
return sofort;
|
|
121
|
-
}
|
|
122
|
-
if (value.startsWith('urn:grn:authn:no:bankid')) {
|
|
123
|
-
return nobankid;
|
|
124
|
-
}
|
|
125
|
-
if (value.startsWith('urn:grn:authn:no:vipps')) {
|
|
126
|
-
return novipps;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
|
3
|
-
|
|
4
|
-
import AuthMethodSelector from './AuthMethodSelector';
|
|
5
|
-
import CriiptoVerifyProvider from '../../provider';
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
title: 'Components/AuthMethodSelector',
|
|
9
|
-
component: AuthMethodSelector,
|
|
10
|
-
} as ComponentMeta<typeof AuthMethodSelector>;
|
|
11
|
-
|
|
12
|
-
// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
|
|
13
|
-
const Template: ComponentStory<typeof AuthMethodSelector> = (args, {globals}) => {
|
|
14
|
-
return (
|
|
15
|
-
<CriiptoVerifyProvider domain={globals.domain} clientID={globals.clientID} redirectUri="https://httpbin.org/get">
|
|
16
|
-
<AuthMethodSelector {...args} />
|
|
17
|
-
</CriiptoVerifyProvider>
|
|
18
|
-
);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const Default = Template.bind({});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {OpenIDConfiguration} from '@criipto/auth-js';
|
|
2
|
-
import React, { useContext, useEffect, useState } from 'react';
|
|
3
|
-
import CriiptoVerifyContext from '../../context';
|
|
4
|
-
import { acrValueToTitle, filterAcrValues, Language } from '../../utils';
|
|
5
|
-
import AuthMethodButton from '../AuthMethodButton/AuthMethodButton';
|
|
6
|
-
|
|
7
|
-
interface Props {
|
|
8
|
-
acrValues?: string[],
|
|
9
|
-
language?: Language,
|
|
10
|
-
onSelect?: (acrValue: string) => void,
|
|
11
|
-
redirectUri?: string
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default function AuthMethodSelector(props: Props) {
|
|
15
|
-
const context = useContext(CriiptoVerifyContext);
|
|
16
|
-
const language = props.language || 'en';
|
|
17
|
-
const [configuration, setConfiguration] = useState<OpenIDConfiguration | null>(null);
|
|
18
|
-
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
(async () => {
|
|
21
|
-
const configuration = await context.fetchOpenIDConfiguration();
|
|
22
|
-
setConfiguration(configuration);
|
|
23
|
-
})();
|
|
24
|
-
}, []);
|
|
25
|
-
|
|
26
|
-
const acrValues = filterAcrValues(props.acrValues ?? configuration?.acr_values_supported ?? []);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<React.Fragment>
|
|
30
|
-
{acrValues.map(acrValue => (
|
|
31
|
-
<AuthMethodButton
|
|
32
|
-
acrValue={acrValue}
|
|
33
|
-
key={acrValue}
|
|
34
|
-
onClick={props.onSelect ? (() => props.onSelect!(acrValue)) : undefined}
|
|
35
|
-
redirectUri={props.redirectUri}
|
|
36
|
-
>
|
|
37
|
-
{acrValueToTitle(language, acrValue).title}<br />
|
|
38
|
-
{acrValueToTitle(language, acrValue).subtitle}
|
|
39
|
-
</AuthMethodButton>
|
|
40
|
-
))}
|
|
41
|
-
</React.Fragment>
|
|
42
|
-
)
|
|
43
|
-
}
|
package/src/context.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {OpenIDConfiguration, AuthorizeUrlParamsOptional} from '@criipto/auth-js';
|
|
2
|
-
import { createContext } from 'react';
|
|
3
|
-
|
|
4
|
-
export interface CriiptoVerifyContextInterface {
|
|
5
|
-
loginWithRedirect: () => Promise<void>,
|
|
6
|
-
fetchOpenIDConfiguration: () => Promise<OpenIDConfiguration>,
|
|
7
|
-
buildAuthorizeUrl: (options?: AuthorizeUrlParamsOptional) => Promise<string>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @ignore
|
|
12
|
-
*/
|
|
13
|
-
const stub = (): never => {
|
|
14
|
-
throw new Error('You forgot to wrap your component in <CriiptoVerifyProvider>.');
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @ignore
|
|
19
|
-
*/
|
|
20
|
-
const initialContext = {
|
|
21
|
-
loginWithRedirect: stub,
|
|
22
|
-
fetchOpenIDConfiguration: stub,
|
|
23
|
-
buildAuthorizeUrl: stub
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const CriiptoVerifyContext = createContext<CriiptoVerifyContextInterface>(initialContext);
|
|
27
|
-
|
|
28
|
-
export default CriiptoVerifyContext;
|
package/src/global.d.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import {default as CriiptoVerifyProvider} from './provider';
|
|
2
|
-
import {default as AuthMethodSelector} from './components/AuthMethodSelector';
|
|
3
|
-
import {default as AuthMethodButton} from './components/AuthMethodButton';
|
|
4
|
-
|
|
5
|
-
export {CriiptoVerifyProvider, AuthMethodSelector, AuthMethodButton};
|
package/src/provider.tsx
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React, {useMemo, useState} from 'react';
|
|
2
|
-
import CriiptoAuth, {AuthorizeUrlParamsOptional} from '@criipto/auth-js';
|
|
3
|
-
|
|
4
|
-
import CriiptoVerifyContext, {CriiptoVerifyContextInterface} from './context';
|
|
5
|
-
|
|
6
|
-
export interface CriiptoVerifyProviderOptions {
|
|
7
|
-
domain: string
|
|
8
|
-
clientID: string
|
|
9
|
-
redirectUri?: string;
|
|
10
|
-
children: React.ReactNode
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const CriiptoVerifyProvider = (props: CriiptoVerifyProviderOptions) : JSX.Element => {
|
|
14
|
-
const [client] = useState(
|
|
15
|
-
() => new CriiptoAuth({
|
|
16
|
-
domain: props.domain,
|
|
17
|
-
clientID: props.clientID,
|
|
18
|
-
store: sessionStorage,
|
|
19
|
-
redirectUri: props.redirectUri
|
|
20
|
-
})
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const context = useMemo<CriiptoVerifyContextInterface>(() => {
|
|
24
|
-
return {
|
|
25
|
-
loginWithRedirect: () => client.redirect.authorize({
|
|
26
|
-
redirectUri: window.location.origin
|
|
27
|
-
}),
|
|
28
|
-
fetchOpenIDConfiguration: () => client.fetchOpenIDConfiguration(),
|
|
29
|
-
buildAuthorizeUrl: async (options?: AuthorizeUrlParamsOptional) => {
|
|
30
|
-
return await client.buildAuthorizeUrl(client.buildAuthorizeParams(options || {}));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}, [
|
|
34
|
-
client,
|
|
35
|
-
props.redirectUri
|
|
36
|
-
]);
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<CriiptoVerifyContext.Provider value={context}>
|
|
40
|
-
{props.children}
|
|
41
|
-
</CriiptoVerifyContext.Provider>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export default CriiptoVerifyProvider
|
package/src/utils.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
export const DKMITID_PREFIX = 'urn:grn:authn:dk:mitid';
|
|
2
|
-
|
|
3
|
-
export function lowestMitIDValue(input: string[]) : string | null {
|
|
4
|
-
let dkmitidMethod : string | null = null;
|
|
5
|
-
|
|
6
|
-
input.forEach(s => {
|
|
7
|
-
if (s.startsWith(DKMITID_PREFIX)) {
|
|
8
|
-
if (!dkmitidMethod) {
|
|
9
|
-
dkmitidMethod = s;
|
|
10
|
-
} else {
|
|
11
|
-
let newLevel = s.replace(DKMITID_PREFIX, '');
|
|
12
|
-
let oldLevel = dkmitidMethod.replace(DKMITID_PREFIX, '');
|
|
13
|
-
if (newLevel === ':low' && [':substantial', ':high'].includes(oldLevel)) {
|
|
14
|
-
dkmitidMethod = s;
|
|
15
|
-
}
|
|
16
|
-
else if (newLevel === ':substantial' && oldLevel === ':high') {
|
|
17
|
-
dkmitidMethod = s;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
return dkmitidMethod;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function autoTitleCase(input: string) {
|
|
27
|
-
var segments = input.split(/:|-/).map(segment => {
|
|
28
|
-
segment = segment.replace(/id(\s|$)/, 'ID');
|
|
29
|
-
if (segment.length === 2) return segment.toUpperCase();
|
|
30
|
-
return segment.substr(0, 1).toUpperCase() + segment.substr(1);
|
|
31
|
-
});
|
|
32
|
-
return segments.join(' ');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export type Language = 'en' | 'da' | 'sv' | 'nb';
|
|
36
|
-
|
|
37
|
-
export function acrValueToTitle(language: Language, value: string) : {title: string, subtitle?: string} {
|
|
38
|
-
value = value.replace('urn:grn:authn:', '');
|
|
39
|
-
|
|
40
|
-
if (value.startsWith('be:eid')) {
|
|
41
|
-
return {title: autoTitleCase(value).replace('BEEID', 'Belgian eID')};
|
|
42
|
-
}
|
|
43
|
-
if (value.startsWith('nl:digid')) {
|
|
44
|
-
return {title: autoTitleCase(value).replace('NL ', '')};
|
|
45
|
-
}
|
|
46
|
-
if (value.startsWith('dk:mitid')) {
|
|
47
|
-
return {title: 'MitID'};
|
|
48
|
-
}
|
|
49
|
-
if (value.startsWith('dk:nemid')) {
|
|
50
|
-
let subtitle : string | undefined = undefined;
|
|
51
|
-
let suffix = value.replace('dk:nemid:', '');
|
|
52
|
-
|
|
53
|
-
if (suffix === 'poces') {
|
|
54
|
-
if (language === 'en') subtitle = 'Personal';
|
|
55
|
-
if (language === 'da') subtitle = 'Personlig';
|
|
56
|
-
if (language === 'sv') subtitle = 'Personlig';
|
|
57
|
-
if (language === 'nb') subtitle = 'Personlig';
|
|
58
|
-
}
|
|
59
|
-
if (suffix === 'moces') {
|
|
60
|
-
if (language === 'en') subtitle = 'Employee key card';
|
|
61
|
-
if (language === 'da') subtitle = 'Medarbejder nøglekort';
|
|
62
|
-
if (language === 'sv') subtitle = 'Anställd nyckelkort';
|
|
63
|
-
if (language === 'nb') subtitle = 'Ansatt nøkkelkort';
|
|
64
|
-
}
|
|
65
|
-
if (suffix === 'moces:codefile') {
|
|
66
|
-
if (language === 'en') subtitle = 'Employee key file';
|
|
67
|
-
if (language === 'da') subtitle = 'Medarbejder nøglefil';
|
|
68
|
-
if (language === 'sv') subtitle = 'Anställd nyckelfil';
|
|
69
|
-
if (language === 'nb') subtitle = 'Ansatt nøkkelfil';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
title: 'NemID',
|
|
74
|
-
subtitle
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (value.startsWith('fi')) {
|
|
78
|
-
return {title: autoTitleCase(value).replace('FI', 'FTN')};
|
|
79
|
-
}
|
|
80
|
-
if (value.startsWith('itsme')) {
|
|
81
|
-
return {title: autoTitleCase(value).replace('me', 'ME')};
|
|
82
|
-
}
|
|
83
|
-
if (value.startsWith('se:bankid')) {
|
|
84
|
-
let subtitle : string | undefined = undefined;
|
|
85
|
-
let suffix = value.replace('se:bankid:', '');
|
|
86
|
-
|
|
87
|
-
if (suffix === 'same-device') {
|
|
88
|
-
if (language === 'en') subtitle = 'On this device';
|
|
89
|
-
if (language === 'da') subtitle = 'På denne enhed';
|
|
90
|
-
if (language === 'sv') subtitle = 'På denna enheten';
|
|
91
|
-
if (language === 'nb') subtitle = 'På denne enheten';
|
|
92
|
-
}
|
|
93
|
-
if (suffix === 'another-device') {
|
|
94
|
-
if (language === 'en') subtitle = 'With your SSN';
|
|
95
|
-
if (language === 'da') subtitle = 'Med dit personnummer';
|
|
96
|
-
if (language === 'sv') subtitle = 'Med ditt personnummer';
|
|
97
|
-
if (language === 'nb') subtitle = 'Med personnummeret ditt';
|
|
98
|
-
}
|
|
99
|
-
if (suffix === 'another-device:qr') {
|
|
100
|
-
if (language === 'en') subtitle = 'With QR Code';
|
|
101
|
-
if (language === 'da') subtitle = 'Med QR-kode';
|
|
102
|
-
if (language === 'sv') subtitle = 'Med QR-kod';
|
|
103
|
-
if (language === 'nb') subtitle = 'Med QR-kode';
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return {title: 'BankID', subtitle};
|
|
107
|
-
}
|
|
108
|
-
if (value.startsWith('de:sofort')) {
|
|
109
|
-
return {title: autoTitleCase(value).replace('DE ', '')};
|
|
110
|
-
}
|
|
111
|
-
if (value.startsWith('no:bankid')) {
|
|
112
|
-
return {title: autoTitleCase(value).replace('NO ', '')};
|
|
113
|
-
}
|
|
114
|
-
if (value.startsWith('no:vipps')) {
|
|
115
|
-
return {title: autoTitleCase(value).replace('NO ', '')};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return {title: autoTitleCase(value)};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function filterAcrValues(input: string[]) {
|
|
122
|
-
let original = input.slice();
|
|
123
|
-
let dkmitidMethod : string | null = lowestMitIDValue(input);
|
|
124
|
-
|
|
125
|
-
if (dkmitidMethod) {
|
|
126
|
-
return input.filter(s => !s.startsWith(DKMITID_PREFIX)).concat([dkmitidMethod]).sort((a, b) => original.indexOf(a) - original.indexOf(b));
|
|
127
|
-
}
|
|
128
|
-
return input;
|
|
129
|
-
}
|
package/webpack.config.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const nodeExternals = require('webpack-node-externals');
|
|
3
|
-
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
|
|
6
|
-
module.exports = {
|
|
7
|
-
mode: 'production',
|
|
8
|
-
devtool: "source-map",
|
|
9
|
-
experiments: {
|
|
10
|
-
outputModule: true
|
|
11
|
-
},
|
|
12
|
-
entry: {
|
|
13
|
-
'criipto-verify-react.esm': {
|
|
14
|
-
import: path.resolve(__dirname, 'src/index.ts'),
|
|
15
|
-
library: {
|
|
16
|
-
type: 'module'
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
'criipto-verify-react.cjs': {
|
|
20
|
-
import: path.resolve(__dirname, 'src/index.ts'),
|
|
21
|
-
library: {
|
|
22
|
-
type: 'commonjs'
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
externalsPresets: { node: true },
|
|
27
|
-
externals: [nodeExternals()],
|
|
28
|
-
plugins: [
|
|
29
|
-
new MiniCssExtractPlugin()
|
|
30
|
-
],
|
|
31
|
-
module: {
|
|
32
|
-
rules: [
|
|
33
|
-
{
|
|
34
|
-
test: /\.css$/i,
|
|
35
|
-
use: [
|
|
36
|
-
{
|
|
37
|
-
loader: MiniCssExtractPlugin.loader,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
loader: "css-loader",
|
|
41
|
-
options: {
|
|
42
|
-
sourceMap: false
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
test: /\.tsx?$/,
|
|
49
|
-
exclude: /node_modules/,
|
|
50
|
-
loader: 'ts-loader',
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
test: /\.(png|jpg|gif|svg)$/i,
|
|
54
|
-
use: [
|
|
55
|
-
{
|
|
56
|
-
loader: 'url-loader',
|
|
57
|
-
options: {
|
|
58
|
-
limit: true,
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
resolve: {
|
|
66
|
-
extensions: ['.tsx', '.ts', '.js'],
|
|
67
|
-
},
|
|
68
|
-
output: {
|
|
69
|
-
path: path.resolve(__dirname, 'dist'),
|
|
70
|
-
filename: '[name].js'
|
|
71
|
-
}
|
|
72
|
-
};
|