gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: towards new 2fa


From: gnunet
Subject: [taler-wallet-core] branch master updated: towards new 2fa
Date: Fri, 05 Jan 2024 16:30:00 +0100

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 1b9db448d towards new 2fa
1b9db448d is described below

commit 1b9db448dc3dd4893c484c63cf459d7d9250e693
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Jan 5 12:29:53 2024 -0300

    towards new 2fa
---
 .../src/pages/account/ShowAccountDetails.tsx       |   4 +-
 .../src/pages/business/CreateCashout.tsx           |  10 +-
 packages/taler-util/src/http-client/bank-core.ts   |  66 ++++++++--
 packages/taler-util/src/http-client/types.ts       | 140 +++++++++++++++------
 4 files changed, 163 insertions(+), 57 deletions(-)

diff --git a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx 
b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
index 1f2d67c49..4b66c0d8d 100644
--- a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
@@ -89,9 +89,9 @@ export function ShowAccountDetails({
             description: resp.detail.hint as TranslatedString,
             debug: resp.detail,
           })
-          case "user-cant-change-contact": return notify({
+          case "missing-contact-data": return notify({
             type: "error",
-            title: i18n.str`You can't change the contact info, please contact 
the your account administrator.`,
+            title: i18n.str`You need contact data to enable 2FA.`,
             description: resp.detail.hint as TranslatedString,
             debug: resp.detail,
           })
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx 
b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
index 8987accd1..92c80ea38 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
@@ -212,12 +212,6 @@ export function CreateCashout({
             description: resp.detail.hint as TranslatedString,
             debug: resp.detail,
           });
-          case "no-contact-info": return notify({
-            type: "error",
-            title: i18n.str`Missing contact info before to create the cashout`,
-            description: resp.detail.hint as TranslatedString,
-            debug: resp.detail,
-          });
           case "no-enough-balance": return notify({
             type: "error",
             title: i18n.str`The account does not have sufficient funds`,
@@ -230,9 +224,9 @@ export function CreateCashout({
             description: resp.detail.hint as TranslatedString,
             debug: resp.detail,
           });
-          case "tan-failed": return notify({
+          case "no-cashout-uri": return notify({
             type: "error",
-            title: i18n.str`Sending the confirmation code failed.`,
+            title: i18n.str`Missing cashout URI in the profile`,
             description: resp.detail.hint as TranslatedString,
             debug: resp.detail,
           });
diff --git a/packages/taler-util/src/http-client/bank-core.ts 
b/packages/taler-util/src/http-client/bank-core.ts
index 51d6d7c96..b7e0292bd 100644
--- a/packages/taler-util/src/http-client/bank-core.ts
+++ b/packages/taler-util/src/http-client/bank-core.ts
@@ -18,7 +18,9 @@ import {
   HttpStatusCode,
   LibtoolVersion,
   TalerErrorCode,
-  codecForTalerErrorDetail
+  codecForChallenge,
+  codecForTalerErrorDetail,
+  codecForTanTransmission
 } from "@gnu-taler/taler-util";
 import {
   HttpRequestLibrary,
@@ -123,6 +125,7 @@ export class TalerCoreBankHttpClient {
       },
     });
     switch (resp.status) {
+      case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
       case HttpStatusCode.NoContent: return opEmptySuccess()
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
       case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", 
resp);
@@ -153,6 +156,7 @@ export class TalerCoreBankHttpClient {
       },
     });
     switch (resp.status) {
+      case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
       case HttpStatusCode.NoContent: return opEmptySuccess()
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
       case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", 
resp);
@@ -163,7 +167,7 @@ export class TalerCoreBankHttpClient {
           case TalerErrorCode.BANK_NON_ADMIN_PATCH_LEGAL_NAME: return 
opKnownFailure("user-cant-change-name", resp);
           case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return 
opKnownFailure("user-cant-change-debt", resp);
           case TalerErrorCode.BANK_NON_ADMIN_PATCH_CASHOUT: return 
opKnownFailure("user-cant-change-cashout", resp);
-          case TalerErrorCode.BANK_NON_ADMIN_PATCH_CONTACT: return 
opKnownFailure("user-cant-change-contact", resp);
+          case TalerErrorCode.BANK_MISSING_TAN_INFO: return 
opKnownFailure("missing-contact-data", resp);
           default: return opUnknownFailure(resp, body)
         }
       }
@@ -185,6 +189,7 @@ export class TalerCoreBankHttpClient {
       },
     });
     switch (resp.status) {
+      case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
       case HttpStatusCode.NoContent: return opEmptySuccess()
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
       case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", 
resp);
@@ -326,6 +331,7 @@ export class TalerCoreBankHttpClient {
       body,
     });
     switch (resp.status) {
+      case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
       case HttpStatusCode.Ok: return opSuccess(resp, 
codecForCreateTransactionResponse())
       case HttpStatusCode.BadRequest: return opKnownFailure("invalid-input", 
resp);
       case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", 
resp);
@@ -405,6 +411,7 @@ export class TalerCoreBankHttpClient {
       },
     });
     switch (resp.status) {
+      case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
       case HttpStatusCode.NoContent: return opEmptySuccess()
       //FIXME: missing in docs
       case HttpStatusCode.BadRequest: return opKnownFailure("invalid-id", resp)
@@ -466,6 +473,7 @@ export class TalerCoreBankHttpClient {
       body,
     });
     switch (resp.status) {
+      case HttpStatusCode.Accepted: return opSuccess(resp, codecForChallenge())
       case HttpStatusCode.Ok: return opSuccess(resp, codecForCashoutPending())
       case HttpStatusCode.NotFound: return opKnownFailure("account-not-found", 
resp)
       case HttpStatusCode.Conflict: {
@@ -474,20 +482,19 @@ export class TalerCoreBankHttpClient {
         switch (details.code) {
           case TalerErrorCode.BANK_TRANSFER_REQUEST_UID_REUSED: return 
opKnownFailure("request-already-used", resp);
           case TalerErrorCode.BANK_BAD_CONVERSION: return 
opKnownFailure("incorrect-exchange-rate", resp);
-          case TalerErrorCode.BANK_MISSING_TAN_INFO: return 
opKnownFailure("no-contact-info", resp);
           case TalerErrorCode.BANK_UNALLOWED_DEBIT: return 
opKnownFailure("no-enough-balance", resp);
+          case TalerErrorCode.BANK_CONFIRM_INCOMPLETE: return 
opKnownFailure("no-cashout-uri", resp);
           default: return opUnknownFailure(resp, body)
         }
       }
       case HttpStatusCode.NotImplemented: return 
opKnownFailure("cashout-not-supported", resp);
-      case HttpStatusCode.BadGateway: return opKnownFailure("tan-failed", 
resp);
       default: return opUnknownFailure(resp, await resp.text())
     }
   }
 
   /**
    * 
https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-abort
-   * 
+   * @deprecated since 4
    */
   async abortCashoutById(auth: UserAndToken, cid: number) {
     const url = new URL(`accounts/${auth.username}/cashouts/${cid}/abort`, 
this.baseUrl);
@@ -508,7 +515,7 @@ export class TalerCoreBankHttpClient {
 
   /**
    * 
https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-cashouts-$CASHOUT_ID-confirm
-   * 
+   * @deprecated since 4
    */
   async confirmCashoutById(auth: UserAndToken, cid: number, body: 
TalerCorebankApi.CashoutConfirmRequest) {
     const url = new URL(`accounts/${auth.username}/cashouts/${cid}/confirm`, 
this.baseUrl);
@@ -522,7 +529,6 @@ export class TalerCoreBankHttpClient {
     switch (resp.status) {
       case HttpStatusCode.NoContent: return opEmptySuccess()
       case HttpStatusCode.NotFound: return opKnownFailure("not-found", resp);
-      // case HttpStatusCode.Forbidden: return 
opKnownFailure("wrong-tan-or-credential", resp);
       case HttpStatusCode.Conflict: {
         const body = await resp.json()
         const details = codecForTalerErrorDetail().decode(body)
@@ -637,6 +643,52 @@ export class TalerCoreBankHttpClient {
     }
   }
 
+  //
+  // 2FA
+  //
+  async sendChallenge(auth: UserAndToken, cid: string) {
+    const url = new URL(`accounts/${auth.username}/challenge/${cid}`, 
this.baseUrl);
+    const resp = await this.httpLib.fetch(url.href, {
+      method: "POST",
+      headers: {
+        Authorization: makeBearerTokenAuthHeader(auth.token)
+      },
+    });
+    switch (resp.status) {
+      case HttpStatusCode.Ok: return opSuccess(resp, codecForTanTransmission())
+      case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", 
resp);
+      case HttpStatusCode.NotFound: return opKnownFailure("invalid-challenge", 
resp);
+      case HttpStatusCode.BadGateway: {
+        const body = await resp.json()
+        const details = codecForTalerErrorDetail().decode(body)
+        switch (details.code) {
+          case TalerErrorCode.BANK_TAN_CHANNEL_SCRIPT_FAILED: return 
opKnownFailure("tan-failed", resp);
+          default: return opUnknownFailure(resp, body)
+        }
+      }
+      default: return opUnknownFailure(resp, await resp.text())
+    }
+  }
+
+  async confirmChallenge(auth: UserAndToken, cid: string) {
+    const url = new URL(`accounts/${auth.username}/challenge/${cid}/confirm`, 
this.baseUrl);
+    const resp = await this.httpLib.fetch(url.href, {
+      method: "POST",
+      headers: {
+        Authorization: makeBearerTokenAuthHeader(auth.token)
+      },
+    });
+    switch (resp.status) {
+      case HttpStatusCode.Ok: return opEmptySuccess()
+      case HttpStatusCode.Unauthorized: return opKnownFailure("unauthorized", 
resp);
+      case HttpStatusCode.NotFound: return opKnownFailure("invalid-challenge", 
resp);
+      case HttpStatusCode.Conflict: return opKnownFailure("wrong-code", resp);
+      case HttpStatusCode.TooManyRequests: return 
opKnownFailure("too-many-errors", resp);
+      default: return opUnknownFailure(resp, await resp.text())
+    }
+  }
+
+
   //
   // Others API
   //
diff --git a/packages/taler-util/src/http-client/types.ts 
b/packages/taler-util/src/http-client/types.ts
index b0d4deca1..f43a0a3a1 100644
--- a/packages/taler-util/src/http-client/types.ts
+++ b/packages/taler-util/src/http-client/types.ts
@@ -1,3 +1,4 @@
+import { deprecate } from "util";
 import { codecForAmountString } from "../amounts.js";
 import {
   Codec,
@@ -280,8 +281,8 @@ export const codecForCoreBankConfig = (): 
Codec<TalerCorebankApi.Config> =>
     .property("currency_specification", codecForCurrencySpecificiation())
     .property("currency", codecForString())
     .property("supported_tan_channels", codecForList(codecForEither(
-      codecForConstString(TanChannel.SMS),
-      codecForConstString(TanChannel.EMAIL),
+      codecForConstString(TalerCorebankApi.TanChannel.SMS),
+      codecForConstString(TalerCorebankApi.TanChannel.EMAIL),
     )))
     .build("TalerCorebankApi.Config");
 
@@ -434,8 +435,8 @@ export const codecForBankAccountCreateWithdrawalResponse =
       .build("TalerCorebankApi.BankAccountCreateWithdrawalResponse");
 
 export const codecForCashoutPending =
-  (): Codec<TalerCorebankApi.CashoutPending> =>
-    buildCodecForObject<TalerCorebankApi.CashoutPending>()
+  (): Codec<TalerCorebankApi.CashoutResponse> =>
+    buildCodecForObject<TalerCorebankApi.CashoutResponse>()
       .property("cashout_id", codecForNumber())
       .build("TalerCorebankApi.CashoutPending");
 
@@ -463,11 +464,12 @@ export const codecForCashoutInfo = (): 
Codec<TalerCorebankApi.CashoutInfo> =>
     .property("cashout_id", codecForNumber())
     .property(
       "status",
-      codecForEither(
-        codecForConstString("pending"),
-        codecForConstString("aborted"),
-        codecForConstString("confirmed"),
-      ),
+      codecOptional(
+        codecForEither(
+          codecForConstString("pending"),
+          codecForConstString("aborted"),
+          codecForConstString("confirmed"),
+        )),
     )
     .build("TalerCorebankApi.CashoutInfo");
 
@@ -484,11 +486,12 @@ export const codecForGlobalCashoutInfo =
       .property("username", codecForString())
       .property(
         "status",
-        codecForEither(
-          codecForConstString("pending"),
-          codecForConstString("aborted"),
-          codecForConstString("confirmed"),
-        ),
+        codecOptional(
+          codecForEither(
+            codecForConstString("pending"),
+            codecForConstString("aborted"),
+            codecForConstString("confirmed"),
+          )),
       )
       .build("TalerCorebankApi.GlobalCashoutInfo");
 
@@ -497,26 +500,25 @@ export const codecForCashoutStatusResponse =
     buildCodecForObject<TalerCorebankApi.CashoutStatusResponse>()
       .property("amount_credit", codecForAmountString())
       .property("amount_debit", codecForAmountString())
-      .property("confirmation_time", codecOptional(codecForTimestamp))
       .property("creation_time", codecForTimestamp)
-      // .property("credit_payto_uri", codecForPaytoString())
+      .property(
+        "tan_channel",
+        codecOptional(codecForEither(
+          codecForConstString(TalerCorebankApi.TanChannel.SMS),
+          codecForConstString(TalerCorebankApi.TanChannel.EMAIL),
+        )),
+      )
+      .property("subject", codecForString())
+      .property("confirmation_time", codecOptional(codecForTimestamp))
       .property(
         "status",
-        codecForEither(
+        codecOptional(codecForEither(
           codecForConstString("pending"),
           codecForConstString("aborted"),
           codecForConstString("confirmed"),
-        ),
+        )),
       )
-      .property(
-        "tan_channel",
-        codecForEither(
-          codecForConstString(TanChannel.SMS),
-          codecForConstString(TanChannel.EMAIL),
-        ),
-      )
-      .property("subject", codecForString())
-      .property("tan_info", codecForString())
+      .property("tan_info", codecOptional(codecForString()))
       .build("TalerCorebankApi.CashoutStatusResponse");
 
 export const codecForConversionRatesResponse =
@@ -735,6 +737,22 @@ export const codecForAmlDecisionDetail =
       .property("decider_pub", codecForString())
       .build("TalerExchangeApi.AmlDecisionDetail");
 
+export const codecForChallenge =
+  (): Codec<TalerCorebankApi.Challenge> =>
+    buildCodecForObject<TalerCorebankApi.Challenge>()
+      .property("challenge_id", codecForString())
+      .build("TalerCorebankApi.Challenge");
+
+export const codecForTanTransmission =
+  (): Codec<TalerCorebankApi.TanTransmission> =>
+    buildCodecForObject<TalerCorebankApi.TanTransmission>()
+      .property("tan_channel", codecForEither(
+        codecForConstString(TalerCorebankApi.TanChannel.SMS),
+        codecForConstString(TalerCorebankApi.TanChannel.EMAIL),
+      ))
+      .property("tan_info", codecForString())
+      .build("TalerCorebankApi.TanTransmission");
+
 interface KycDetail {
   provider_section: string;
   attributes?: Object;
@@ -894,10 +912,6 @@ const codecForLibtoolVersion = codecForString;
 const codecForCurrencyName = codecForString;
 const codecForDecimalNumber = codecForString;
 
-enum TanChannel {
-  SMS = "sms",
-  EMAIL = "email",
-}
 export type WithdrawalOperationStatus =
   | "pending"
   | "selected"
@@ -1442,10 +1456,6 @@ export namespace TalerCorebankApi {
     is_taler_exchange?: boolean;
 
     // Addresses where to send the TAN for transactions.
-    // Currently only used for cashouts.
-    // If missing, cashouts will fail.
-    // In the future, might be used for other transactions
-    // as well.
     contact_data?: ChallengeContactData;
 
     // 'payto' address of a fiat bank account.
@@ -1497,6 +1507,10 @@ export namespace TalerCorebankApi {
     // If present, change the max debit allowed for this user
     // Only admin can change this property.
     debit_threshold?: AmountString;
+
+    // If present, enables 2FA and set the TAN channel used for challenges
+    tan_channel?: TanChannel;
+
   }
 
   export interface AccountPasswordChange {
@@ -1579,6 +1593,9 @@ export namespace TalerCorebankApi {
 
     // Is this a taler exchange account?
     is_taler_exchange: boolean;
+
+    // Is 2FA enabled and what channel is used for challenges?
+    tan_channel?: TanChannel;
   }
 
   export interface CashoutRequest {
@@ -1613,15 +1630,20 @@ export namespace TalerCorebankApi {
     // this field is missing, it defaults to SMS.
     // The default choice prefers to change the communication
     // channel respect to the one used to issue this request.
+    /**
+     * @deprecated since 4, use 2fa
+     */
     tan_channel?: TanChannel;
   }
 
-  export interface CashoutPending {
+  export interface CashoutResponse {
     // ID identifying the operation being created
-    // and now waiting for the TAN confirmation.
     cashout_id: number;
   }
 
+  /**
+   * @deprecated since 4, use 2fa
+   */
   export interface CashoutConfirmRequest {
     // the TAN that confirms $CASHOUT_ID.
     tan: string;
@@ -1634,7 +1656,10 @@ export namespace TalerCorebankApi {
 
   export interface CashoutInfo {
     cashout_id: number;
-    status: "pending" | "aborted" | "confirmed";
+    /**
+     * @deprecated since 4, use new 2fa
+     */
+    status?: "pending" | "aborted" | "confirmed";
   }
   export interface GlobalCashouts {
     // Every string represents a cash-out operation ID.
@@ -1643,11 +1668,13 @@ export namespace TalerCorebankApi {
   export interface GlobalCashoutInfo {
     cashout_id: number;
     username: string;
-    status: "pending" | "aborted" | "confirmed";
+    /**
+     * @deprecated since 4, use new 2fa
+     */
+    status?: "pending" | "aborted" | "confirmed";
   }
 
   export interface CashoutStatusResponse {
-    status: "pending" | "aborted" | "confirmed";
 
     // Amount debited to the internal
     // regional currency bank account.
@@ -1666,16 +1693,30 @@ export namespace TalerCorebankApi {
     // Time when the cashout was created.
     creation_time: Timestamp;
 
+    /**
+     * @deprecated since 4, use new 2fa
+     */
+    status?: "pending" | "aborted" | "confirmed";
+
     // Time when the cashout was confirmed via its TAN.
     // Missing when the operation wasn't confirmed yet.
+    /**
+     * @deprecated since 4, use new 2fa
+     */
     confirmation_time?: Timestamp;
 
     // Channel of the last successful transmission of the TAN challenge.
     // Missing when all transmissions failed.
+    /**
+     * @deprecated since 4, use new 2fa
+     */
     tan_channel?: TanChannel;
 
     // Info of the last successful transmission of the TAN challenge.
     // Missing when all transmissions failed.
+    /**
+     * @deprecated since 4, use new 2fa
+     */
     tan_info?: string;
   }
 
@@ -1767,6 +1808,25 @@ export namespace TalerCorebankApi {
     // exchange to another bank account.
     talerOutVolume: AmountString;
   }
+  export interface TanTransmission {
+    // Channel of the last successful transmission of the TAN challenge.
+    tan_channel: TanChannel;
+
+    // Info of the last successful transmission of the TAN challenge.
+    tan_info: string;
+  }
+
+  export interface Challenge {
+    // Unique identifier of the challenge to solve to run this protected
+    // operation.
+    challenge_id: string;
+  }
+
+  export enum TanChannel {
+    SMS = "sms",
+    EMAIL = "email"
+  }
+
 }
 
 export namespace TalerExchangeApi {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]