anastasis: make iban auth work again

This commit is contained in:
Florian Dold 2022-04-14 14:14:02 +02:00
parent aad836ee90
commit bc05050524
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
9 changed files with 92 additions and 51 deletions

View File

@ -28,7 +28,7 @@ export enum ChallengeFeedbackStatus {
TalerPayment = "taler-payment",
Unsupported = "unsupported",
RateLimitExceeded = "rate-limit-exceeded",
AuthIban = "auth-iban",
IbanInstructions = "iban-instructions",
IncorrectAnswer = "incorrect-answer",
}
@ -93,7 +93,7 @@ export interface ChallengeFeedbackRateLimitExceeded {
* IBAN bank transfer.
*/
export interface ChallengeFeedbackBankTransferRequired {
state: ChallengeFeedbackStatus.AuthIban;
state: ChallengeFeedbackStatus.IbanInstructions;
/**
* Amount that should be transfered for a successful authentication.

View File

@ -1,3 +1,22 @@
/*
This file is part of GNU Anastasis
(C) 2021-2022 Anastasis SARL
GNU Anastasis is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Anastasis 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with
GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Imports.
*/
import {
AmountJson,
AmountLike,
@ -22,6 +41,7 @@ import {
TalerSignaturePurpose,
AbsoluteTime,
URL,
j2s,
} from "@gnu-taler/taler-util";
import { anastasisData } from "./anastasis-data.js";
import {
@ -879,7 +899,7 @@ async function pollChallenges(
);
continue;
}
if (feedback.state === ChallengeFeedbackStatus.AuthIban) {
if (feedback.state === ChallengeFeedbackStatus.IbanInstructions) {
const s2 = await requestTruth(state, truth, {
pin: feedback.answer_code,
});
@ -1080,7 +1100,7 @@ async function changeVersion(
): Promise<ReducerStateRecovery | ReducerStateError> {
const st: ReducerStateRecovery = {
...state,
selected_version: args.selection,
selected_version: args,
};
return downloadPolicy(st);
}
@ -1147,9 +1167,10 @@ async function selectChallenge(
if (resp.status === HttpStatusCode.Ok) {
const respBodyJson = await resp.json();
logger.info(`validating ${j2s(respBodyJson)}`);
const instr = codecForChallengeInstructionMessage().decode(respBodyJson);
let feedback: ChallengeFeedback;
switch (instr.method) {
switch (instr.challenge_type) {
case "FILE_WRITTEN": {
feedback = {
state: ChallengeFeedbackStatus.CodeInFile,
@ -1160,12 +1181,12 @@ async function selectChallenge(
}
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,
state: ChallengeFeedbackStatus.IbanInstructions,
answer_code: instr.wire_details.answer_code,
target_business_name: instr.wire_details.business_name,
challenge_amount: instr.wire_details.challenge_amount,
target_iban: instr.wire_details.credit_iban,
wire_transfer_subject: instr.wire_details.wire_transfer_subject,
};
break;
}

View File

@ -20,6 +20,7 @@ import {
buildCodecForUnion,
Codec,
codecForAmountString,
codecForAny,
codecForConstString,
codecForNumber,
codecForString,
@ -137,10 +138,11 @@ export type ChallengeInstructionMessage =
export interface IbanChallengeInstructionMessage {
// What kind of challenge is this?
method: "IBAN_WIRE";
challenge_type: "IBAN_WIRE";
wire_details: {
// How much should be wired?
amount: AmountString;
challenge_amount: AmountString;
// What is the target IBAN?
credit_iban: string;
@ -158,11 +160,12 @@ export interface IbanChallengeInstructionMessage {
// Hint about the origin account that must be used.
debit_account_hint: string;
};
}
export interface PinChallengeInstructionMessage {
// What kind of challenge is this?
method: "TAN_SENT";
challenge_type: "TAN_SENT";
// Where was the PIN code sent? Note that this
// address will most likely have been obscured
@ -172,7 +175,7 @@ export interface PinChallengeInstructionMessage {
export interface FileChallengeInstructionMessage {
// What kind of challenge is this?
method: "FILE_WRITTEN";
challenge_type: "FILE_WRITTEN";
// Name of the file where the PIN code was written.
filename: string;
@ -181,33 +184,28 @@ export interface FileChallengeInstructionMessage {
export const codecForFileChallengeInstructionMessage =
(): Codec<FileChallengeInstructionMessage> =>
buildCodecForObject<FileChallengeInstructionMessage>()
.property("method", codecForConstString("FILE_WRITTEN"))
.property("challenge_type", codecForConstString("FILE_WRITTEN"))
.property("filename", codecForString())
.build("FileChallengeInstructionMessage");
export const codecForPinChallengeInstructionMessage =
(): Codec<PinChallengeInstructionMessage> =>
buildCodecForObject<PinChallengeInstructionMessage>()
.property("method", codecForConstString("TAN_SENT"))
.property("challenge_type", codecForConstString("TAN_SENT"))
.property("tan_address_hint", codecForString())
.build("PinChallengeInstructionMessage");
export const codecForIbanChallengeInstructionMessage =
(): Codec<IbanChallengeInstructionMessage> =>
buildCodecForObject<IbanChallengeInstructionMessage>()
.property("method", codecForConstString("IBAN_WIRE"))
.property("amount", codecForAmountString())
.property("business_name", codecForString())
.property("credit_iban", codecForString())
.property("wire_transfer_subject", codecForString())
.property("answer_code", codecForNumber())
.property("debit_account_hint", codecForString())
.property("challenge_type", codecForConstString("IBAN_WIRE"))
.property("wire_details", codecForAny())
.build("IbanChallengeInstructionMessage");
export const codecForChallengeInstructionMessage =
(): Codec<ChallengeInstructionMessage> =>
buildCodecForUnion<ChallengeInstructionMessage>()
.discriminateOn("method")
.discriminateOn("challenge_type")
.alternative("FILE_WRITTEN", codecForFileChallengeInstructionMessage())
.alternative("IBAN_WIRE", codecForIbanChallengeInstructionMessage())
.alternative("TAN_SENT", codecForPinChallengeInstructionMessage())

View File

@ -221,7 +221,7 @@ export interface ReducerStateRecovery {
/**
* Explicitly selected version by the user.
*/
selected_version?: AggregatedPolicyMetaInfo;
selected_version?: SelectedVersionInfo;
challenge_feedback?: { [uuid: string]: ChallengeFeedback };
@ -464,10 +464,16 @@ export interface ActionArgsUpdateExpiration {
expiration: TalerProtocolTimestamp;
}
export interface ActionArgsChangeVersion {
selection: AggregatedPolicyMetaInfo;
export interface SelectedVersionInfo {
attribute_mask: number;
providers: {
url: string;
version: number;
}[];
}
export type ActionArgsChangeVersion = SelectedVersionInfo;
export interface ActionArgsUpdatePolicy {
policy_index: number;
policy: PolicyMember[];
@ -518,10 +524,8 @@ export interface DiscoveryResult {
cursor?: DiscoveryCursor;
}
export const codecForActionArgsChangeVersion = () =>
buildCodecForObject<ActionArgsChangeVersion>()
.property("selection", codecForAny())
.build("ActionArgsChangeVersion");
// FIXME: specify schema!
export const codecForActionArgsChangeVersion = codecForAny;
export const codecForPolicyMember = () =>
buildCodecForObject<PolicyMember>()

View File

@ -250,7 +250,7 @@ export const OnePolicyWithAllTheChallengesInDifferentState = createExample(
challenge_feedback: {
"uuid-1": { state: ChallengeFeedbackStatus.Solved.toString() },
"uuid-3": {
state: ChallengeFeedbackStatus.AuthIban.toString(),
state: ChallengeFeedbackStatus.IbanInstructions.toString(),
challenge_amount: "EUR:1",
target_iban: "DE12345789000",
target_business_name: "Data Loss Incorporated",

View File

@ -16,7 +16,7 @@ function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {
switch (feedback.state) {
case ChallengeFeedbackStatus.Solved:
return <div />;
case ChallengeFeedbackStatus.AuthIban:
case ChallengeFeedbackStatus.IbanInstructions:
return null;
case ChallengeFeedbackStatus.ServerFailure:
return <div class="block has-text-danger">Server error.</div>;
@ -173,7 +173,7 @@ export function ChallengeOverviewScreen(): VNode {
case ChallengeFeedbackStatus.TruthUnknown:
case ChallengeFeedbackStatus.RateLimitExceeded:
return <div />;
case ChallengeFeedbackStatus.AuthIban:
case ChallengeFeedbackStatus.IbanInstructions:
case ChallengeFeedbackStatus.TalerPayment:
return (
<div>

View File

@ -32,7 +32,7 @@ export function SolveOverviewFeedbackDisplay(props: {
]}
/>
);
case ChallengeFeedbackStatus.AuthIban:
case ChallengeFeedbackStatus.IbanInstructions:
return (
<Notifications
notifications={[

View File

@ -1,5 +1,23 @@
/*
This file is part of GNU Anastasis
(C) 2021-2022 Anastasis SARL
GNU Anastasis is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Anastasis 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with
GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Imports.
*/
import {
ChallengeFeedbackStatus,
ChallengeInfo,
} from "@gnu-taler/anastasis-core";
import { h, VNode } from "preact";

View File

@ -158,7 +158,7 @@ export const TruthUnknownFeedback = createExample(TestedComponent[type].solve, {
} as ReducerState);
const ibanFeedback: ChallengeFeedbackBankTransferRequired = {
state: ChallengeFeedbackStatus.AuthIban,
state: ChallengeFeedbackStatus.IbanInstructions,
challenge_amount: "EUR:1",
target_iban: "DE12345789000",
target_business_name: "Data Loss Incorporated",