Add TPIN reset via OTP, with server-clock countdowns and redacted API logs
- Reset TPIN: empty-body initiate -> OTP -> encrypted new TPIN via /tpin/reset/*, from a Services tile, search, and "Forgot your TPIN?" on the transfer's TPIN sheet (returns to the same transfer review) - Handle every documented code: SESSION_INVALID signs out, TPIN_NOT_SET offers Create TPIN, CBS customer/account/org refusals stop the flow, outages retry from the start, expired or spent OTP/token restarts, policy VALIDATION_ERROR stays on the new-TPIN step - Secrets live in screen state only and are dropped as each step ends - Countdowns use the envelope timestamp, kept aside by the interceptor, so a wrong device clock cannot skew OTP or token expiry - New TPINs refuse any three-digit run (1235, 5987), for create too - Dev API logger redacts the session token, OTPs, PINs, encrypted payloads and one-time tokens - Tests: request bodies, RSA-OAEP SHA-256 payload decrypted with Node, fresh nonce on key retry, server-clock deadlines, log redaction Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f1def81eb7
commit
5fbd13ba12
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
|
||||
|
||||
import { ScreenShell } from '../../../components';
|
||||
import { useAppSelector } from '../../../app/hooks';
|
||||
import { FeatureKey } from '../../../constants/featureKeys';
|
||||
import { useFeature } from '../../../features';
|
||||
import type { ServicesStackParamList } from '../../../navigation/types';
|
||||
import { TpinResetFlow } from '../../payments/components/TpinResetFlow';
|
||||
|
||||
type Props = Readonly<NativeStackScreenProps<ServicesStackParamList, 'ResetTpin'>>;
|
||||
|
||||
/**
|
||||
* Resets a forgotten transaction PIN, from the service desk.
|
||||
*
|
||||
* The signed-in session stands in for the MPIN that creating a TPIN asks for;
|
||||
* the bank re-verifies the customer and an OTP to the registered mobile is the
|
||||
* second factor.
|
||||
*/
|
||||
export default function ResetTpinScreen({ navigation }: Props) {
|
||||
const session = useAppSelector((state) => state.auth.session);
|
||||
const lastProfile = useAppSelector((state) => state.auth.lastProfile);
|
||||
// Create TPIN is offered on TPIN_NOT_SET only where its route exists.
|
||||
const canCreateTpin = useFeature(FeatureKey.SERVICES_TPIN_CHANGE);
|
||||
|
||||
return (
|
||||
<ScreenShell
|
||||
title="Reset TPIN"
|
||||
subtitle="Set a new PIN for authorising fund transfers"
|
||||
contentContainerStyle={styles.container}
|
||||
>
|
||||
<TpinResetFlow
|
||||
mobileNumber={session?.mobileNumber ?? lastProfile?.mobileNumber}
|
||||
onSuccess={() => navigation.goBack()}
|
||||
onExit={() => navigation.goBack()}
|
||||
onCreateTpin={canCreateTpin ? () => navigation.replace('SetTpin') : undefined}
|
||||
/>
|
||||
</ScreenShell>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
padding: 16,
|
||||
flexGrow: 1,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user