Skip to content

Conversation

Copy link

Copilot AI commented Dec 28, 2025

Adds PSD2-compliant decoupled TAN authentication where transaction approval happens on a separate device (e.g., mobile banking app). Implements FinTS 3.0 PINTAN specification with automatic polling, state management, and configurable timeouts.

Core Implementation

DecoupledTanManager (src/decoupled-tan/decoupled-tan-manager.ts)

  • Manages polling lifecycle with configurable intervals (default: 2s between requests, 60 max requests, 5min timeout)
  • State machine: INITIATED → CHALLENGE_SENT → PENDING_CONFIRMATION → CONFIRMED/FAILED/CANCELLED/TIMED_OUT
  • Respects server-provided timing parameters from TanMethod
  • Handles return codes 3956 (pending), 3076 (SCA required), 0030 (confirmed)

Type System (src/decoupled-tan/types.ts)

  • DecoupledTanState enum for lifecycle tracking
  • DecoupledTanConfig interface for polling configuration
  • DecoupledTanStatus interface for current state

Error Handling (src/errors/decoupled-tan-error.ts)

  • DecoupledTanError with status snapshot, transaction reference, remaining requests
  • Helper methods: isTimeout(), isCancelled(), hasRemainingRequests()

Integration Points

Dialog (src/dialog.ts)

  • send() auto-detects decoupled TAN requirements via return codes 3956/3076
  • handleDecoupledTan() initiates polling with optional status callbacks
  • checkDecoupledTanStatus() for manual status checks
  • cancelDecoupledTan() for user cancellation

PinTanClient (src/pin-tan-client.ts)

  • DecoupledTanConfig in client configuration
  • handleDecoupledTanChallenge() wraps polling with callback support

TanRequiredError (src/errors/tan-required-error.ts)

  • isDecoupledTan() method to detect decoupled challenges
  • decoupledTanState property for lifecycle tracking

Usage

const client = new PinTanClient({
    url: "https://bank.example.com/fints",
    name: "username",
    pin: "12345",
    blz: "12345678",
    decoupledTanConfig: {
        maxStatusRequests: 60,
        waitBetweenStatusRequests: 2000,
        totalTimeout: 300000,
    },
});

try {
    await client.creditTransfer(account, transfer);
} catch (error) {
    if (error instanceof TanRequiredError && error.isDecoupledTan()) {
        // Automatic polling with status updates
        await client.handleDecoupledTanChallenge(error, (status) => {
            console.log(`${status.state}: ${status.statusRequestCount}/${status.maxStatusRequests}`);
        });
    }
}

Testing

  • 38 new tests covering state machine, polling, timeouts, cancellation, error handling
  • 297 total tests passing (zero breaking changes)
  • 87.95% statement coverage, 88.05% line coverage
Original prompt

Implement Decoupled TAN (Asynchronous Authentication) Support

This comprehensive implementation adds support for Decoupled TAN (asynchronous authentication) to the fints-lib library, enabling modern PSD2-compliant authentication flows where transaction approval occurs on a separate, trusted device (e.g., mobile app).

Specification Reference

This implementation follows the FinTS 3.0 Security Specification (PINTAN) with these key requirements:

  • HKTAN Segment Support: tanProcess="2" for decoupled/asynchronous authentication
  • Polling Mechanism: Automatic status polling with configurable intervals and timeouts
  • HIRMG Return Codes: Support for codes 3956 (pending confirmation), 3920 (TAN methods available), 3076 (SCA required)
  • State Management: Track decoupled TAN states through the entire lifecycle
  • Timeout Handling: Configurable total timeout and polling parameters

Core Components to Implement

1. DecoupledTanManager (packages/fints/src/decoupled-tan/decoupled-tan-manager.ts)

  • Manages the decoupled TAN lifecycle
  • Handles automatic polling with exponential backoff
  • Tracks state transitions and errors
  • Configurable polling intervals and timeouts

