anastasis: make iban auth work again
This commit is contained in:
parent
aad836ee90
commit
bc05050524
@ -28,7 +28,7 @@ export enum ChallengeFeedbackStatus {
|
|||||||
TalerPayment = "taler-payment",
|
TalerPayment = "taler-payment",
|
||||||
Unsupported = "unsupported",
|
Unsupported = "unsupported",
|
||||||
RateLimitExceeded = "rate-limit-exceeded",
|
RateLimitExceeded = "rate-limit-exceeded",
|
||||||
AuthIban = "auth-iban",
|
IbanInstructions = "iban-instructions",
|
||||||
IncorrectAnswer = "incorrect-answer",
|
IncorrectAnswer = "incorrect-answer",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ export interface ChallengeFeedbackRateLimitExceeded {
|
|||||||
* IBAN bank transfer.
|
* IBAN bank transfer.
|
||||||
*/
|
*/
|
||||||
export interface ChallengeFeedbackBankTransferRequired {
|
export interface ChallengeFeedbackBankTransferRequired {
|
||||||
state: ChallengeFeedbackStatus.AuthIban;
|
state: ChallengeFeedbackStatus.IbanInstructions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amount that should be transfered for a successful authentication.
|
* Amount that should be transfered for a successful authentication.
|
||||||
|
@ -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 {
|
import {
|
||||||
AmountJson,
|
AmountJson,
|
||||||
AmountLike,
|
AmountLike,
|
||||||
@ -22,6 +41,7 @@ import {
|
|||||||
TalerSignaturePurpose,
|
TalerSignaturePurpose,
|
||||||
AbsoluteTime,
|
AbsoluteTime,
|
||||||
URL,
|
URL,
|
||||||
|
j2s,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { anastasisData } from "./anastasis-data.js";
|
import { anastasisData } from "./anastasis-data.js";
|
||||||
import {
|
import {
|
||||||
@ -879,7 +899,7 @@ async function pollChallenges(
|
|||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (feedback.state === ChallengeFeedbackStatus.AuthIban) {
|
if (feedback.state === ChallengeFeedbackStatus.IbanInstructions) {
|
||||||
const s2 = await requestTruth(state, truth, {
|
const s2 = await requestTruth(state, truth, {
|
||||||
pin: feedback.answer_code,
|
pin: feedback.answer_code,
|
||||||
});
|
});
|
||||||
@ -1080,7 +1100,7 @@ async function changeVersion(
|
|||||||
): Promise<ReducerStateRecovery | ReducerStateError> {
|
): Promise<ReducerStateRecovery | ReducerStateError> {
|
||||||
const st: ReducerStateRecovery = {
|
const st: ReducerStateRecovery = {
|
||||||
...state,
|
...state,
|
||||||
selected_version: args.selection,
|
selected_version: args,
|
||||||
};
|
};
|
||||||
return downloadPolicy(st);
|
return downloadPolicy(st);
|
||||||
}
|
}
|
||||||
@ -1147,9 +1167,10 @@ async function selectChallenge(
|
|||||||
|
|
||||||
if (resp.status === HttpStatusCode.Ok) {
|
if (resp.status === HttpStatusCode.Ok) {
|
||||||
const respBodyJson = await resp.json();
|
const respBodyJson = await resp.json();
|
||||||
|
logger.info(`validating ${j2s(respBodyJson)}`);
|
||||||
const instr = codecForChallengeInstructionMessage().decode(respBodyJson);
|
const instr = codecForChallengeInstructionMessage().decode(respBodyJson);
|
||||||
let feedback: ChallengeFeedback;
|
let feedback: ChallengeFeedback;
|
||||||
switch (instr.method) {
|
switch (instr.challenge_type) {
|
||||||
case "FILE_WRITTEN": {
|
case "FILE_WRITTEN": {
|
||||||
feedback = {
|
feedback = {
|
||||||
state: ChallengeFeedbackStatus.CodeInFile,
|
state: ChallengeFeedbackStatus.CodeInFile,
|
||||||
@ -1160,12 +1181,12 @@ async function selectChallenge(
|
|||||||
}
|
}
|
||||||
case "IBAN_WIRE": {
|
case "IBAN_WIRE": {
|
||||||
feedback = {
|
feedback = {
|
||||||
state: ChallengeFeedbackStatus.AuthIban,
|
state: ChallengeFeedbackStatus.IbanInstructions,
|
||||||
answer_code: instr.answer_code,
|
answer_code: instr.wire_details.answer_code,
|
||||||
target_business_name: instr.business_name,
|
target_business_name: instr.wire_details.business_name,
|
||||||
challenge_amount: instr.amount,
|
challenge_amount: instr.wire_details.challenge_amount,
|
||||||
target_iban: instr.credit_iban,
|
target_iban: instr.wire_details.credit_iban,
|
||||||
wire_transfer_subject: instr.wire_transfer_subject,
|
wire_transfer_subject: instr.wire_details.wire_transfer_subject,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
buildCodecForUnion,
|
buildCodecForUnion,
|
||||||
Codec,
|
Codec,
|
||||||
codecForAmountString,
|
codecForAmountString,
|
||||||
|
codecForAny,
|
||||||
codecForConstString,
|
codecForConstString,
|
||||||
codecForNumber,
|
codecForNumber,
|
||||||
codecForString,
|
codecForString,
|
||||||
@ -137,32 +138,34 @@ export type ChallengeInstructionMessage =
|
|||||||
|
|
||||||
export interface IbanChallengeInstructionMessage {
|
export interface IbanChallengeInstructionMessage {
|
||||||
// What kind of challenge is this?
|
// What kind of challenge is this?
|
||||||
method: "IBAN_WIRE";
|
challenge_type: "IBAN_WIRE";
|
||||||
|
|
||||||
// How much should be wired?
|
wire_details: {
|
||||||
amount: AmountString;
|
// How much should be wired?
|
||||||
|
challenge_amount: AmountString;
|
||||||
|
|
||||||
// What is the target IBAN?
|
// What is the target IBAN?
|
||||||
credit_iban: string;
|
credit_iban: string;
|
||||||
|
|
||||||
// What is the receiver name?
|
// What is the receiver name?
|
||||||
business_name: string;
|
business_name: string;
|
||||||
|
|
||||||
// What is the expected wire transfer subject?
|
// What is the expected wire transfer subject?
|
||||||
wire_transfer_subject: string;
|
wire_transfer_subject: string;
|
||||||
|
|
||||||
// What is the numeric code (also part of the
|
// What is the numeric code (also part of the
|
||||||
// wire transfer subject) to be hashed when
|
// wire transfer subject) to be hashed when
|
||||||
// solving the challenge?
|
// solving the challenge?
|
||||||
answer_code: number;
|
answer_code: number;
|
||||||
|
|
||||||
// Hint about the origin account that must be used.
|
// Hint about the origin account that must be used.
|
||||||
debit_account_hint: string;
|
debit_account_hint: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PinChallengeInstructionMessage {
|
export interface PinChallengeInstructionMessage {
|
||||||
// What kind of challenge is this?
|
// What kind of challenge is this?
|
||||||
method: "TAN_SENT";
|
challenge_type: "TAN_SENT";
|
||||||
|
|
||||||
// Where was the PIN code sent? Note that this
|
// Where was the PIN code sent? Note that this
|
||||||
// address will most likely have been obscured
|
// address will most likely have been obscured
|
||||||
@ -172,7 +175,7 @@ export interface PinChallengeInstructionMessage {
|
|||||||
|
|
||||||
export interface FileChallengeInstructionMessage {
|
export interface FileChallengeInstructionMessage {
|
||||||
// What kind of challenge is this?
|
// What kind of challenge is this?
|
||||||
method: "FILE_WRITTEN";
|
challenge_type: "FILE_WRITTEN";
|
||||||
|
|
||||||
// Name of the file where the PIN code was written.
|
// Name of the file where the PIN code was written.
|
||||||
filename: string;
|
filename: string;
|
||||||
@ -181,33 +184,28 @@ export interface FileChallengeInstructionMessage {
|
|||||||
export const codecForFileChallengeInstructionMessage =
|
export const codecForFileChallengeInstructionMessage =
|
||||||
(): Codec<FileChallengeInstructionMessage> =>
|
(): Codec<FileChallengeInstructionMessage> =>
|
||||||
buildCodecForObject<FileChallengeInstructionMessage>()
|
buildCodecForObject<FileChallengeInstructionMessage>()
|
||||||
.property("method", codecForConstString("FILE_WRITTEN"))
|
.property("challenge_type", codecForConstString("FILE_WRITTEN"))
|
||||||
.property("filename", codecForString())
|
.property("filename", codecForString())
|
||||||
.build("FileChallengeInstructionMessage");
|
.build("FileChallengeInstructionMessage");
|
||||||
|
|
||||||
export const codecForPinChallengeInstructionMessage =
|
export const codecForPinChallengeInstructionMessage =
|
||||||
(): Codec<PinChallengeInstructionMessage> =>
|
(): Codec<PinChallengeInstructionMessage> =>
|
||||||
buildCodecForObject<PinChallengeInstructionMessage>()
|
buildCodecForObject<PinChallengeInstructionMessage>()
|
||||||
.property("method", codecForConstString("TAN_SENT"))
|
.property("challenge_type", codecForConstString("TAN_SENT"))
|
||||||
.property("tan_address_hint", codecForString())
|
.property("tan_address_hint", codecForString())
|
||||||
.build("PinChallengeInstructionMessage");
|
.build("PinChallengeInstructionMessage");
|
||||||
|
|
||||||
export const codecForIbanChallengeInstructionMessage =
|
export const codecForIbanChallengeInstructionMessage =
|
||||||
(): Codec<IbanChallengeInstructionMessage> =>
|
(): Codec<IbanChallengeInstructionMessage> =>
|
||||||
buildCodecForObject<IbanChallengeInstructionMessage>()
|
buildCodecForObject<IbanChallengeInstructionMessage>()
|
||||||
.property("method", codecForConstString("IBAN_WIRE"))
|
.property("challenge_type", codecForConstString("IBAN_WIRE"))
|
||||||
.property("amount", codecForAmountString())
|
.property("wire_details", codecForAny())
|
||||||
.property("business_name", codecForString())
|
|
||||||
.property("credit_iban", codecForString())
|
|
||||||
.property("wire_transfer_subject", codecForString())
|
|
||||||
.property("answer_code", codecForNumber())
|
|
||||||
.property("debit_account_hint", codecForString())
|
|
||||||
.build("IbanChallengeInstructionMessage");
|
.build("IbanChallengeInstructionMessage");
|
||||||
|
|
||||||
export const codecForChallengeInstructionMessage =
|
export const codecForChallengeInstructionMessage =
|
||||||
(): Codec<ChallengeInstructionMessage> =>
|
(): Codec<ChallengeInstructionMessage> =>
|
||||||
buildCodecForUnion<ChallengeInstructionMessage>()
|
buildCodecForUnion<ChallengeInstructionMessage>()
|
||||||
.discriminateOn("method")
|
.discriminateOn("challenge_type")
|
||||||
.alternative("FILE_WRITTEN", codecForFileChallengeInstructionMessage())
|
.alternative("FILE_WRITTEN", codecForFileChallengeInstructionMessage())
|
||||||
.alternative("IBAN_WIRE", codecForIbanChallengeInstructionMessage())
|
.alternative("IBAN_WIRE", codecForIbanChallengeInstructionMessage())
|
||||||
.alternative("TAN_SENT", codecForPinChallengeInstructionMessage())
|
.alternative("TAN_SENT", codecForPinChallengeInstructionMessage())
|
||||||
|
@ -221,7 +221,7 @@ export interface ReducerStateRecovery {
|
|||||||
/**
|
/**
|
||||||
* Explicitly selected version by the user.
|
* Explicitly selected version by the user.
|
||||||
*/
|
*/
|
||||||
selected_version?: AggregatedPolicyMetaInfo;
|
selected_version?: SelectedVersionInfo;
|
||||||
|
|
||||||
challenge_feedback?: { [uuid: string]: ChallengeFeedback };
|
challenge_feedback?: { [uuid: string]: ChallengeFeedback };
|
||||||
|
|
||||||
@ -464,10 +464,16 @@ export interface ActionArgsUpdateExpiration {
|
|||||||
expiration: TalerProtocolTimestamp;
|
expiration: TalerProtocolTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ActionArgsChangeVersion {
|
export interface SelectedVersionInfo {
|
||||||
selection: AggregatedPolicyMetaInfo;
|
attribute_mask: number;
|
||||||
|
providers: {
|
||||||
|
url: string;
|
||||||
|
version: number;
|
||||||
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ActionArgsChangeVersion = SelectedVersionInfo;
|
||||||
|
|
||||||
export interface ActionArgsUpdatePolicy {
|
export interface ActionArgsUpdatePolicy {
|
||||||
policy_index: number;
|
policy_index: number;
|
||||||
policy: PolicyMember[];
|
policy: PolicyMember[];
|
||||||
@ -518,10 +524,8 @@ export interface DiscoveryResult {
|
|||||||
cursor?: DiscoveryCursor;
|
cursor?: DiscoveryCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const codecForActionArgsChangeVersion = () =>
|
// FIXME: specify schema!
|
||||||
buildCodecForObject<ActionArgsChangeVersion>()
|
export const codecForActionArgsChangeVersion = codecForAny;
|
||||||
.property("selection", codecForAny())
|
|
||||||
.build("ActionArgsChangeVersion");
|
|
||||||
|
|
||||||
export const codecForPolicyMember = () =>
|
export const codecForPolicyMember = () =>
|
||||||
buildCodecForObject<PolicyMember>()
|
buildCodecForObject<PolicyMember>()
|
||||||
|
@ -250,7 +250,7 @@ export const OnePolicyWithAllTheChallengesInDifferentState = createExample(
|
|||||||
challenge_feedback: {
|
challenge_feedback: {
|
||||||
"uuid-1": { state: ChallengeFeedbackStatus.Solved.toString() },
|
"uuid-1": { state: ChallengeFeedbackStatus.Solved.toString() },
|
||||||
"uuid-3": {
|
"uuid-3": {
|
||||||
state: ChallengeFeedbackStatus.AuthIban.toString(),
|
state: ChallengeFeedbackStatus.IbanInstructions.toString(),
|
||||||
challenge_amount: "EUR:1",
|
challenge_amount: "EUR:1",
|
||||||
target_iban: "DE12345789000",
|
target_iban: "DE12345789000",
|
||||||
target_business_name: "Data Loss Incorporated",
|
target_business_name: "Data Loss Incorporated",
|
||||||
|
@ -16,7 +16,7 @@ function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {
|
|||||||
switch (feedback.state) {
|
switch (feedback.state) {
|
||||||
case ChallengeFeedbackStatus.Solved:
|
case ChallengeFeedbackStatus.Solved:
|
||||||
return <div />;
|
return <div />;
|
||||||
case ChallengeFeedbackStatus.AuthIban:
|
case ChallengeFeedbackStatus.IbanInstructions:
|
||||||
return null;
|
return null;
|
||||||
case ChallengeFeedbackStatus.ServerFailure:
|
case ChallengeFeedbackStatus.ServerFailure:
|
||||||
return <div class="block has-text-danger">Server error.</div>;
|
return <div class="block has-text-danger">Server error.</div>;
|
||||||
@ -173,7 +173,7 @@ export function ChallengeOverviewScreen(): VNode {
|
|||||||
case ChallengeFeedbackStatus.TruthUnknown:
|
case ChallengeFeedbackStatus.TruthUnknown:
|
||||||
case ChallengeFeedbackStatus.RateLimitExceeded:
|
case ChallengeFeedbackStatus.RateLimitExceeded:
|
||||||
return <div />;
|
return <div />;
|
||||||
case ChallengeFeedbackStatus.AuthIban:
|
case ChallengeFeedbackStatus.IbanInstructions:
|
||||||
case ChallengeFeedbackStatus.TalerPayment:
|
case ChallengeFeedbackStatus.TalerPayment:
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -32,7 +32,7 @@ export function SolveOverviewFeedbackDisplay(props: {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case ChallengeFeedbackStatus.AuthIban:
|
case ChallengeFeedbackStatus.IbanInstructions:
|
||||||
return (
|
return (
|
||||||
<Notifications
|
<Notifications
|
||||||
notifications={[
|
notifications={[
|
||||||
|
@ -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 {
|
import {
|
||||||
ChallengeFeedbackStatus,
|
|
||||||
ChallengeInfo,
|
ChallengeInfo,
|
||||||
} from "@gnu-taler/anastasis-core";
|
} from "@gnu-taler/anastasis-core";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
|
@ -158,7 +158,7 @@ export const TruthUnknownFeedback = createExample(TestedComponent[type].solve, {
|
|||||||
} as ReducerState);
|
} as ReducerState);
|
||||||
|
|
||||||
const ibanFeedback: ChallengeFeedbackBankTransferRequired = {
|
const ibanFeedback: ChallengeFeedbackBankTransferRequired = {
|
||||||
state: ChallengeFeedbackStatus.AuthIban,
|
state: ChallengeFeedbackStatus.IbanInstructions,
|
||||||
challenge_amount: "EUR:1",
|
challenge_amount: "EUR:1",
|
||||||
target_iban: "DE12345789000",
|
target_iban: "DE12345789000",
|
||||||
target_business_name: "Data Loss Incorporated",
|
target_business_name: "Data Loss Incorporated",
|
||||||
|
Loading…
Reference in New Issue
Block a user