Bug Fix: HMRC OAuth Callback Now Requires a Valid NINO
Bug Fix: HMRC OAuth Callback Now Requires a Valid NINO
Release: v1.0.425
Severity: Medium
Status: Fixed
What Happened
A bug was identified in the HMRC OAuth connection flow that could result in credentials being stored with an empty National Insurance Number (NINO), and business details never being retrieved from HMRC — all without any error being surfaced to the user.
This affected users who:
- Clicked Skip when prompted for their NINO during onboarding, and
- Then proceeded to connect their HMRC account from the HMRC page.
Root Cause
The HMRC authorise route (/api/hmrc/authorise/route.ts) encrypts the user's NINO and embeds it in the OAuth state parameter before redirecting to HMRC. When the OAuth flow completes and HMRC redirects back to the callback route (/api/hmrc/callback/route.ts), the callback decrypts this state and uses the NINO in two subsequent calls:
// In /api/hmrc/callback/route.ts
const encryptedNino = Buffer.from(encryptedNinoB64, 'base64url').toString('utf8');
niNumber = await ninoCipher.decrypt(encryptedNino);
// ...
await upsertCredentials({ userId, orgId, niNumber, tokens });
await fetchBusinessDetails(tokens.access_token, niNumber);
If the user had no NINO set at the time they initiated OAuth, niNumber would be an empty string (''). The code did not guard against this case:
upsertCredentialsstored the empty string into the credentials record.fetchBusinessDetailsforwarded the empty string to the HMRC API, which responded with a400or422error. This error was caught internally and treated as non-fatal, so execution continued and the callback returned a success response to the user.
Impact
Users affected by this bug would see their HMRC connection appear successful, but:
- Their stored credentials would have an empty
niNumber. - Their HMRC business details (including Business ID required for submissions) would not be fetched or stored.
- Subsequent quarterly submissions would fail, as a valid NINO is required by HMRC's MTD ITSA API at submission time.
The failure at submission time would be the first indication to the user that something had gone wrong — with no clear trace back to the original OAuth connection issue.
The Fix
The callback route now validates the decrypted NINO before proceeding with any HMRC API calls or credential storage. If the NINO is empty or absent, the callback returns an explicit error response and does not store credentials.
This ensures:
- No credentials are saved in an invalid state.
- Users receive a clear, actionable error message explaining that their NINO must be set before connecting to HMRC.
- The silent data corruption path is fully closed.
Action Required
If you connected to HMRC before setting your NINO
Your stored credentials may be affected. To resolve this:
- Go to Settings → Profile and add your National Insurance Number.
- Navigate to the HMRC page.
- Disconnect your existing HMRC connection (if applicable).
- Click Connect to HMRC and complete the OAuth flow again.
Your credentials will be saved correctly and your business details will be fetched from HMRC.
For new connections
No action required. The fix is applied automatically. If you attempt to connect to HMRC without a NINO set, you will now see a clear prompt to add your NINO first.
Affected Components
| Component | File |
|---|---|
| HMRC Authorise Route | src/app/api/hmrc/authorise/route.ts |
| HMRC Callback Route | src/app/api/hmrc/callback/route.ts |