Authentication
Auth Flow
Drivers authenticate with phone + OTP, then set a 4-digit PIN for subsequent logins.
┌─────────┐ Phone number ┌──────────────┐ OTP verified ┌──────────────┐
│ App │────────────────►│ POST │────────────────►│ Store JWT │
│ │ │ /login │ │ + PIN hash │
└─────────┘ └──────────────┘ └──────────────┘
┌─────────┐ PIN entered ┌──────────────┐ PIN valid ┌──────────────┐
│ App │────────────────►│ POST │────────────────►│ Store JWT │
│ │ │ /get-pin │ │ Proceed │
└─────────┘ └──────────────┘ └──────────────┘
Steps
1. Phone Login
final response = await dioClient.post(
'/driver/user-auth/login',
data: {'phone': '+919876543210'},
);
2. Verify OTP
final response = await dioClient.post(
'/driver/user-auth/otp-verify',
data: {
'phone': '+919876543210',
'otp': '123456',
},
);
// Response
// {
// "driver": { "id": "...", "driverName": "...", "bus": {...} },
// "accessToken": "...",
// "refreshToken": "...",
// "isPinExist": false
// }
// Store tokens
await secureStorage.write('accessToken', accessToken);
await secureStorage.write('refreshToken', refreshToken);
3. Set PIN (first login only)
If isPinExist == false, redirect to PIN setup screen.
await dioClient.post(
'/driver/user-auth/set-pin',
data: {'pin': '1234'},
);
4. PIN Login (subsequent opens)
final response = await dioClient.post(
'/driver/user-auth/get-pin',
data: {'phone': '+919876543210', 'pin': '1234'},
);
5. Forgot PIN
// Step 1: Request OTP
await dioClient.post('/driver/user-auth/get-forgotten-pin', data: {'phone': '+919876543210'});
// Step 2: Verify OTP
await dioClient.post('/driver/user-auth/verify-change-pin-otp', data: {'phone': '+919876543210', 'otp': '123456'});
// Step 3: Set new PIN
await dioClient.post('/driver/user-auth/change-pin', data: {'phone': '+919876543210', 'pin': '5678'});
Forgot PIN Flow
class ForgotPasswordOtpView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PinCodeVerificationScreen(
onVerified: () => Navigator.pushReplacementNamed(context, '/set-pin'),
);
}
}
Logout
await secureStorage.delete('accessToken');
await secureStorage.delete('refreshToken');
// Navigate to login screen