From 1fd337f4fed08d7867359ec52104a6cadb76cdfc Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 2 Nov 2021 12:31:37 -0300 Subject: refactoring challenge overview to look more like policy reviewing --- .../src/pages/home/AuthenticationEditorScreen.tsx | 2 +- .../pages/home/ChallengeOverviewScreen.stories.tsx | 61 +++++++----- .../src/pages/home/ChallengeOverviewScreen.tsx | 82 +++++++++-------- .../src/pages/home/ReviewPoliciesScreen.tsx | 2 +- .../authMethod/AuthMethodEmailSetup.stories.tsx | 66 +++++++++++++ .../pages/home/authMethod/AuthMethodEmailSetup.tsx | 62 +++++++++++++ .../authMethod/AuthMethodIbanSetup.stories.tsx | 65 +++++++++++++ .../pages/home/authMethod/AuthMethodIbanSetup.tsx | 68 ++++++++++++++ .../authMethod/AuthMethodPostSetup.stories.tsx | 66 +++++++++++++ .../pages/home/authMethod/AuthMethodPostSetup.tsx | 102 +++++++++++++++++++++ .../authMethod/AuthMethodQuestionSetup.stories.tsx | 66 +++++++++++++ .../home/authMethod/AuthMethodQuestionSetup.tsx | 70 ++++++++++++++ .../home/authMethod/AuthMethodSmsSetup.stories.tsx | 66 +++++++++++++ .../pages/home/authMethod/AuthMethodSmsSetup.tsx | 63 +++++++++++++ .../authMethod/AuthMethodTotpSetup.stories.tsx | 64 +++++++++++++ .../pages/home/authMethod/AuthMethodTotpSetup.tsx | 81 ++++++++++++++++ .../authMethod/AuthMethodVideoSetup.stories.tsx | 66 +++++++++++++ .../pages/home/authMethod/AuthMethodVideoSetup.tsx | 56 +++++++++++ .../src/pages/home/authMethod/index.tsx | 68 ++++++++++++++ .../src/pages/home/authMethod/totp.ts | 56 +++++++++++ .../AuthMethodEmailSetup.stories.tsx | 66 ------------- .../home/authMethodSetup/AuthMethodEmailSetup.tsx | 62 ------------- .../AuthMethodIbanSetup.stories.tsx | 65 ------------- .../home/authMethodSetup/AuthMethodIbanSetup.tsx | 68 -------------- .../AuthMethodPostSetup.stories.tsx | 66 ------------- .../home/authMethodSetup/AuthMethodPostSetup.tsx | 102 --------------------- .../AuthMethodQuestionSetup.stories.tsx | 66 ------------- .../authMethodSetup/AuthMethodQuestionSetup.tsx | 70 -------------- .../authMethodSetup/AuthMethodSmsSetup.stories.tsx | 66 ------------- .../home/authMethodSetup/AuthMethodSmsSetup.tsx | 63 ------------- .../AuthMethodTotpSetup.stories.tsx | 64 ------------- .../home/authMethodSetup/AuthMethodTotpSetup.tsx | 81 ---------------- .../AuthMethodVideoSetup.stories.tsx | 66 ------------- .../home/authMethodSetup/AuthMethodVideoSetup.tsx | 56 ----------- .../src/pages/home/authMethodSetup/index.tsx | 68 -------------- .../src/pages/home/authMethodSetup/totp.ts | 56 ----------- 36 files changed, 1167 insertions(+), 1150 deletions(-) create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/index.tsx create mode 100644 packages/anastasis-webui/src/pages/home/authMethod/totp.ts delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/authMethodSetup/totp.ts (limited to 'packages/anastasis-webui/src/pages') diff --git a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx index f4d2aee58..4e7819a77 100644 --- a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx @@ -3,7 +3,7 @@ import { AuthMethod } from "anastasis-core"; import { ComponentChildren, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useAnastasisContext } from "../../context/anastasis"; -import { authMethods, KnownAuthMethods } from "./authMethodSetup"; +import { authMethods, KnownAuthMethods } from "./authMethod"; import { AnastasisClientFrame } from "./index"; diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx index 758963574..a89b5640c 100644 --- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx +++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx @@ -56,17 +56,17 @@ export const SomePoliciesOneSolved = createExample(TestedComponent, { policies: [[{ uuid: '1' }, { uuid: '2' }], [{ uuid: 'uuid-3' }]], challenges: [{ cost: 'USD:1', - instructions: 'just go for it', + instructions: 'this question cost 1 USD', type: 'question', uuid: '1', }, { - cost: 'USD:1', - instructions: 'just go for it', + cost: 'USD:0', + instructions: 'answering this question is free', type: 'question', uuid: '2', }, { cost: 'USD:1', - instructions: 'just go for it', + instructions: 'this question is already answered', type: 'question', uuid: 'uuid-3', }] @@ -84,8 +84,8 @@ export const OneBadConfiguredPolicy = createExample(TestedComponent, { policies: [[{ uuid: '1' }, { uuid: '2' }]], challenges: [{ cost: 'USD:1', - instructions: 'just go for it', - type: 'sasd', + instructions: 'this policy has a missing uuid (the other auth method)', + type: 'totp', uuid: '1', }], }, @@ -101,35 +101,48 @@ export const OnePolicyWithAllTheChallenges = createExample(TestedComponent, { { uuid: '4' }, { uuid: '5' }, { uuid: '6' }, + { uuid: '7' }, + { uuid: '8' }, ]], challenges: [{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'Does P equals NP?', type: 'question', uuid: '1', },{ cost: 'USD:1', - instructions: 'enter a text received by a sms', + instructions: 'SMS to 555-555', type: 'sms', uuid: '2', },{ cost: 'USD:1', - instructions: 'enter a text received by a email', + instructions: 'Email to qwe@asd.com', type: 'email', uuid: '3', },{ cost: 'USD:1', - instructions: 'enter a code based on a time-based one-time password', + instructions: 'Enter 8 digits code for "Anastasis"', type: 'totp', uuid: '4', - },{ - cost: 'USD:1', - instructions: 'send a wire transfer to an account', + },{// + cost: 'USD:0', + instructions: 'Wire transfer from ASDXCVQWE123123 with holder Florian', type: 'iban', uuid: '5', },{ cost: 'USD:1', - instructions: 'just go for it', + instructions: 'Join a video call', + type: 'video',//Enter 8 digits code for "Anastasis" + uuid: '7', + },{ + },{ + cost: 'USD:1', + instructions: 'Letter to address in postal code DE123123', + type: 'post',//Enter 8 digits code for "Anastasis" + uuid: '8', + },{ + cost: 'USD:1', + instructions: 'instruction for an unknown type of challenge', type: 'new-type-of-challenge', uuid: '6', }], @@ -154,52 +167,52 @@ export const OnePolicyWithAllTheChallengesInDifferentState = createExample(Teste ]], challenges: [{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "solved"', type: 'question', uuid: '1', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "hint"', type: 'question', uuid: '2', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "details"', type: 'question', uuid: '3', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "body"', type: 'question', uuid: '4', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "redirect"', type: 'question', uuid: '5', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "server-failure"', type: 'question', uuid: '6', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "truth-unknown"', type: 'question', uuid: '7', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "rate-limit-exceeded"', type: 'question', uuid: '8', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "authentication-timeout"', type: 'question', uuid: '9', },{ cost: 'USD:1', - instructions: 'answer the a question correctly', + instructions: 'in state "external-instructions"', type: 'question', uuid: '10', }], diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx index cf44d5bf4..7b9b060ce 100644 --- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx @@ -1,7 +1,9 @@ +/* eslint-disable @typescript-eslint/camelcase */ import { ChallengeFeedback } from "anastasis-core"; import { h, VNode } from "preact"; import { useAnastasisContext } from "../../context/anastasis"; import { AnastasisClientFrame } from "./index"; +import { authMethods, KnownAuthMethods } from "./authMethod"; export function ChallengeOverviewScreen(): VNode { const reducer = useAnastasisContext() @@ -50,59 +52,61 @@ export function ChallengeOverviewScreen(): VNode { const errors = !atLeastThereIsOnePolicySolved ? "Solve one policy before proceeding" : undefined; return ( - {!policies.length ?

+ {!policies.length ?

No policies found, try with another version of the secret -

: (policies.length === 1 ?

+

: (policies.length === 1 ?

One policy found for this secret. You need to solve all the challenges in order to recover your secret. -

:

+

:

We have found {policies.length} polices. You need to solve all the challenges from one policy in order to recover your secret.

)} - {policiesWithInfo.map((row, i) => { - const tableBody = row.challenges.map(({ info, uuid }) => { + {policiesWithInfo.map((policy, policy_index) => { + const tableBody = policy.challenges.map(({ info, uuid }) => { + const isFree = !info.cost || info.cost.endsWith(':0') + const method = authMethods[info.type as KnownAuthMethods] return ( - - {info.type} - - {info.instructions} - - {info.feedback?.state ?? "unknown"} - {info.cost} - - {info.feedback?.state !== "solved" ? ( - reducer.transition("select_challenge", { uuid })}> - Solve + ); }) + + const policyName = policy.challenges.map(x => x.info.type).join(" + "); + const opa = !atLeastThereIsOnePolicySolved ? undefined : ( policy.isPolicySolved ? undefined : '0.6') return ( -
- Policy #{i + 1} - {row.challenges.length === 0 &&

- This policy doesn't have challenges +

+

+ Policy #{policy_index + 1}: {policyName} +

+ {policy.challenges.length === 0 &&

+ This policy doesn't have challenges.

} - {row.challenges.length === 1 &&

- This policy just have one challenge to be solved + {policy.challenges.length === 1 &&

+ This policy just have one challenge.

} - {row.challenges.length > 1 &&

- This policy have {row.challenges.length} challenges + {policy.challenges.length > 1 &&

+ This policy have {policy.challenges.length} challenges.

} - - - - - - - - - - - {tableBody} - -
Challenge typeDescriptionStatusCost
+ {tableBody}
); })} diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx index 6d5220a05..673f215e2 100644 --- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx @@ -2,7 +2,7 @@ import { h, VNode } from "preact"; import { useAnastasisContext } from "../../context/anastasis"; import { AnastasisClientFrame } from "./index"; -import { authMethods, KnownAuthMethods } from "./authMethodSetup"; +import { authMethods, KnownAuthMethods } from "./authMethod"; export function ReviewPoliciesScreen(): VNode { const reducer = useAnastasisContext() diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx new file mode 100644 index 000000000..e178a4955 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx @@ -0,0 +1,66 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../../utils'; +import { authMethods as TestedComponent, KnownAuthMethods } from './index'; + + +export default { + title: 'Pages/backup/authMethods/email', + component: TestedComponent, + args: { + order: 5, + }, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +const type: KnownAuthMethods = 'email' + +export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [] +}); + +export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Email to sebasjm@email.com ', + remove: () => null + }] +}); + +export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Email to sebasjm@email.com', + remove: () => null + },{ + challenge: 'qwe', + type, + instructions: 'Email to someone@sebasjm.com', + remove: () => null + }] +}); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx new file mode 100644 index 000000000..1a6be1b61 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.tsx @@ -0,0 +1,62 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { + encodeCrock, + stringToBytes +} from "@gnu-taler/taler-util"; +import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; +import { AnastasisClientFrame } from "../index"; +import { TextInput } from "../../../components/fields/TextInput"; +import { EmailInput } from "../../../components/fields/EmailInput"; + +const EMAIL_PATTERN = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + +export function AuthMethodEmailSetup({ cancel, addAuthMethod, configured }: AuthMethodSetupProps): VNode { + const [email, setEmail] = useState(""); + const addEmailAuth = (): void => addAuthMethod({ + authentication_method: { + type: "email", + instructions: `Email to ${email}`, + challenge: encodeCrock(stringToBytes(email)), + }, + }); + const emailError = !EMAIL_PATTERN.test(email) ? 'Email address is not valid' : undefined + const errors = !email ? 'Add your email' : emailError + + return ( + +

+ For email authentication, you need to provide an email address. When + recovering your secret, you will need to enter the code you receive by + email. +

+
+ +
+ {configured.length > 0 &&
+
+ Your emails: +
+ {configured.map((c, i) => { + return
+

{c.instructions}

+
+
+ })} +
} +
+
+ + + + +
+
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx new file mode 100644 index 000000000..71f618646 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx @@ -0,0 +1,65 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../../utils'; +import { authMethods as TestedComponent, KnownAuthMethods } from './index'; + + +export default { + title: 'Pages/backup/authMethods/IBAN', + component: TestedComponent, + args: { + order: 5, + }, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +const type: KnownAuthMethods = 'iban' + +export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [] +}); + +export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Wire transfer from QWEASD123123 with holder Sebastian', + remove: () => null + }] +}); +export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Wire transfer from QWEASD123123 with holder Javier', + remove: () => null + },{ + challenge: 'qwe', + type, + instructions: 'Wire transfer from QWEASD123123 with holder Sebastian', + remove: () => null + }] +},); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx new file mode 100644 index 000000000..c9edbfa07 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.tsx @@ -0,0 +1,68 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { + canonicalJson, + encodeCrock, + stringToBytes +} from "@gnu-taler/taler-util"; +import { h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { TextInput } from "../../../components/fields/TextInput"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; +import { AnastasisClientFrame } from "../index"; + +export function AuthMethodIbanSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { + const [name, setName] = useState(""); + const [account, setAccount] = useState(""); + const addIbanAuth = (): void => addAuthMethod({ + authentication_method: { + type: "iban", + instructions: `Wire transfer from ${account} with holder ${name}`, + challenge: encodeCrock(stringToBytes(canonicalJson({ + name, account + }))), + }, + }); + const errors = !name ? 'Add an account name' : ( + !account ? 'Add an account IBAN number' : undefined + ) + return ( + +

+ For bank transfer authentication, you need to provide a bank + account (account holder name and IBAN). When recovering your + secret, you will be asked to pay the recovery fee via bank + transfer from the account you provided here. +

+
+ + +
+ {configured.length > 0 &&
+
+ Your bank accounts: +
+ {configured.map((c, i) => { + return
+

{c.instructions}

+
+
+ })} +
} +
+
+ + + + +
+
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx new file mode 100644 index 000000000..0f1c17495 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx @@ -0,0 +1,66 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../../utils'; +import { authMethods as TestedComponent, KnownAuthMethods } from './index'; + + +export default { + title: 'Pages/backup/authMethods/Post', + component: TestedComponent, + args: { + order: 5, + }, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +const type: KnownAuthMethods = 'post' + +export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [] +}); + +export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Letter to address in postal code QWE456', + remove: () => null + }] +}); + +export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Letter to address in postal code QWE456', + remove: () => null + },{ + challenge: 'qwe', + type, + instructions: 'Letter to address in postal code ABC123', + remove: () => null + }] +}); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx new file mode 100644 index 000000000..bfeaaa832 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.tsx @@ -0,0 +1,102 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { + canonicalJson, encodeCrock, + stringToBytes +} from "@gnu-taler/taler-util"; +import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; +import { TextInput } from "../../../components/fields/TextInput"; +import { AnastasisClientFrame } from ".."; + +export function AuthMethodPostSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { + const [fullName, setFullName] = useState(""); + const [street, setStreet] = useState(""); + const [city, setCity] = useState(""); + const [postcode, setPostcode] = useState(""); + const [country, setCountry] = useState(""); + + const addPostAuth = () => { + const challengeJson = { + full_name: fullName, + street, + city, + postcode, + country, + }; + addAuthMethod({ + authentication_method: { + type: "post", + instructions: `Letter to address in postal code ${postcode}`, + challenge: encodeCrock(stringToBytes(canonicalJson(challengeJson))), + }, + }); + }; + + const errors = !fullName ? 'The full name is missing' : ( + !street ? 'The street is missing' : ( + !city ? 'The city is missing' : ( + !postcode ? 'The postcode is missing' : ( + !country ? 'The country is missing' : undefined + ) + ) + ) + ) + return ( + +

+ For postal letter authentication, you need to provide a postal + address. When recovering your secret, you will be asked to enter a + code that you will receive in a letter to that address. +

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + {configured.length > 0 &&
+
+ Your postal code: +
+ {configured.map((c, i) => { + return
+

{c.instructions}

+
+
+ })} +
+
} +
+ + + + +
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx new file mode 100644 index 000000000..3ba4a84ca --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx @@ -0,0 +1,66 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../../utils'; +import { authMethods as TestedComponent, KnownAuthMethods } from './index'; + + +export default { + title: 'Pages/backup/authMethods/Question', + component: TestedComponent, + args: { + order: 5, + }, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +const type: KnownAuthMethods = 'question' + +export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [] +}); + +export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Is integer factorization polynomial? (non-quantum computer)', + remove: () => null + }] +}); + +export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Does P equal NP?', + remove: () => null + },{ + challenge: 'asd', + type, + instructions: 'Are continuous groups automatically differential groups?', + remove: () => null + }] +}); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx new file mode 100644 index 000000000..eab800e35 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.tsx @@ -0,0 +1,70 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { + encodeCrock, + stringToBytes +} from "@gnu-taler/taler-util"; +import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; +import { AnastasisClientFrame } from "../index"; +import { TextInput } from "../../../components/fields/TextInput"; + +export function AuthMethodQuestionSetup({ cancel, addAuthMethod, configured }: AuthMethodSetupProps): VNode { + const [questionText, setQuestionText] = useState(""); + const [answerText, setAnswerText] = useState(""); + const addQuestionAuth = (): void => addAuthMethod({ + authentication_method: { + type: "question", + instructions: questionText, + challenge: encodeCrock(stringToBytes(answerText)), + }, + }); + + const errors = !questionText ? "Add your security question" : ( + !answerText ? 'Add the answer to your question' : undefined + ) + return ( + +
+

