
Security architecture
Defence in depth, from the edge to the audit log
Stage 0 found unauthenticated tracking on the login page, local portal passwords without MFA, and a content security policy that permitted inline script. Every one of those findings is designed out here.
0
Passwords in the new portal
100%
MFA coverage of portal accounts
0
Session-replay tools retained
01
Identity & multi-factor authentication
The portal's weakest link today is its strongest control tomorrow.
LA OFFICER
│ 1. requests /portal
▼
PLATFORM ──2. OIDC authorisation request (PKCE, nonce, state)──▶ ENTRA ID
│
3. primary auth (organisational account)│
4. MFA challenge — phishing-resistant │
5. Conditional Access evaluation: │
device compliance · sign-in risk ·
location · session lifetime
◀────────6. signed ID token + claims (tenant, authority, roles)┘
│
▼
PLATFORM 7. verify signature, issuer, audience, nonce, expiry
8. map claims → RBAC role + authority scope
9. issue short-lived HttpOnly session, rotate on privilege change
10. every request re-authorised server-side; RLS enforced in the DB
11. all auth events written to the tamper-evident audit logNo shared or local credentials
Accounts are organisational identities managed by each local authority's own IT function. Leavers lose access the moment their account is disabled.
Phishing-resistant MFA
Passkeys/FIDO2 and Microsoft Authenticator number-matching preferred; SMS permitted only as a documented fallback.
Domain allow-listing
Only verified local authority and CARO tenants/domains may complete registration; self-service open registration is removed.
Approval workflow
Elevated roles require named approval, are time-bounded and are reviewed on a recurring access-recertification cycle.
02
Layered controls
Each layer assumes the one outside it may fail.
Perimeter
- Managed WAF with OWASP core rule set, tuned and monitored
- Bot management, adaptive rate limiting and DDoS absorption at the edge
- TLS 1.3 only, HSTS with preload, automated certificate rotation
- DNSSEC, CAA records, SPF/DKIM/DMARC enforcement on sending domains
Application
- Strict nonce-based Content-Security-Policy with no unsafe-inline and no unsafe-eval
- Referrer-Policy, X-Content-Type-Options, Permissions-Policy, COOP/CORP, frame-ancestors none
- CSRF middleware on every server function; SameSite=Lax, HttpOnly, Secure cookies
- Zod validation and output encoding at every boundary; parameterised queries only
- Signed, short-lived URLs for protected document downloads
Identity
- Microsoft Entra ID (OIDC) single sign-on — no locally stored passwords
- MFA enforced for every portal account, phishing-resistant methods preferred
- Conditional Access: device compliance, risk-based sign-in, session lifetime, optional geo-fencing
- Local authority derived from the verified identity claim — the free-text self-declaration is removed
- SCIM provisioning and immediate de-provisioning on leaver events
Authorisation
- Role-based access control: Reader, Contributor, Authority Administrator, CARO Administrator
- Authority-scoped data access enforced server-side and again at row level in the database
- Deny-by-default routing; no privilege decision ever made in client code
- Just-in-time elevation with approval and time limits for administrative actions
Data
- EU-only data residency; encryption in transit (TLS 1.3) and at rest (AES-256)
- Row-level security policies mirroring application authorisation
- Data minimisation, documented retention schedule and defensible deletion
- Tamper-evident audit log of authentication, permission change and content publication events
Supply chain
- Pinned dependencies, automated patch PRs, SCA with license policy enforcement
- Secret scanning with push protection; all secrets in a managed vault, never in the repository
- Signed commits, protected branches, reproducible builds and a signed SBOM per release
- Least-privilege CI credentials using short-lived OIDC federation, no long-lived keys
03
Threat model
Named threats, the Stage 0 position, and the designed mitigation.
| Threat | Observed today | Proposed mitigation |
|---|---|---|
| Credential stuffing / password reuse against the portal | Current site uses local accounts with self-service registration | Passwords eliminated entirely — Entra ID SSO with enforced MFA and risk-based Conditional Access |
| Unauthorised access to another authority's data | Authority declared by the user as free text | Authority derived from the verified identity claim, enforced by server-side authorisation and row-level security |
| Cross-site scripting via CMS-authored content | Permissive CSP allows inline and evaluated script | Strict nonce CSP, sanitised rich text, no dangerouslySetInnerHTML on untrusted input |
| Protected portal content leaking into public search | Single search surface | Physically separate indexes plus an automated CI assertion on every build |
| Behavioural tracking on authenticated pages | Session-replay tooling observed on the login page | No replay tooling anywhere; analytics consent-gated and disabled on authenticated views |
| Compromised dependency or build pipeline | No published provenance | Signed commits, SBOM, artefact attestation, least-privilege OIDC CI credentials, protected environments |
| Defacement or malicious content publication | Limited workflow visibility | Approval workflow, immutable audit trail, atomic rollback within minutes |
| Loss of service or data | Recovery objectives undocumented | RPO 15 min / RTO 60 min with rehearsed, evidenced restores |
04
Brand & reputational protection
Security failures are brand failures. These controls protect the CARO name as much as the data.
Nothing publishes unreviewed
Editorial approval, scheduled publication and rollback prevent test pages and placeholder slugs from reaching the public index — a problem observed on the current estate.
Consistent, controlled presentation
A locked design-token system and component library make off-brand pages structurally difficult to create.
Domain and email trust
DMARC enforcement, DNSSEC and CAA reduce the risk of spoofed CARO communications and certificate mis-issuance.
Link equity preserved
Single-hop 301 redirects for every legacy URL, retained for at least 24 months, with Search Console monitoring at cutover.
Accurate public statements
Accessibility and privacy statements published, dated and maintained — with a named contact and feedback route.
Responsible disclosure
Published security.txt and a documented vulnerability-disclosure process with response targets.
05
Assurance, monitoring & incident response
Controls are only credible when they are tested and reported.
- Independent penetration test of the public site and the portal before go-live, then annually and after any significant change; remediation evidence provided to the authority.
- Continuous automated scanning: SAST, SCA, secret detection, IaC and header/TLS posture checks with results reported monthly.
- Centralised security logging with alerting on authentication anomalies, privilege change, mass export and administrative action.
- Documented incident response plan with severity definitions, escalation paths, forensic log retention and GDPR breach-notification timelines aligned to the authority's DPO.
- Access recertification, key rotation and dependency-patch SLAs (critical vulnerabilities remediated within defined windows) written into the service agreement.
- Annual disaster-recovery and restore rehearsal, evidenced in the service report.
Provenance“Observed today” entries are behaviours recorded during read-only Stage 0 inspection of the live caro.ie estate (see docs/current-site-audit.md, docs/integration-register.md and docs/risk-register.md). They are technical observations, not legal conclusions. All portal screens in this prototype are MOCK and perform no real authentication.