taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit d6c8cc274c5350c86dbd0440b5531c171188e75e
parent be9995c91c24cf8da3e4f1818b9bb5bd49b6d7cc
Author: Sebastian <sebasjm@gmail.com>
Date:   Wed, 30 Oct 2024 15:24:57 -0300

add support for bank token auth

Diffstat:
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx | 21+++++++++++++++------
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx | 33++++++++++++++++++++++++++++-----
Mpackages/taler-util/src/http-client/bank-revenue.ts | 32+++++++++++++++++---------------
Mpackages/taler-util/src/http-client/utils.ts | 26++++++++++++++++++++++++++
Mpackages/taler-util/src/index.ts | 2+-
Mpackages/taler-util/src/types-taler-merchant.ts | 10+++++++++-
6 files changed, 96 insertions(+), 28 deletions(-)

diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/index.tsx @@ -20,6 +20,7 @@ */ import { + AccessToken, FacadeCredentials, HttpStatusCode, OperationFail, @@ -28,7 +29,7 @@ import { TalerError, TalerMerchantApi, TalerRevenueHttpClient, - opFixedSuccess + opFixedSuccess, } from "@gnu-taler/taler-util"; import { BrowserFetchHttpLib, @@ -40,6 +41,7 @@ import { NotificationCard } from "../../../../components/menu/index.js"; import { useSessionContext } from "../../../../context/session.js"; import { Notification } from "../../../../utils/types.js"; import { CreatePage } from "./CreatePage.js"; +import { BasicOrTokenAuth } from "@gnu-taler/taler-util"; export type Entity = TalerMerchantApi.AccountAddDetails; interface Props { @@ -76,7 +78,8 @@ export default function CreateValidator({ onConfirm, onBack }: Props): VNode { setNotif({ message: i18n.str`Could not create account`, type: "ERROR", - description: error instanceof Error ? error.message : String(error), + description: + error instanceof Error ? error.message : String(error), }); }); }} @@ -105,17 +108,23 @@ export async function testRevenueAPI( revenueAPI.href, new BrowserFetchHttpLib(), ); - const auth = + const auth: BasicOrTokenAuth | undefined = creds === undefined ? undefined : creds.type === "none" ? undefined : creds.type === "basic" ? { + type: "basic", username: creds.username, password: creds.password, } - : undefined; + : creds.type === "bearer" + ? { + type: "bearer", + token: creds.token as AccessToken, + } + : undefined; try { const config = await api.getConfig(auth); @@ -131,10 +140,10 @@ export async function testRevenueAPI( if (!resp.body.credit_account) { return { - type:"fail", + type: "fail", case: TestRevenueErrorType.CANT_VALIDATE, detail: undefined, - } + }; } return opFixedSuccess(resp.body.credit_account as PaytoString); } catch (err) { diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx @@ -54,7 +54,7 @@ type FormType = TalerMerchantApi.AccountPatchDetails & { verified: boolean; payto_uri?: PaytoString; }; -const accountAuthType = ["unedit", "none", "basic"]; +const accountAuthType = ["unedit", "none", "basic", "bearer"]; interface Props { onUpdate: (d: TalerMerchantApi.AccountPatchDetails) => Promise<void>; onReplace: ( @@ -125,6 +125,13 @@ export function UpdatePage({ ? i18n.str`Required` : undefined, + token: + state.credit_facade_credentials?.type !== "bearer" + ? undefined + : !state.credit_facade_credentials.token + ? i18n.str`Required` + : undefined, + password: state.credit_facade_credentials?.type !== "basic" ? undefined @@ -157,9 +164,14 @@ export function UpdatePage({ password: state.credit_facade_credentials.password, username: state.credit_facade_credentials.username, } - : { - type: "none", - }; + : state.credit_facade_credentials.type === "bearer" + ? { + type: "bearer", + token: state.credit_facade_credentials.token, + } + : { + type: "none", + }; if (replacingAccountId) { return onReplace(account, { @@ -300,7 +312,8 @@ export function UpdatePage({ values={accountAuthType} toStr={(str) => { if (str === "none") return i18n.str`Without authentication`; - if (str === "basic") return i18n.str`With authentication`; + if (str === "basic") return i18n.str`With password`; + if (str === "bearer") return i18n.str`With token`; return i18n.str`Do not change`; }} /> @@ -319,6 +332,16 @@ export function UpdatePage({ /> </Fragment> ) : undefined} + {state.credit_facade_credentials?.type === "bearer" ? ( + <Fragment> + <Input + name="credit_facade_credentials.token" + label={i18n.str`Token`} + inputType="password" + tooltip={i18n.str`Access token to access the account information.`} + /> + </Fragment> + ) : undefined} <InputToggle<FormType> label={i18n.str`Match`} tooltip={i18n.str`Check where the information match against the server info.`} diff --git a/packages/taler-util/src/http-client/bank-revenue.ts b/packages/taler-util/src/http-client/bank-revenue.ts @@ -30,12 +30,21 @@ import { opSuccessFromHttp, opUnknownFailure, } from "../operation.js"; -import { LongPollParams, PaginationParams } from "../types-taler-common.js"; +import { + AccessToken, + LongPollParams, + PaginationParams, +} from "../types-taler-common.js"; import { codecForRevenueConfig, codecForRevenueIncomingHistory, } from "../types-taler-revenue.js"; -import { addLongPollingParam, addPaginationParams } from "./utils.js"; +import { + addLongPollingParam, + addPaginationParams, + BasicOrTokenAuth, + createAuthorizationHeader, +} from "./utils.js"; export type TalerBankRevenueResultByMethod< prop extends keyof TalerRevenueHttpClient, @@ -44,10 +53,7 @@ export type TalerBankRevenueErrorsByMethod< prop extends keyof TalerRevenueHttpClient, > = FailCasesByMethod<TalerRevenueHttpClient, prop>; -type UsernameAndPassword = { - username: string; - password: string; -}; + /** * The API is used by the merchant (or other parties) to query * for incoming transactions to their account. @@ -62,7 +68,7 @@ export class TalerRevenueHttpClient { this.httpLib = httpClient ?? createPlatformHttpLib(); } - public readonly PROTOCOL_VERSION = "0:0:0"; + public readonly PROTOCOL_VERSION = "1:0:0"; isCompatible(version: string): boolean { const compare = LibtoolVersion.compare(this.PROTOCOL_VERSION, version); @@ -73,14 +79,12 @@ export class TalerRevenueHttpClient { * https://docs.taler.net/core/api-bank-revenue.html#get--config * */ - async getConfig(auth?: UsernameAndPassword) { + async getConfig(auth?: BasicOrTokenAuth) { const url = new URL(`config`, this.baseUrl); const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { - Authorization: auth - ? makeBasicAuthHeader(auth.username, auth.password) - : undefined, + Authorization: createAuthorizationHeader(auth), }, }); switch (resp.status) { @@ -100,7 +104,7 @@ export class TalerRevenueHttpClient { * @returns */ async getHistory( - auth?: UsernameAndPassword, + auth?: BasicOrTokenAuth, params?: PaginationParams & LongPollParams, ) { const url = new URL(`history`, this.baseUrl); @@ -109,9 +113,7 @@ export class TalerRevenueHttpClient { const resp = await this.httpLib.fetch(url.href, { method: "GET", headers: { - Authorization: auth - ? makeBasicAuthHeader(auth.username, auth.password) - : undefined, + Authorization: createAuthorizationHeader(auth), }, }); switch (resp.status) { diff --git a/packages/taler-util/src/http-client/utils.ts b/packages/taler-util/src/http-client/utils.ts @@ -46,6 +46,32 @@ export function makeBearerTokenAuthHeader(token: AccessToken): string { return `Bearer ${token}`; } +export type BasicOrTokenAuth = BasicAuth | TokenAuth; + +export type BasicAuth = { + type: "basic"; + username: string; + password: string; +}; + +export type TokenAuth = { + type: "bearer"; + token: AccessToken; +}; + +export function createAuthorizationHeader(auth?: BasicOrTokenAuth): string | undefined { + if (!auth) return undefined; + switch (auth.type) { + case "basic": { + return makeBasicAuthHeader(auth.username, auth.password); + } + case "bearer": { + return makeBearerTokenAuthHeader(auth.token); + } + } + return undefined; +} + /** * https://bugs.gnunet.org/view.php?id=7949 */ diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts @@ -22,7 +22,7 @@ export * from "./http-client/challenger.js"; export * from "./http-client/exchange.js"; export * from "./http-client/merchant.js"; export * from "./http-client/officer-account.js"; -export { CacheEvictor } from "./http-client/utils.js"; +export { CacheEvictor, BasicOrTokenAuth, BasicAuth, TokenAuth } from "./http-client/utils.js"; export * from "./http-status-codes.js"; export * from "./i18n.js"; export * from "./iban.js"; diff --git a/packages/taler-util/src/types-taler-merchant.ts b/packages/taler-util/src/types-taler-merchant.ts @@ -1414,7 +1414,8 @@ export interface AccountAddDetails { export type FacadeCredentials = | NoFacadeCredentials - | BasicAuthFacadeCredentials; + | BasicAuthFacadeCredentials + | BearerAuthFacadeCredentials; export interface NoFacadeCredentials { type: "none"; @@ -1430,6 +1431,13 @@ export interface BasicAuthFacadeCredentials { password: string; } +export interface BearerAuthFacadeCredentials { + type: "bearer"; + + // token to use to authenticate + token: string; +} + export interface AccountAddResponse { // Hash over the wire details (including over the salt). h_wire: HashCode;