+ For security question authentication, you need to provide a question + and its answer. When recovering your secret, you will be shown the + question and you will need to type the answer exactly as you typed it + here. +

+
+ +
+
+ +
+ + {configured.length > 0 &&
+
+ Your security questions: +
+ {configured.map((c, i) => { + return
+

{c.instructions}

+
+
+ })} +
} +
+ + + + +
+
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx new file mode 100644 index 000000000..ae8297ef7 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx @@ -0,0 +1,66 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../../utils'; +import { authMethods as TestedComponent, KnownAuthMethods } from './index'; + + +export default { + title: 'Pages/backup/authMethods/Sms', + component: TestedComponent, + args: { + order: 5, + }, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +const type: KnownAuthMethods = 'sms' + +export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [] +}); + +export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'SMS to +11-1234-2345', + remove: () => null + }] +}); + +export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'SMS to +11-1234-2345', + remove: () => null + },{ + challenge: 'qwe', + type, + instructions: 'SMS to +11-5555-2345', + remove: () => null + }] +}); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx new file mode 100644 index 000000000..9e85af2b2 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.tsx @@ -0,0 +1,63 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { + encodeCrock, + stringToBytes +} from "@gnu-taler/taler-util"; +import { Fragment, h, VNode } from "preact"; +import { useLayoutEffect, useRef, useState } from "preact/hooks"; +import { NumberInput } from "../../../components/fields/NumberInput"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; +import { AnastasisClientFrame } from "../index"; + +export function AuthMethodSmsSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { + const [mobileNumber, setMobileNumber] = useState(""); + const addSmsAuth = (): void => { + addAuthMethod({ + authentication_method: { + type: "sms", + instructions: `SMS to ${mobileNumber}`, + challenge: encodeCrock(stringToBytes(mobileNumber)), + }, + }); + }; + const inputRef = useRef(null); + useLayoutEffect(() => { + inputRef.current?.focus(); + }, []); + const errors = !mobileNumber ? 'Add a mobile number' : undefined + return ( + +
+

