~/bpabatao
← back to index

Identity & Access

Narrowing the paths that let someone reach an account that was not theirs - at the front door, in the browser, and in the console.

Role
Primary author
Period
2026
Stack
AWS Cognito · Oracle CCS · Terraform · IAM · Fastify · TypeScript
beforeafterno direct accesson most portalsbrowserno password or email callscore apipermissions declared onceoracle ccsidentity verificationcognitoreal client ip forwardedregistration: lockout on repeat attempts,zip disambiguation on the last-four space
On most portals the browser no longer changes email or password directly; those calls go through the API, which forwards the real client IP and gates registration on verification with lockout

Problem

Three separate ways existed to end up somewhere you should not be. Identity verification at registration matched on data thin enough to hit the wrong person. The browser held credentials to talk to the identity provider directly. And engineer and pipeline access to AWS had grown by accretion rather than design.

Constraints

Real utility customers register through this flow, so a fix that locks out legitimate people is not a fix. The portals are multi-tenant and the identity plumbing is shared, so a backend change reaches every tenant.

Decisions

Architecture

At the front door: an identity-verification gap enabled account takeover - the last-four plus street match resolved to the wrong person on roughly 2.4% of one tenant's accounts.

In the browser: on most portals, email and password changes now go through the API instead of from the page. A build-time content-security policy injects environment-aware provider URLs, and the real client IP is forwarded to the provider so its adaptive threat protection sees the actual source rather than the load balancer, logging an error when that forwarding falls back.

In the console: every destructive operation is permission-gated, and the recorded IAM roles cover a least-privilege developer policy, per-client task roles, and deploy roles named and documented rather than inherited.

Outcome

view resume ↗ (opens in new tab)email me