diff options
author | Florian Dold <florian@dold.me> | 2022-04-13 21:40:56 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2022-04-13 23:46:34 +0200 |
commit | 4e1fe5eb10a5db44c86becbcef66daacc408239d (patch) | |
tree | 66c619c46a2228dc00ed78b200db6d1be395125b /packages/anastasis-core/src/index.ts | |
parent | bd76b5d76f0e03d2d511b6cc0aae4636a2ec52c9 (diff) | |
download | wallet-core-4e1fe5eb10a5db44c86becbcef66daacc408239d.tar.xz |
anastasis-webui: updated challenge feedback
Diffstat (limited to 'packages/anastasis-core/src/index.ts')
-rw-r--r-- | packages/anastasis-core/src/index.ts | 139 |
1 files changed, 105 insertions, 34 deletions
diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts index 98aba2ce6..055f3fb62 100644 --- a/packages/anastasis-core/src/index.ts +++ b/packages/anastasis-core/src/index.ts @@ -25,6 +25,7 @@ import { } from "@gnu-taler/taler-util"; import { anastasisData } from "./anastasis-data.js"; import { + codecForChallengeInstructionMessage, EscrowConfigurationResponse, RecoveryMetaResponse, TruthUploadRequest, @@ -363,9 +364,10 @@ async function getTruthValue( case "email": case "totp": case "iban": + case "post": return authMethod.challenge; default: - throw Error("unknown auth type"); + throw Error(`unknown auth type '${authMethod.type}'`); } } @@ -947,17 +949,27 @@ async function requestTruth( const hresp = await getResponseHash(truth, solveRequest); - const resp = await fetch(url.href, { - method: "POST", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - body: JSON.stringify({ - truth_decryption_key: truth.truth_key, - h_response: hresp, - }), - }); + let resp: Response; + + try { + resp = await fetch(url.href, { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + body: JSON.stringify({ + truth_decryption_key: truth.truth_key, + h_response: hresp, + }), + }); + } catch (e) { + return { + reducer_type: "error", + code: TalerErrorCode.ANASTASIS_TRUTH_CHALLENGE_FAILED, + hint: "network error", + } as ReducerStateError; + } logger.info( `got POST /truth/.../solve response from ${truth.url}, http status ${resp.status}`, @@ -1007,6 +1019,19 @@ async function requestTruth( return tryRecoverSecret(newState); } + if (resp.status === HttpStatusCode.Forbidden) { + const challengeFeedback: { [x: string]: ChallengeFeedback } = { + ...state.challenge_feedback, + [truth.uuid]: { + state: ChallengeFeedbackStatus.IncorrectAnswer, + }, + }; + return { + ...state, + challenge_feedback: challengeFeedback, + }; + } + return { reducer_type: "error", code: TalerErrorCode.ANASTASIS_TRUTH_CHALLENGE_FAILED, @@ -1072,6 +1097,9 @@ async function selectChallenge( const url = new URL(`/truth/${truth.uuid}/challenge`, truth.url); + const newFeedback = { ...state.challenge_feedback }; + delete newFeedback[truth.uuid]; + switch (truth.escrow_type) { case ChallengeType.Question: case ChallengeType.Totp: { @@ -1079,51 +1107,93 @@ async function selectChallenge( ...state, recovery_state: RecoveryStates.ChallengeSolving, selected_challenge_uuid: truth.uuid, - challenge_feedback: { - ...state.challenge_feedback, - [truth.uuid]: { - state: ChallengeFeedbackStatus.Pending, - }, - }, + challenge_feedback: newFeedback, }; } } - const resp = await fetch(url.href, { - method: "POST", - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - body: JSON.stringify({ - truth_decryption_key: truth.truth_key, - }), - }); + let resp: Response; + + try { + resp = await fetch(url.href, { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + body: JSON.stringify({ + truth_decryption_key: truth.truth_key, + }), + }); + } catch (e) { + const feedback: ChallengeFeedback = { + state: ChallengeFeedbackStatus.ServerFailure, + http_status: 0, + }; + return { + ...state, + recovery_state: RecoveryStates.ChallengeSelecting, + selected_challenge_uuid: truth.uuid, + challenge_feedback: { + ...state.challenge_feedback, + [truth.uuid]: feedback, + }, + }; + } logger.info( `got GET /truth/.../challenge response from ${truth.url}, http status ${resp.status}`, ); if (resp.status === HttpStatusCode.Ok) { + const respBodyJson = await resp.json(); + const instr = codecForChallengeInstructionMessage().decode(respBodyJson); + let feedback: ChallengeFeedback; + switch (instr.method) { + case "FILE_WRITTEN": { + feedback = { + state: ChallengeFeedbackStatus.CodeInFile, + display_hint: "TAN code is in file (for debugging)", + filename: instr.filename, + }; + break; + } + case "IBAN_WIRE": { + feedback = { + state: ChallengeFeedbackStatus.AuthIban, + answer_code: instr.answer_code, + target_business_name: instr.business_name, + challenge_amount: instr.amount, + target_iban: instr.credit_iban, + wire_transfer_subject: instr.wire_transfer_subject, + }; + break; + } + case "TAN_SENT": { + feedback = { + state: ChallengeFeedbackStatus.CodeSent, + address_hint: instr.tan_address_hint, + display_hint: "Code sent to address", + }; + } + } return { ...state, recovery_state: RecoveryStates.ChallengeSolving, selected_challenge_uuid: truth.uuid, challenge_feedback: { ...state.challenge_feedback, - [truth.uuid]: { - state: ChallengeFeedbackStatus.Pending, - }, + [truth.uuid]: feedback, }, }; } - // FIXME: look at response, include in challenge_feedback! + // FIXME: look at more error codes in response return { reducer_type: "error", code: TalerErrorCode.ANASTASIS_TRUTH_CHALLENGE_FAILED, - hint: "got unexpected /truth/.../challenge response status", + hint: `got unexpected /truth/.../challenge response status (${resp.status})`, http_status: resp.status, } as ReducerStateError; } @@ -1727,8 +1797,9 @@ export async function reduceAction( } try { return await h.handler(state, parsedArgs); - } catch (e) { + } catch (e: any) { logger.error("action handler failed"); + logger.error(`${e?.stack ?? e}`); if (e instanceof ReducerError) { return { reducer_type: "error", |