+ For SMS authentication, you need to provide a mobile number. When + recovering your secret, you will be asked to enter the code you + receive via SMS. +

+
+ +
+ {configured.length > 0 &&
+
+ Your mobile numbers: +
+ {configured.map((c, i) => { + return
+

{c.instructions}

+
+
+ })} +
} +
+ + + + +
+
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx new file mode 100644 index 000000000..4e46b600e --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx @@ -0,0 +1,64 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../../utils'; +import { authMethods as TestedComponent, KnownAuthMethods } from './index'; + + +export default { + title: 'Pages/backup/authMethods/TOTP', + component: TestedComponent, + args: { + order: 5, + }, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +const type: KnownAuthMethods = 'totp' + +export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [] +}); +export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Enter 8 digits code for "Anastasis"', + remove: () => null + }] +}); +export const WithMoreExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: 'Enter 8 digits code for "Anastasis1"', + remove: () => null + },{ + challenge: 'qwe', + type, + instructions: 'Enter 8 digits code for "Anastasis2"', + remove: () => null + }] +}); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx new file mode 100644 index 000000000..fd0bd0224 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.tsx @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { + encodeCrock, + stringToBytes +} from "@gnu-taler/taler-util"; +import { h, VNode } from "preact"; +import { useMemo, useState } from "preact/hooks"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; +import { AnastasisClientFrame } from "../index"; +import { TextInput } from "../../../components/fields/TextInput"; +import { QR } from "../../../components/QR"; +import { base32enc, computeTOTPandCheck } from "./totp"; + +export function AuthMethodTotpSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { + const [name, setName] = useState("anastasis"); + const [test, setTest] = useState(""); + const digits = 8 + const secretKey = useMemo(() => { + const array = new Uint8Array(32) + return window.crypto.getRandomValues(array) + }, []) + const secret32 = base32enc(secretKey); + const totpURL = `otpauth://totp/${name}?digits=${digits}&secret=${secret32}` + + const addTotpAuth = (): void => addAuthMethod({ + authentication_method: { + type: "totp", + instructions: `Enter ${digits} digits code for "${name}"`, + challenge: encodeCrock(stringToBytes(totpURL)), + }, + }); + + const testCodeMatches = computeTOTPandCheck(secretKey, 8, parseInt(test, 10)); + + const errors = !name ? 'The TOTP name is missing' : ( + !testCodeMatches ? 'The test code doesnt match' : undefined + ); + return ( + +

+ For Time-based One-Time Password (TOTP) authentication, you need to set + a name for the TOTP secret. Then, you must scan the generated QR code + with your TOTP App to import the TOTP secret into your TOTP App. +

+
+ +
+
+ +
+

+ After scanning the code with your TOTP App, test it in the input below. +

+ + {configured.length > 0 &&
+
+ Your TOTP numbers: +
+ {configured.map((c, i) => { + return
+

{c.instructions}

+
+
+ })} +
} +
+
+ + + + +
+
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx new file mode 100644 index 000000000..3c4c7bf39 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.stories.tsx @@ -0,0 +1,66 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../../utils'; +import { authMethods as TestedComponent, KnownAuthMethods } from './index'; +import logoImage from '../../../assets/logo.jpeg' + +export default { + title: 'Pages/backup/authMethods/Video', + component: TestedComponent, + args: { + order: 5, + }, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +const type: KnownAuthMethods = 'video' + +export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [] +}); + +export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: logoImage, + remove: () => null + }] +}); + +export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { + configured: [{ + challenge: 'qwe', + type, + instructions: logoImage, + remove: () => null + },{ + challenge: 'qwe', + type, + instructions: logoImage, + remove: () => null + }] +}); diff --git a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx new file mode 100644 index 000000000..8be999b3f --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodVideoSetup.tsx @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import { + encodeCrock, + stringToBytes +} from "@gnu-taler/taler-util"; +import { h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { ImageInput } from "../../../components/fields/ImageInput"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; +import { AnastasisClientFrame } from "../index"; + +export function AuthMethodVideoSetup({cancel, addAuthMethod, configured}: AuthMethodSetupProps): VNode { + const [image, setImage] = useState(""); + const addVideoAuth = (): void => { + addAuthMethod({ + authentication_method: { + type: "video", + instructions: 'Join a video call', + challenge: encodeCrock(stringToBytes(image)), + }, + }) + }; + return ( + +

+ For video identification, you need to provide a passport-style + photograph. When recovering your secret, you will be asked to join a + video call. During that call, a human will use the photograph to + verify your identity. +

+
+ +
+ {configured.length > 0 &&
+
+ Your photographs: +
+ {configured.map((c, i) => { + return
+ +
+
+ })} +
} +
+
+ + +
+
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/authMethod/index.tsx b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx new file mode 100644 index 000000000..1e1d7bc03 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/index.tsx @@ -0,0 +1,68 @@ +import { h, VNode } from "preact"; +import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; + +import { AuthMethodEmailSetup as EmailScreen } from "./AuthMethodEmailSetup"; +import { AuthMethodIbanSetup as IbanScreen } from "./AuthMethodIbanSetup"; +import { AuthMethodPostSetup as PostalScreen } from "./AuthMethodPostSetup"; +import { AuthMethodQuestionSetup as QuestionScreen } from "./AuthMethodQuestionSetup"; +import { AuthMethodSmsSetup as SmsScreen } from "./AuthMethodSmsSetup"; +import { AuthMethodTotpSetup as TotpScreen } from "./AuthMethodTotpSetup"; +import { AuthMethodVideoSetup as VideScreen } from "./AuthMethodVideoSetup"; +import postalIcon from '../../../assets/icons/auth_method/postal.svg'; +import questionIcon from '../../../assets/icons/auth_method/question.svg'; +import smsIcon from '../../../assets/icons/auth_method/sms.svg'; +import videoIcon from '../../../assets/icons/auth_method/video.svg'; + +interface AuthMethodConfiguration { + icon: VNode; + label: string; + screen: (props: AuthMethodSetupProps) => VNode; +} +export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban"; + +type KnowMethodConfig = { + [name in KnownAuthMethods]: AuthMethodConfiguration; +}; + +export const authMethods: KnowMethodConfig = { + question: { + icon: , + label: "Question", + screen: QuestionScreen + }, + sms: { + icon: , + label: "SMS", + screen: SmsScreen + }, + email: { + icon: , + label: "Email", + screen: EmailScreen + + }, + iban: { + icon: , + label: "IBAN", + screen: IbanScreen + + }, + post: { + icon: , + label: "Physical mail", + screen: PostalScreen + + }, + totp: { + icon: , + label: "TOTP", + screen: TotpScreen + + }, + video: { + icon: , + label: "Video", + screen: VideScreen + + } +} \ No newline at end of file diff --git a/packages/anastasis-webui/src/pages/home/authMethod/totp.ts b/packages/anastasis-webui/src/pages/home/authMethod/totp.ts new file mode 100644 index 000000000..0bc3feaf8 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/authMethod/totp.ts @@ -0,0 +1,56 @@ +/* eslint-disable @typescript-eslint/camelcase */ +import jssha from 'jssha' + +const SEARCH_RANGE = 16 +const timeStep = 30 + +export function computeTOTPandCheck(secretKey: Uint8Array, digits: number, code: number): boolean { + const now = new Date().getTime() + const epoch = Math.floor(Math.round(now / 1000.0) / timeStep); + + for (let ms = -SEARCH_RANGE; ms < SEARCH_RANGE; ms++) { + const movingFactor = (epoch + ms).toString(16).padStart(16, "0"); + + const hmacSha = new jssha('SHA-1', 'HEX', { hmacKey: { value: secretKey, format: 'UINT8ARRAY' } }); + hmacSha.update(movingFactor); + const hmac_text = hmacSha.getHMAC('UINT8ARRAY'); + + const offset = (hmac_text[hmac_text.length - 1] & 0xf) + + const otp = (( + (hmac_text[offset + 0] << 24) + + (hmac_text[offset + 1] << 16) + + (hmac_text[offset + 2] << 8) + + (hmac_text[offset + 3]) + ) & 0x7fffffff) % Math.pow(10, digits) + + if (otp == code) return true + } + return false +} + +const encTable__ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".split('') +export function base32enc(buffer: Uint8Array): string { + let rpos = 0 + let bits = 0 + let vbit = 0 + + let result = "" + while ((rpos < buffer.length) || (vbit > 0)) { + if ((rpos < buffer.length) && (vbit < 5)) { + bits = (bits << 8) | buffer[rpos++]; + vbit += 8; + } + if (vbit < 5) { + bits <<= (5 - vbit); + vbit = 5; + } + result += encTable__[(bits >> (vbit - 5)) & 31]; + vbit -= 5; + } + return result +} + +// const array = new Uint8Array(256) +// const secretKey = window.crypto.getRandomValues(array) +// console.log(base32enc(secretKey)) diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx deleted file mode 100644 index e178a4955..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.stories.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { createExample, reducerStatesExample } from '../../../utils'; -import { authMethods as TestedComponent, KnownAuthMethods } from './index'; - - -export default { - title: 'Pages/backup/authMethods/email', - component: TestedComponent, - args: { - order: 5, - }, - argTypes: { - onUpdate: { action: 'onUpdate' }, - onBack: { action: 'onBack' }, - }, -}; - -const type: KnownAuthMethods = 'email' - -export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [] -}); - -export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Email to sebasjm@email.com ', - remove: () => null - }] -}); - -export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Email to sebasjm@email.com', - remove: () => null - },{ - challenge: 'qwe', - type, - instructions: 'Email to someone@sebasjm.com', - remove: () => null - }] -}); diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx deleted file mode 100644 index e8cee9cb4..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodEmailSetup.tsx +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; -import { Fragment, h, VNode } from "preact"; -import { useState } from "preact/hooks"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; -import { AnastasisClientFrame } from "../index"; -import { TextInput } from "../../../components/fields/TextInput"; -import { EmailInput } from "../../../components/fields/EmailInput"; - -const EMAIL_PATTERN = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ - -export function AuthMethodEmailSetup({ cancel, addAuthMethod, configured }: AuthMethodSetupProps): VNode { - const [email, setEmail] = useState(""); - const addEmailAuth = (): void => addAuthMethod({ - authentication_method: { - type: "email", - instructions: `Email to ${email}`, - challenge: encodeCrock(stringToBytes(email)), - }, - }); - const emailError = !EMAIL_PATTERN.test(email) ? 'Email address is not valid' : undefined - const errors = !email ? 'Add your email' : emailError - - return ( - -

- For email authentication, you need to provide an email address. When - recovering your secret, you will need to enter the code you receive by - email. -

-
- -
- {configured.length > 0 &&
-
- Your emails: -
- {configured.map((c, i) => { - return
-

{c.instructions}

-
-
- })} -
} -
-
- - - - -
-
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx deleted file mode 100644 index 71f618646..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.stories.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { createExample, reducerStatesExample } from '../../../utils'; -import { authMethods as TestedComponent, KnownAuthMethods } from './index'; - - -export default { - title: 'Pages/backup/authMethods/IBAN', - component: TestedComponent, - args: { - order: 5, - }, - argTypes: { - onUpdate: { action: 'onUpdate' }, - onBack: { action: 'onBack' }, - }, -}; - -const type: KnownAuthMethods = 'iban' - -export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [] -}); - -export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Wire transfer from QWEASD123123 with holder Sebastian', - remove: () => null - }] -}); -export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Wire transfer from QWEASD123123 with holder Javier', - remove: () => null - },{ - challenge: 'qwe', - type, - instructions: 'Wire transfer from QWEASD123123 with holder Sebastian', - remove: () => null - }] -},); diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx deleted file mode 100644 index c9edbfa07..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodIbanSetup.tsx +++ /dev/null @@ -1,68 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - canonicalJson, - encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; -import { h, VNode } from "preact"; -import { useState } from "preact/hooks"; -import { TextInput } from "../../../components/fields/TextInput"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; -import { AnastasisClientFrame } from "../index"; - -export function AuthMethodIbanSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { - const [name, setName] = useState(""); - const [account, setAccount] = useState(""); - const addIbanAuth = (): void => addAuthMethod({ - authentication_method: { - type: "iban", - instructions: `Wire transfer from ${account} with holder ${name}`, - challenge: encodeCrock(stringToBytes(canonicalJson({ - name, account - }))), - }, - }); - const errors = !name ? 'Add an account name' : ( - !account ? 'Add an account IBAN number' : undefined - ) - return ( - -

- For bank transfer authentication, you need to provide a bank - account (account holder name and IBAN). When recovering your - secret, you will be asked to pay the recovery fee via bank - transfer from the account you provided here. -

-
- - -
- {configured.length > 0 &&
-
- Your bank accounts: -
- {configured.map((c, i) => { - return
-

{c.instructions}

-
-
- })} -
} -
-
- - - - -
-
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx deleted file mode 100644 index 0f1c17495..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.stories.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { createExample, reducerStatesExample } from '../../../utils'; -import { authMethods as TestedComponent, KnownAuthMethods } from './index'; - - -export default { - title: 'Pages/backup/authMethods/Post', - component: TestedComponent, - args: { - order: 5, - }, - argTypes: { - onUpdate: { action: 'onUpdate' }, - onBack: { action: 'onBack' }, - }, -}; - -const type: KnownAuthMethods = 'post' - -export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [] -}); - -export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Letter to address in postal code QWE456', - remove: () => null - }] -}); - -export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Letter to address in postal code QWE456', - remove: () => null - },{ - challenge: 'qwe', - type, - instructions: 'Letter to address in postal code ABC123', - remove: () => null - }] -}); diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx deleted file mode 100644 index bfeaaa832..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodPostSetup.tsx +++ /dev/null @@ -1,102 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - canonicalJson, encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; -import { Fragment, h, VNode } from "preact"; -import { useState } from "preact/hooks"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; -import { TextInput } from "../../../components/fields/TextInput"; -import { AnastasisClientFrame } from ".."; - -export function AuthMethodPostSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { - const [fullName, setFullName] = useState(""); - const [street, setStreet] = useState(""); - const [city, setCity] = useState(""); - const [postcode, setPostcode] = useState(""); - const [country, setCountry] = useState(""); - - const addPostAuth = () => { - const challengeJson = { - full_name: fullName, - street, - city, - postcode, - country, - }; - addAuthMethod({ - authentication_method: { - type: "post", - instructions: `Letter to address in postal code ${postcode}`, - challenge: encodeCrock(stringToBytes(canonicalJson(challengeJson))), - }, - }); - }; - - const errors = !fullName ? 'The full name is missing' : ( - !street ? 'The street is missing' : ( - !city ? 'The city is missing' : ( - !postcode ? 'The postcode is missing' : ( - !country ? 'The country is missing' : undefined - ) - ) - ) - ) - return ( - -

- For postal letter authentication, you need to provide a postal - address. When recovering your secret, you will be asked to enter a - code that you will receive in a letter to that address. -

-
- -
-
- -
-
- -
-
- -
-
- -
- - {configured.length > 0 &&
-
- Your postal code: -
- {configured.map((c, i) => { - return
-

{c.instructions}

-
-
- })} -
-
} -
- - - - -
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx deleted file mode 100644 index 3ba4a84ca..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.stories.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { createExample, reducerStatesExample } from '../../../utils'; -import { authMethods as TestedComponent, KnownAuthMethods } from './index'; - - -export default { - title: 'Pages/backup/authMethods/Question', - component: TestedComponent, - args: { - order: 5, - }, - argTypes: { - onUpdate: { action: 'onUpdate' }, - onBack: { action: 'onBack' }, - }, -}; - -const type: KnownAuthMethods = 'question' - -export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [] -}); - -export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Is integer factorization polynomial? (non-quantum computer)', - remove: () => null - }] -}); - -export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Does P equal NP?', - remove: () => null - },{ - challenge: 'asd', - type, - instructions: 'Are continuous groups automatically differential groups?', - remove: () => null - }] -}); diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx deleted file mode 100644 index eab800e35..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodQuestionSetup.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; -import { Fragment, h, VNode } from "preact"; -import { useState } from "preact/hooks"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; -import { AnastasisClientFrame } from "../index"; -import { TextInput } from "../../../components/fields/TextInput"; - -export function AuthMethodQuestionSetup({ cancel, addAuthMethod, configured }: AuthMethodSetupProps): VNode { - const [questionText, setQuestionText] = useState(""); - const [answerText, setAnswerText] = useState(""); - const addQuestionAuth = (): void => addAuthMethod({ - authentication_method: { - type: "question", - instructions: questionText, - challenge: encodeCrock(stringToBytes(answerText)), - }, - }); - - const errors = !questionText ? "Add your security question" : ( - !answerText ? 'Add the answer to your question' : undefined - ) - return ( - -
-

- For security question authentication, you need to provide a question - and its answer. When recovering your secret, you will be shown the - question and you will need to type the answer exactly as you typed it - here. -

-
- -
-
- -
- - {configured.length > 0 &&
-
- Your security questions: -
- {configured.map((c, i) => { - return
-

{c.instructions}

-
-
- })} -
} -
- - - - -
-
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx deleted file mode 100644 index ae8297ef7..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.stories.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { createExample, reducerStatesExample } from '../../../utils'; -import { authMethods as TestedComponent, KnownAuthMethods } from './index'; - - -export default { - title: 'Pages/backup/authMethods/Sms', - component: TestedComponent, - args: { - order: 5, - }, - argTypes: { - onUpdate: { action: 'onUpdate' }, - onBack: { action: 'onBack' }, - }, -}; - -const type: KnownAuthMethods = 'sms' - -export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [] -}); - -export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'SMS to +11-1234-2345', - remove: () => null - }] -}); - -export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'SMS to +11-1234-2345', - remove: () => null - },{ - challenge: 'qwe', - type, - instructions: 'SMS to +11-5555-2345', - remove: () => null - }] -}); diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx deleted file mode 100644 index 9e85af2b2..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodSmsSetup.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; -import { Fragment, h, VNode } from "preact"; -import { useLayoutEffect, useRef, useState } from "preact/hooks"; -import { NumberInput } from "../../../components/fields/NumberInput"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; -import { AnastasisClientFrame } from "../index"; - -export function AuthMethodSmsSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { - const [mobileNumber, setMobileNumber] = useState(""); - const addSmsAuth = (): void => { - addAuthMethod({ - authentication_method: { - type: "sms", - instructions: `SMS to ${mobileNumber}`, - challenge: encodeCrock(stringToBytes(mobileNumber)), - }, - }); - }; - const inputRef = useRef(null); - useLayoutEffect(() => { - inputRef.current?.focus(); - }, []); - const errors = !mobileNumber ? 'Add a mobile number' : undefined - return ( - -
-

- For SMS authentication, you need to provide a mobile number. When - recovering your secret, you will be asked to enter the code you - receive via SMS. -

-
- -
- {configured.length > 0 &&
-
- Your mobile numbers: -
- {configured.map((c, i) => { - return
-

{c.instructions}

-
-
- })} -
} -
- - - - -
-
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx deleted file mode 100644 index 4e46b600e..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.stories.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { createExample, reducerStatesExample } from '../../../utils'; -import { authMethods as TestedComponent, KnownAuthMethods } from './index'; - - -export default { - title: 'Pages/backup/authMethods/TOTP', - component: TestedComponent, - args: { - order: 5, - }, - argTypes: { - onUpdate: { action: 'onUpdate' }, - onBack: { action: 'onBack' }, - }, -}; - -const type: KnownAuthMethods = 'totp' - -export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [] -}); -export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Enter 8 digits code for "Anastasis"', - remove: () => null - }] -}); -export const WithMoreExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: 'Enter 8 digits code for "Anastasis1"', - remove: () => null - },{ - challenge: 'qwe', - type, - instructions: 'Enter 8 digits code for "Anastasis2"', - remove: () => null - }] -}); diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx deleted file mode 100644 index db656e630..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodTotpSetup.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; -import { h, VNode } from "preact"; -import { useMemo, useState } from "preact/hooks"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; -import { AnastasisClientFrame } from "../index"; -import { TextInput } from "../../../components/fields/TextInput"; -import { QR } from "../../../components/QR"; -import { base32enc, computeTOTPandCheck } from "./totp"; - -export function AuthMethodTotpSetup({ addAuthMethod, cancel, configured }: AuthMethodSetupProps): VNode { - const [name, setName] = useState("anastasis"); - const [test, setTest] = useState(""); - const digits = 8 - const secretKey = useMemo(() => { - const array = new Uint8Array(32) - return window.crypto.getRandomValues(array) - }, []) - const secret32 = base32enc(secretKey); - const totpURL = `otpauth://totp/${name}?digits=${digits}&secret=${secret32}` - - const addTotpAuth = (): void => addAuthMethod({ - authentication_method: { - type: "totp", - instructions: `Enter ${digits} digits code for ${name}`, - challenge: encodeCrock(stringToBytes(totpURL)), - }, - }); - - const testCodeMatches = computeTOTPandCheck(secretKey, 8, parseInt(test, 10)); - - const errors = !name ? 'The TOTP name is missing' : ( - !testCodeMatches ? 'The test code doesnt match' : undefined - ); - return ( - -

