Handle decoupled TAN challenges when banks return 3955 without 0030#44
Handle decoupled TAN challenges when banks return 3955 without 0030#44larsdecker merged 5 commits intomasterfrom
Conversation
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>
There was a problem hiding this comment.
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 treat3955as TAN-required when aHITANsegment is present, while keeping0030as the primary trigger. - Mark
3955responses as decoupled (decoupledTanState = INITIATED) and propagate the actual triggering return code (0030vs3955) intoTanRequiredError.context.returnCode. - Add a regression test for the Sparda-style response (
3955+HITAN, no0030).
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.
| const returnValue = response.returnValues().get("0030"); | ||
| const returnValues = response.returnValues(); | ||
| const hasTanRequiredCode = returnValues.has("0030"); | ||
| let hitan; |
There was a problem hiding this comment.
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.
| let hitan; | |
| let hitan: HITAN | undefined; |
| // 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) |
There was a problem hiding this comment.
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.
| // 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 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>
Done — I applied the requested thread feedback in commit |
Some banks (e.g. Sparda) start decoupled SCA by returning
3955+HITANduringdialog.init(), but without0030.The current flow only raises
TanRequiredErroron0030, so these responses were treated as success and the decoupled challenge was not surfaced to callers.TAN challenge detection in
Dialog.send()3955as TAN-required when aHITANsegment is present.0030behavior;0030remains the primary trigger path.Decoupled flow classification
3955responses as decoupled TAN (decoupledTanState = INITIATED) alongside existing decoupled indicators (3956,3076).TanRequiredError.context.returnCode(0030or3955) for downstream handling/diagnostics.Regression coverage
3955+HITAN, no0030) asserting:TanRequiredErroris thrownINITIATED3955