2. DecoupledTanState and Enums (packages/fints/src/decoupled-tan/types.ts)

  • Define DecoupledTanState enum: INITIATED, CHALLENGE_SENT, PENDING_CONFIRMATION, CONFIRMED, FAILED, CANCELLED, TIMED_OUT
  • Define DecoupledTanConfig interface with polling parameters
  • Define DecoupledTanStatus interface for tracking current state

3. DecoupledTanError (packages/fints/src/errors/decoupled-tan-error.ts)

  • Custom error class for decoupled TAN failures
  • Includes state, transaction reference, and remaining status requests
  • Provides helpful error messages

4. Dialog Extension (packages/fints/src/dialog.ts)

  • Add DecoupledTanManager integration
  • Add handleDecoupledTan() method for initiating polling
  • Add checkDecoupledTanStatus() for manual status checks
  • Add cancelDecoupledTan() for user cancellation
  • Add support for detecting decoupled TAN requirements from HIRMG codes

5. PinTanClient Extension (packages/fints/src/pin-tan-client.ts)

  • Add DecoupledTanConfig to PinTanClientConfig
  • Add handleDecoupledTanChallenge() method with auto-polling support
  • Add callback support for UI updates during polling
  • Add submitWithDecoupledTan() for transparent decoupled TAN handling

6. TanRequiredError Extension (packages/fints/src/errors/tan-required-error.ts)

  • Add isDecoupledTan() method
  • Add decoupledTanState property
  • Add isMultiStep() method for multi-step flows

Implementation Features

Polling Behavior:

  • Configurable wait time before first status request (default: 2000ms)
  • Configurable wait time between status requests (default: 2000ms)
  • Configurable max status requests (default: 60)
  • Configurable total timeout (default: 5 minutes)
  • Automatic polling loop with state updates

Error Handling:

  • Graceful timeout with DecoupledTanError
  • Max status requests exceeded handling
  • User cancellation support
  • Server-side error code mapping
  • Detailed error messages for troubleshooting

State Tracking:

  • INITIATED: Challenge has been received
  • CHALLENGE_SENT: Challenge text presented to user
  • PENDING_CONFIRMATION: Polling for confirmation
  • CONFIRMED: Confirmation received from server
  • FAILED: Error occurred during polling
  • CANCELLED: User cancelled the TAN process
  • TIMED_OUT: Total timeout exceeded

User Integration:

  • Optional callback for UI updates during polling
  • Real-time state change notifications
  • Graceful cancellation support
  • Clear error messages

Testing Requirements

All implementations must include comprehensive tests:

Unit Tests (packages/fints/src/decoupled-tan/__tests__/):

  • DecoupledTanManager state machine tests
  • Polling interval calculation tests
  • Timeout handling tests
  • Error code mapping tests
  • HKTAN segment serialization with decoupled parameters
  • Status request segment creation

Integration Tests (packages/fints/src/__tests__/):

  • Dialog with decoupled TAN flows
  • Multi-step decoupled TAN scenarios
  • Cancellation workflows
  • End-to-end credit transfer with decoupled TAN
  • Error handling and recovery

Test Coverage Requirements:

  • Minimum 85% code coverage for decoupled TAN implementation
  • Mock FinTS server simulation for realistic test scenarios
  • Edge case handling (network errors, timeouts, rapid confirmations)

Files to Create/Modify

New Files:

  • packages/fints/src/decoupled-tan/decoupled-tan-manager.ts
  • packages/fints/src/decoupled-tan/types.ts
  • packages/fints/src/decoupled-tan/index.ts
  • packages/fints/src/errors/decoupled-tan-error.ts
  • packages/fints/src/decoupled-tan/__tests__/test-decoupled-tan-manager.ts
  • packages/fints/src/decoupled-tan/__tests__/test-decoupled-tan-integration.ts

Modified Files:

  • packages/fints/src/dialog.ts
  • `packages/fints/src/p...

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 4 commits December 28, 2025 23:58
Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement decoupled TAN support for asynchronous authentication Implement Decoupled TAN (Asynchronous Authentication) Support Dec 29, 2025
Copilot AI requested a review from larsdecker December 29, 2025 00:18
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.

2 participants