- For Time-based One-Time Password (TOTP) authentication, you need to set - a name for the TOTP secret. Then, you must scan the generated QR code - with your TOTP App to import the TOTP secret into your TOTP App. -

-
- -
-
- -
-

- After scanning the code with your TOTP App, test it in the input below. -

- - {configured.length > 0 &&
-
- Your TOTP numbers: -
- {configured.map((c, i) => { - return
-

{c.instructions}

-
-
- })} -
} -
-
- - - - -
-
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx deleted file mode 100644 index 3c4c7bf39..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.stories.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { createExample, reducerStatesExample } from '../../../utils'; -import { authMethods as TestedComponent, KnownAuthMethods } from './index'; -import logoImage from '../../../assets/logo.jpeg' - -export default { - title: 'Pages/backup/authMethods/Video', - component: TestedComponent, - args: { - order: 5, - }, - argTypes: { - onUpdate: { action: 'onUpdate' }, - onBack: { action: 'onBack' }, - }, -}; - -const type: KnownAuthMethods = 'video' - -export const Empty = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [] -}); - -export const WithOneExample = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: logoImage, - remove: () => null - }] -}); - -export const WithMoreExamples = createExample(TestedComponent[type].screen, reducerStatesExample.authEditing, { - configured: [{ - challenge: 'qwe', - type, - instructions: logoImage, - remove: () => null - },{ - challenge: 'qwe', - type, - instructions: logoImage, - remove: () => null - }] -}); diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx deleted file mode 100644 index d292a9d24..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/AuthMethodVideoSetup.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; -import { h, VNode } from "preact"; -import { useState } from "preact/hooks"; -import { ImageInput } from "../../../components/fields/ImageInput"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; -import { AnastasisClientFrame } from "../index"; - -export function AuthMethodVideoSetup({cancel, addAuthMethod, configured}: AuthMethodSetupProps): VNode { - const [image, setImage] = useState(""); - const addVideoAuth = (): void => { - addAuthMethod({ - authentication_method: { - type: "video", - instructions: image, - challenge: encodeCrock(stringToBytes(image)), - }, - }) - }; - return ( - -

- For video identification, you need to provide a passport-style - photograph. When recovering your secret, you will be asked to join a - video call. During that call, a human will use the photograph to - verify your identity. -

-
- -
- {configured.length > 0 &&
-
- Your photographs: -
- {configured.map((c, i) => { - return
- -
-
- })} -
} -
-
- - -
-
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx b/packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx deleted file mode 100644 index 1e1d7bc03..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/index.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { h, VNode } from "preact"; -import { AuthMethodSetupProps } from "../AuthenticationEditorScreen"; - -import { AuthMethodEmailSetup as EmailScreen } from "./AuthMethodEmailSetup"; -import { AuthMethodIbanSetup as IbanScreen } from "./AuthMethodIbanSetup"; -import { AuthMethodPostSetup as PostalScreen } from "./AuthMethodPostSetup"; -import { AuthMethodQuestionSetup as QuestionScreen } from "./AuthMethodQuestionSetup"; -import { AuthMethodSmsSetup as SmsScreen } from "./AuthMethodSmsSetup"; -import { AuthMethodTotpSetup as TotpScreen } from "./AuthMethodTotpSetup"; -import { AuthMethodVideoSetup as VideScreen } from "./AuthMethodVideoSetup"; -import postalIcon from '../../../assets/icons/auth_method/postal.svg'; -import questionIcon from '../../../assets/icons/auth_method/question.svg'; -import smsIcon from '../../../assets/icons/auth_method/sms.svg'; -import videoIcon from '../../../assets/icons/auth_method/video.svg'; - -interface AuthMethodConfiguration { - icon: VNode; - label: string; - screen: (props: AuthMethodSetupProps) => VNode; -} -export type KnownAuthMethods = "sms" | "email" | "post" | "question" | "video" | "totp" | "iban"; - -type KnowMethodConfig = { - [name in KnownAuthMethods]: AuthMethodConfiguration; -}; - -export const authMethods: KnowMethodConfig = { - question: { - icon: , - label: "Question", - screen: QuestionScreen - }, - sms: { - icon: , - label: "SMS", - screen: SmsScreen - }, - email: { - icon: , - label: "Email", - screen: EmailScreen - - }, - iban: { - icon: , - label: "IBAN", - screen: IbanScreen - - }, - post: { - icon: , - label: "Physical mail", - screen: PostalScreen - - }, - totp: { - icon: , - label: "TOTP", - screen: TotpScreen - - }, - video: { - icon: , - label: "Video", - screen: VideScreen - - } -} \ No newline at end of file diff --git a/packages/anastasis-webui/src/pages/home/authMethodSetup/totp.ts b/packages/anastasis-webui/src/pages/home/authMethodSetup/totp.ts deleted file mode 100644 index 0bc3feaf8..000000000 --- a/packages/anastasis-webui/src/pages/home/authMethodSetup/totp.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import jssha from 'jssha' - -const SEARCH_RANGE = 16 -const timeStep = 30 - -export function computeTOTPandCheck(secretKey: Uint8Array, digits: number, code: number): boolean { - const now = new Date().getTime() - const epoch = Math.floor(Math.round(now / 1000.0) / timeStep); - - for (let ms = -SEARCH_RANGE; ms < SEARCH_RANGE; ms++) { - const movingFactor = (epoch + ms).toString(16).padStart(16, "0"); - - const hmacSha = new jssha('SHA-1', 'HEX', { hmacKey: { value: secretKey, format: 'UINT8ARRAY' } }); - hmacSha.update(movingFactor); - const hmac_text = hmacSha.getHMAC('UINT8ARRAY'); - - const offset = (hmac_text[hmac_text.length - 1] & 0xf) - - const otp = (( - (hmac_text[offset + 0] << 24) + - (hmac_text[offset + 1] << 16) + - (hmac_text[offset + 2] << 8) + - (hmac_text[offset + 3]) - ) & 0x7fffffff) % Math.pow(10, digits) - - if (otp == code) return true - } - return false -} - -const encTable__ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".split('') -export function base32enc(buffer: Uint8Array): string { - let rpos = 0 - let bits = 0 - let vbit = 0 - - let result = "" - while ((rpos < buffer.length) || (vbit > 0)) { - if ((rpos < buffer.length) && (vbit < 5)) { - bits = (bits << 8) | buffer[rpos++]; - vbit += 8; - } - if (vbit < 5) { - bits <<= (5 - vbit); - vbit = 5; - } - result += encTable__[(bits >> (vbit - 5)) & 31]; - vbit -= 5; - } - return result -} - -// const array = new Uint8Array(256) -// const secretKey = window.crypto.getRandomValues(array) -// console.log(base32enc(secretKey)) -- cgit v1.2.3