fints-lib 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -8
- package/dist/decoupled-tan/decoupled-tan-manager.d.ts +82 -0
- package/dist/decoupled-tan/decoupled-tan-manager.js +307 -0
- package/dist/decoupled-tan/decoupled-tan-manager.js.map +1 -0
- package/dist/decoupled-tan/index.d.ts +5 -0
- package/dist/decoupled-tan/index.js +22 -0
- package/dist/decoupled-tan/index.js.map +1 -0
- package/dist/decoupled-tan/types.d.ts +86 -0
- package/dist/decoupled-tan/types.js +42 -0
- package/dist/decoupled-tan/types.js.map +1 -0
- package/dist/dialog.d.ts +49 -1
- package/dist/dialog.js +75 -2
- package/dist/dialog.js.map +1 -1
- package/dist/errors/decoupled-tan-error.d.ts +49 -0
- package/dist/errors/decoupled-tan-error.js +73 -0
- package/dist/errors/decoupled-tan-error.js.map +1 -0
- package/dist/errors/tan-required-error.d.ts +9 -0
- package/dist/errors/tan-required-error.js +6 -0
- package/dist/errors/tan-required-error.js.map +1 -1
- package/dist/http-connection.js +2 -1
- package/dist/http-connection.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mt940-86-structured.js +9 -0
- package/dist/mt940-86-structured.js.map +1 -1
- package/dist/pin-tan-client.d.ts +43 -0
- package/dist/pin-tan-client.js +56 -2
- package/dist/pin-tan-client.js.map +1 -1
- package/dist/segments/hnsha.d.ts +5 -0
- package/dist/segments/hnsha.js +20 -0
- package/dist/segments/hnsha.js.map +1 -1
- package/package.json +6 -6
package/dist/pin-tan-client.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import { Dialog, DialogConfig } from "./dialog";
|
|
|
3
3
|
import { Request } from "./request";
|
|
4
4
|
import { ConnectionConfig } from "./http-connection";
|
|
5
5
|
import { Segment } from "./segments";
|
|
6
|
+
import { DecoupledTanConfig, DecoupledTanStatusCallback } from "./decoupled-tan";
|
|
7
|
+
import { TanRequiredError } from "./errors/tan-required-error";
|
|
8
|
+
import { Response } from "./response";
|
|
6
9
|
/**
|
|
7
10
|
* Set of options needed to construct a `PinTanClient`.
|
|
8
11
|
*/
|
|
@@ -31,6 +34,10 @@ export interface PinTanClientConfig extends Partial<ConnectionConfig> {
|
|
|
31
34
|
* If set to `true`, will log all requests performed and responses received.
|
|
32
35
|
*/
|
|
33
36
|
debug?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Configuration for decoupled TAN (asynchronous authentication)
|
|
39
|
+
*/
|
|
40
|
+
decoupledTanConfig?: DecoupledTanConfig;
|
|
34
41
|
}
|
|
35
42
|
export declare class PinTanClient extends Client {
|
|
36
43
|
/**
|
|
@@ -44,4 +51,40 @@ export declare class PinTanClient extends Client {
|
|
|
44
51
|
constructor(config: PinTanClientConfig);
|
|
45
52
|
createDialog(dialogConfig?: DialogConfig): Dialog;
|
|
46
53
|
createRequest(dialog: Dialog, segments: Segment<any>[], tan?: string): Request;
|
|
54
|
+
/**
|
|
55
|
+
* Handle a decoupled TAN challenge with automatic polling
|
|
56
|
+
*
|
|
57
|
+
* High-level method for handling decoupled TAN authentication flow.
|
|
58
|
+
* Automatically manages the polling lifecycle and provides status updates
|
|
59
|
+
* through an optional callback.
|
|
60
|
+
*
|
|
61
|
+
* **Usage Pattern:**
|
|
62
|
+
* ```typescript
|
|
63
|
+
* try {
|
|
64
|
+
* await client.creditTransfer(account, transfer);
|
|
65
|
+
* } catch (error) {
|
|
66
|
+
* if (error instanceof TanRequiredError && error.isDecoupledTan()) {
|
|
67
|
+
* await client.handleDecoupledTanChallenge(error, (status) => {
|
|
68
|
+
* console.log(`State: ${status.state}, Requests: ${status.statusRequestCount}`);
|
|
69
|
+
* });
|
|
70
|
+
* }
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* **FinTS Specification:**
|
|
75
|
+
* - Implements tanProcess="2" polling per FinTS 3.0 PINTAN
|
|
76
|
+
* - Uses HKTAN segment for status checks
|
|
77
|
+
* - Respects server timing from HITANS segment
|
|
78
|
+
*
|
|
79
|
+
* @param error The TanRequiredError that contains the challenge information
|
|
80
|
+
* @param statusCallback Optional callback for status updates during polling
|
|
81
|
+
* @return The final response after confirmation
|
|
82
|
+
*
|
|
83
|
+
* @throws {Error} If the error is not a decoupled TAN challenge
|
|
84
|
+
* @throws {DecoupledTanError} If polling fails (timeout, cancellation, etc.)
|
|
85
|
+
*
|
|
86
|
+
* @see Dialog.handleDecoupledTan for lower-level control
|
|
87
|
+
* @see https://www.hbci-zka.de/ for FinTS specification
|
|
88
|
+
*/
|
|
89
|
+
handleDecoupledTanChallenge(error: TanRequiredError, statusCallback?: DecoupledTanStatusCallback): Promise<Response>;
|
|
47
90
|
}
|
package/dist/pin-tan-client.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.PinTanClient = void 0;
|
|
4
13
|
const client_1 = require("./client");
|
|
@@ -21,15 +30,60 @@ class PinTanClient extends client_1.Client {
|
|
|
21
30
|
this.connection = new http_connection_1.HttpConnection(connectionConfig);
|
|
22
31
|
}
|
|
23
32
|
createDialog(dialogConfig) {
|
|
24
|
-
const { blz, name, pin, productId = constants_1.PRODUCT_NAME } = this.config;
|
|
33
|
+
const { blz, name, pin, productId = constants_1.PRODUCT_NAME, decoupledTanConfig } = this.config;
|
|
25
34
|
const { connection } = this;
|
|
26
|
-
return new dialog_1.Dialog(dialogConfig ? dialogConfig : { blz, name, pin, systemId: "0", productId }, connection);
|
|
35
|
+
return new dialog_1.Dialog(dialogConfig ? dialogConfig : { blz, name, pin, systemId: "0", productId }, connection, decoupledTanConfig);
|
|
27
36
|
}
|
|
28
37
|
createRequest(dialog, segments, tan) {
|
|
29
38
|
const { blz, name, pin } = this.config;
|
|
30
39
|
const { systemId, dialogId, msgNo, tanMethods } = dialog;
|
|
31
40
|
return new request_1.Request({ blz, name, pin, systemId, dialogId, msgNo, segments, tanMethods, tan });
|
|
32
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Handle a decoupled TAN challenge with automatic polling
|
|
44
|
+
*
|
|
45
|
+
* High-level method for handling decoupled TAN authentication flow.
|
|
46
|
+
* Automatically manages the polling lifecycle and provides status updates
|
|
47
|
+
* through an optional callback.
|
|
48
|
+
*
|
|
49
|
+
* **Usage Pattern:**
|
|
50
|
+
* ```typescript
|
|
51
|
+
* try {
|
|
52
|
+
* await client.creditTransfer(account, transfer);
|
|
53
|
+
* } catch (error) {
|
|
54
|
+
* if (error instanceof TanRequiredError && error.isDecoupledTan()) {
|
|
55
|
+
* await client.handleDecoupledTanChallenge(error, (status) => {
|
|
56
|
+
* console.log(`State: ${status.state}, Requests: ${status.statusRequestCount}`);
|
|
57
|
+
* });
|
|
58
|
+
* }
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* **FinTS Specification:**
|
|
63
|
+
* - Implements tanProcess="2" polling per FinTS 3.0 PINTAN
|
|
64
|
+
* - Uses HKTAN segment for status checks
|
|
65
|
+
* - Respects server timing from HITANS segment
|
|
66
|
+
*
|
|
67
|
+
* @param error The TanRequiredError that contains the challenge information
|
|
68
|
+
* @param statusCallback Optional callback for status updates during polling
|
|
69
|
+
* @return The final response after confirmation
|
|
70
|
+
*
|
|
71
|
+
* @throws {Error} If the error is not a decoupled TAN challenge
|
|
72
|
+
* @throws {DecoupledTanError} If polling fails (timeout, cancellation, etc.)
|
|
73
|
+
*
|
|
74
|
+
* @see Dialog.handleDecoupledTan for lower-level control
|
|
75
|
+
* @see https://www.hbci-zka.de/ for FinTS specification
|
|
76
|
+
*/
|
|
77
|
+
handleDecoupledTanChallenge(error, statusCallback) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
if (!error.isDecoupledTan()) {
|
|
80
|
+
throw new Error("The provided TanRequiredError does not represent a decoupled TAN challenge. " +
|
|
81
|
+
"Only call handleDecoupledTanChallenge when error.isDecoupledTan() returns true. " +
|
|
82
|
+
"For regular TAN challenges, use your normal TAN handling flow instead.");
|
|
83
|
+
}
|
|
84
|
+
return error.dialog.handleDecoupledTan(error.transactionReference, error.challengeText, statusCallback);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
33
87
|
}
|
|
34
88
|
exports.PinTanClient = PinTanClient;
|
|
35
89
|
//# sourceMappingURL=pin-tan-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pin-tan-client.js","sourceRoot":"","sources":["../src/pin-tan-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pin-tan-client.js","sourceRoot":"","sources":["../src/pin-tan-client.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qCAAkC;AAClC,qCAAgD;AAChD,uCAAoC;AACpC,uDAAqE;AAGrE,2CAA2C;AAuC3C,MAAa,YAAa,SAAQ,eAAM;IAUpC,YAAY,MAA0B;QAClC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;QAC/D,MAAM,gBAAgB,GAAqB;YACvC,GAAG;YACH,KAAK,EAAE,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,KAAK;YACrB,OAAO,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,KAAK;YACzB,UAAU,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,CAAC;YAC3B,UAAU,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,IAAI;SACjC,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,IAAI,gCAAc,CAAC,gBAAgB,CAAC,CAAC;IAC3D,CAAC;IAEM,YAAY,CAAC,YAA2B;QAC3C,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,GAAG,wBAAY,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACrF,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QAC5B,OAAO,IAAI,eAAM,CACb,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,EAC1E,UAAU,EACV,kBAAkB,CACrB,CAAC;IACN,CAAC;IAEM,aAAa,CAAC,MAAc,EAAE,QAAwB,EAAE,GAAY;QACvE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACvC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;QACzD,OAAO,IAAI,iBAAO,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IACjG,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACU,2BAA2B,CACpC,KAAuB,EACvB,cAA2C;;YAE3C,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CACX,8EAA8E;oBAC1E,kFAAkF;oBAClF,wEAAwE,CAC/E,CAAC;YACN,CAAC;YAED,OAAO,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QAC5G,CAAC;KAAA;CACJ;AAzFD,oCAyFC"}
|
package/dist/segments/hnsha.d.ts
CHANGED
|
@@ -14,5 +14,10 @@ export declare class HNSHA extends HNSHA_base {
|
|
|
14
14
|
protected defaults(): void;
|
|
15
15
|
protected serialize(): (string | string[])[];
|
|
16
16
|
protected deserialize(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Override debugString to mask sensitive data (PIN/TAN).
|
|
19
|
+
* This prevents credentials from being exposed in logs.
|
|
20
|
+
*/
|
|
21
|
+
get debugString(): string | string[];
|
|
17
22
|
}
|
|
18
23
|
export {};
|
package/dist/segments/hnsha.js
CHANGED
|
@@ -25,6 +25,26 @@ class HNSHA extends (0, segment_1.SegmentClass)(HNSHAProps) {
|
|
|
25
25
|
deserialize() {
|
|
26
26
|
throw new Error("Not implemented.");
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Override debugString to mask sensitive data (PIN/TAN).
|
|
30
|
+
* This prevents credentials from being exposed in logs.
|
|
31
|
+
*/
|
|
32
|
+
get debugString() {
|
|
33
|
+
const info = `Type: ${this.type}\n` +
|
|
34
|
+
`Version: ${this.version}\n` +
|
|
35
|
+
`Segment Number: ${this.segNo}\n` +
|
|
36
|
+
`Referencing: ${this.reference === undefined ? "None" : this.reference}\n` +
|
|
37
|
+
`----\n`;
|
|
38
|
+
const { secRef, tan } = this;
|
|
39
|
+
const maskedData = [
|
|
40
|
+
format_1.Format.num(secRef),
|
|
41
|
+
format_1.Format.empty(),
|
|
42
|
+
tan ? ["***MASKED***", "***MASKED***"] : "***MASKED***",
|
|
43
|
+
];
|
|
44
|
+
return maskedData.reduce((result, group, index) => {
|
|
45
|
+
return `${result}DG ${index}: ${Array.isArray(group) ? group.join(", ") : group}\n`;
|
|
46
|
+
}, info);
|
|
47
|
+
}
|
|
28
48
|
}
|
|
29
49
|
exports.HNSHA = HNSHA;
|
|
30
50
|
//# sourceMappingURL=hnsha.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hnsha.js","sourceRoot":"","sources":["../../src/segments/hnsha.ts"],"names":[],"mappings":";;;AAAA,uCAAyC;AACzC,sCAAmC;AAEnC,MAAa,UAAU;CAKtB;AALD,gCAKC;AAED;;;GAGG;AACH,MAAa,KAAM,SAAQ,IAAA,sBAAY,EAAC,UAAU,CAAC;IAAnD;;QACW,SAAI,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"hnsha.js","sourceRoot":"","sources":["../../src/segments/hnsha.ts"],"names":[],"mappings":";;;AAAA,uCAAyC;AACzC,sCAAmC;AAEnC,MAAa,UAAU;CAKtB;AALD,gCAKC;AAED;;;GAGG;AACH,MAAa,KAAM,SAAQ,IAAA,sBAAY,EAAC,UAAU,CAAC;IAAnD;;QACW,SAAI,GAAG,OAAO,CAAC;IAoC1B,CAAC;IAlCa,QAAQ;QACd,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;IACrB,CAAC;IAES,SAAS;QACf,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAClC,OAAO,CAAC,eAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,eAAM,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxE,CAAC;IAES,WAAW;QACjB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,IAAW,WAAW;QAClB,MAAM,IAAI,GACN,SAAS,IAAI,CAAC,IAAI,IAAI;YACtB,YAAY,IAAI,CAAC,OAAO,IAAI;YAC5B,mBAAmB,IAAI,CAAC,KAAK,IAAI;YACjC,gBAAgB,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI;YAC1E,QAAQ,CAAC;QACb,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC7B,MAAM,UAAU,GAAG;YACf,eAAM,CAAC,GAAG,CAAC,MAAM,CAAC;YAClB,eAAM,CAAC,KAAK,EAAE;YACd,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc;SAC1D,CAAC;QACF,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAC9C,OAAO,GAAG,MAAM,MAAM,KAAK,KAAK,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QACxF,CAAC,EAAE,IAAI,CAAC,CAAC;IACb,CAAC;CACJ;AArCD,sBAqCC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fints-lib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "FinTS client library with psd2 support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fints",
|
|
@@ -56,16 +56,16 @@
|
|
|
56
56
|
"@types/invariant": "^2.2.37",
|
|
57
57
|
"@types/isomorphic-fetch": "^0.0.39",
|
|
58
58
|
"@types/istanbul-lib-report": "^3.0.3",
|
|
59
|
-
"@types/jest": "^
|
|
59
|
+
"@types/jest": "^30.0.0",
|
|
60
60
|
"@types/node": "^25.0.3",
|
|
61
61
|
"cxsd": "^0.1.1",
|
|
62
62
|
"fetch-mock": "^12.6.0",
|
|
63
63
|
"fints-institute-db": "^0.16.0",
|
|
64
|
-
"jest": "^
|
|
65
|
-
"minimatch": "^10.
|
|
64
|
+
"jest": "^30.2.0",
|
|
65
|
+
"minimatch": "^10.1.1",
|
|
66
66
|
"ts-jest": "^29.4.6",
|
|
67
|
-
"typedoc": "^0.
|
|
68
|
-
"typescript": "^5.
|
|
67
|
+
"typedoc": "^0.28.15",
|
|
68
|
+
"typescript": "^5.9.3"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"bind-decorator": "^1.0.11",
|