Skip to content

Handle decoupled TAN challenges when banks return 3955 without 0030#44

Merged
larsdecker merged 5 commits intomasterfrom
copilot/update-fints-lib-handling
Apr 21, 2026
Merged

Handle decoupled TAN challenges when banks return 3955 without 0030#44
larsdecker merged 5 commits intomasterfrom
copilot/update-fints-lib-handling

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 21, 2026

Some banks (e.g. Sparda) start decoupled SCA by returning 3955 + HITAN during dialog.init(), but without 0030.
The current flow only raises TanRequiredError on 0030, so these responses were treated as success and the decoupled challenge was not surfaced to callers.

  • TAN challenge detection in Dialog.send()

    • Extended challenge detection to also treat 3955 as TAN-required when a HITAN segment is present.
    • Preserved existing 0030 behavior; 0030 remains the primary trigger path.
  • Decoupled flow classification

    • Marked 3955 responses as decoupled TAN (decoupledTanState = INITIATED) alongside existing decoupled indicators (3956, 3076).
    • Propagated the actual trigger code into TanRequiredError.context.returnCode (0030 or 3955) for downstream handling/diagnostics.
  • Regression coverage

    • Added a dialog-level test for the Sparda-style response (3955 + HITAN, no 0030) asserting:
      • TanRequiredError is thrown
      • decoupled state is set to INITIATED
      • context return code is 3955
const tanRequiredCode = returnValues.has("0030")
  ? "0030"
  : hitan && returnValues.has("3955")
    ? "3955"
    : undefined;

Copilot AI and others added 4 commits April 21, 2026 21:17
Agent-Logs-Url: https://github.com/larsdecker/fints/sessions/9e3bf9ab-82f7-41d2-8635-3c82b08f41e1

Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Agent-Logs-Url: https://github.com/larsdecker/fints/sessions/9e3bf9ab-82f7-41d2-8635-3c82b08f41e1

Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Agent-Logs-Url: https://github.com/larsdecker/fints/sessions/9e3bf9ab-82f7-41d2-8635-3c82b08f41e1

Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Agent-Logs-Url: https://github.com/larsdecker/fints/sessions/9e3bf9ab-82f7-41d2-8635-3c82b08f41e1

Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
@larsdecker larsdecker marked this pull request as ready for review April 21, 2026 21:44
Copilot AI review requested due to automatic review settings April 21, 2026 21:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates TAN-challenge detection to correctly surface “decoupled SCA initiated” responses where some banks return 3955 + HITAN during dialog.init() without the usual 0030, ensuring callers receive a TanRequiredError in these cases.

Changes:

  • Extend Dialog.send() TAN-required detection to also treat 3955 as TAN-required when a HITAN segment is present, while keeping 0030 as the primary trigger.
  • Mark 3955 responses as decoupled (decoupledTanState = INITIATED) and propagate the actual triggering return code (0030 vs 3955) into TanRequiredError.context.returnCode.
  • Add a regression test for the Sparda-style response (3955 + HITAN, no 0030).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/fints/src/dialog.ts Adds 3955+HITAN TAN detection, decoupled classification, and return-code propagation into error context.
packages/fints/src/tests/test-dialog.ts Adds regression coverage for 3955+HITAN without 0030.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/fints/src/dialog.ts Outdated
const returnValue = response.returnValues().get("0030");
const returnValues = response.returnValues();
const hasTanRequiredCode = returnValues.has("0030");
let hitan;
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let hitan; introduces an implicit any which will fail TypeScript compilation because the repo root tsconfig.json sets noImplicitAny: true. Please add an explicit type for hitan (e.g., the HITAN segment type, optionally allowing undefined as appropriate) instead of leaving it untyped.

Suggested change
let hitan;
let hitan: HITAN | undefined;

Copilot uses AI. Check for mistakes.
Comment thread packages/fints/src/dialog.ts Outdated
Comment on lines 284 to 285
// When either code is present alongside "0030", it signals decoupled TAN flow
// where the user must approve the transaction in a separate app (e.g., mobile banking)
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The decoupled-TAN comment now says the codes are indicators "alongside "0030"", but the logic also treats 3955 as a decoupled indicator even when it is the primary TAN-required code (no 0030). Please update the comment to match the new behavior so it doesn’t mislead future maintainers.

Suggested change
// When either code is present alongside "0030", it signals decoupled TAN flow
// where the user must approve the transaction in a separate app (e.g., mobile banking)
// These codes indicate a decoupled TAN flow where the user must approve the
// transaction in a separate app or device. "3955" can either accompany "0030"
// or be the primary TAN-required return code itself when returned with HITAN.

Copilot uses AI. Check for mistakes.
@larsdecker
Copy link
Copy Markdown
Owner

@copilot apply changes based on the comments in this thread

Agent-Logs-Url: https://github.com/larsdecker/fints/sessions/a5261cb6-8965-498a-bc6a-0eb5311e9c3a

Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Apr 21, 2026

@copilot apply changes based on the comments in this thread

Done — I applied the requested thread feedback in commit 298a86d: hitan is now explicitly typed (HITAN | undefined) and the decoupled TAN comment was updated to match the 3955-without-0030 behavior.

Copilot AI requested a review from larsdecker April 21, 2026 21:52
@larsdecker larsdecker merged commit b7736c3 into master Apr 21, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants