Security-by-Design Systems
Design and verify trust boundaries, authentication and authorization with worked policy tests, operational ownership and safe failure behavior.
trigger="A new system or material change introduces a trust boundary, sensitive data flow, privileged action or security exception." owner="The service architect owns the design; the security owner reviews threats and the service owner accepts operation and recovery." participants={["Service architect", "Security engineer", "Product/data owner", "Platform engineer", "On-call operator"]} prerequisites={["A scoped user journey and its data classification", "Current identity, dependency and administrative-access maps", "Allowed and prohibited business actions", "Owners for incident response, key management and risk acceptance"]} outputs={["A threat model linked to verifiable requirements", "Identity and authorization decision records", "Negative tests and control-failure evidence", "A release gate with owned exceptions and recovery procedures"]} doneWhen={["Critical trust-boundary controls are enforced outside client input", "Allowed and denied policy cases pass", "Revocation, restoration and control outages have been exercised", "Residual risk has an authorized owner and review trigger"]} />
Scope and decision
Security-by-design makes the safe path the normal path for engineers and operators. The practical work starts with assets, trust boundaries, identities, data flows and failure consequences. It then turns those findings into controls that can be verified in code, infrastructure and production operations.
This playbook is for engineering leaders, architects and product teams designing a new system or correcting a system where security depends too heavily on individual judgment. It covers threat modelling, identity, authorization, secrets, data protection, software supply chain controls, observability, incident readiness and the evidence needed before release.
Use it as a working guide, not as a compliance certificate. Regulatory and contractual obligations must be reviewed for the actual product, data and jurisdictions involved. The NIST Secure Software Development Framework, OWASP Application Security Verification Standard and CISA Secure by Design guidance provide useful primary references for the controls described here.
Start with the system, not the control catalogue
Before selecting tools, document what the system must protect and what can go wrong. A useful threat model answers five questions:
- Which identities interact with the system, including users, services, administrators and third parties?
- Which data or actions would cause material harm if disclosed, changed, replayed or made unavailable?
- Where does trust change, such as a browser calling an API, a workload assuming a cloud role or a service sending data to a vendor?
- Which controls prevent, detect and contain failure at each boundary?
- Who owns the decision when a control fails or creates an operational exception?
Draw the real data flow. Include queues, caches, object storage, administration tools, support access, build systems and external integrations. Security gaps often sit outside the main request path. A diagram that shows only the browser, API and database will miss the places where credentials, exports, backups and operator privileges accumulate.
Use abuse cases alongside product use cases. “A customer downloads an invoice” is a use case. “A customer changes the invoice identifier and reads another tenant's invoice” is an abuse case. The second statement produces a verifiable authorization requirement.
Security principles
- Defense in depth: Prevent one missed check from becoming a complete compromise. Identity, network, application and data controls should fail independently.
- Least privilege: Grant the smallest action and resource scope needed for the shortest useful duration. Review machine identities as carefully as human administrators.
- Explicit verification: Evaluate identity, device or workload context, requested action and current policy at the boundary where access is granted. NIST SP 800-207 describes the architectural principles behind zero trust without requiring a specific product.
- Fail safely: When authorization, policy or dependency checks are unavailable, choose behavior based on the consequence of an incorrect allow. A blanket “fail open” or “fail closed” rule is usually too crude.
- Secure defaults: New accounts, services and environments should start with restricted access, logging and safe configuration. Exceptions should be deliberate and visible.
- Traceable change: A production permission or policy change should have an owner, reason, review path and audit event.
Identity and authentication
Authentication establishes an identity. It does not decide what that identity may do. Keep authentication, session management and authorization distinct so each can be tested and changed without hiding responsibilities.
OAuth 2.0 describes delegated authorization; OpenID Connect adds an identity layer. A session is how the application maintains continuity after authentication. JWT is a token representation. These can be used together, so they are not competing authentication methods. Use OpenID Connect Core and the current OAuth security best practice for protocol-specific requirements.
| Design dimension | Choice and consequence | Verification | |---|---|---| | Identity protocol | Local identity, federation or delegated access has different trust and recovery requirements | Validate issuer, client, redirect and protocol-specific response checks | | Browser session | A server-side session can follow an OIDC sign-in | Rotate session identity after authentication; test logout and account disable | | Access-token representation | Opaque tokens may use server lookup; JWTs may be validated locally | Validate intended audience, issuer, expiry and allowed cryptographic configuration | | Revocation | Server state, introspection, deny lists and short lifetimes offer different tradeoffs | Measure actual propagation and cached-decision behavior | | Operational dependency | Session stores and identity services can both fail | Exercise dependency loss without bypassing critical authorization |
A JWT can coexist with server-side state. A server-side session is not inherently unscalable, and its revocation is not necessarily instantaneous across caches. Select the design from the client's capabilities, threat model and required revocation behavior.
Session and token design
- Keep access tokens short-lived and narrowly scoped. A long-lived bearer token is equivalent to a reusable credential for anyone who obtains it.
- Rotate refresh tokens and detect reuse where the identity provider supports it.
- Bind administrative sessions to stronger authentication and shorter idle limits than ordinary customer sessions.
- Store browser session material in secure, HTTP-only cookies where appropriate. Do not expose credentials to client-side code without a clear need.
- Plan logout, revocation and account-disable behavior before launch. “The token eventually expires” is not sufficient for a terminated employee or compromised administrator.
- Log authentication events without logging passwords, secrets, complete tokens or sensitive identity assertions.
Authorization and tenant isolation
Select policy ingredients from the business rule, rather than choosing one acronym for the whole system.
| Rule to express | Useful policy ingredient | Required trustworthy input | |---|---|---| | Billing staff can request invoice exports | Role-based permissions | Current role membership | | Export belongs to the user's tenant and is not restricted | Attribute-based conditions | Server-derived tenant and authoritative resource state | | User owns or has been delegated access to a project | Relationship-based checks | Current ownership or delegation graph |
These ingredients can be combined. For an illustrative invoice-export action, require an authenticated subject, current billing permission, matching tenant, an exportable invoice state and any required approval. A support role does not receive implicit customer access.
| Subject / resource / action | Expected result | Why | |---|---|---| | Active billing member of tenant A exports an eligible A invoice | Allow within the approved field scope | All policy conditions hold | | Same subject changes the invoice ID to one in tenant B | Deny | Resource tenant differs | | Member removed from billing uses an older session | Deny after the defined revocation boundary | Current permission is absent | | Support operator without scoped delegation exports A's invoice | Deny | Support role alone is insufficient | | Approved export payload changes to include another tenant | Deny and require new review | Approval no longer matches the action | | Policy service unavailable for a sensitive export | Stop or queue under the approved fallback | Authority cannot be established |
"type": "flow", "title": "Authorize an invoice export using authoritative context", "steps": [ ], "caption": "A denial stops the export. The client may name an invoice, but cannot choose the authoritative tenant, role or approval decision." }} />
- RBAC: Assign permissions to roles. It is easy to explain, but role counts grow when teams encode every exception as a new role.
- ABAC: Evaluate attributes such as organization, data classification, region or resource state. It can express richer policy, but only if attributes are trustworthy and policy evaluation is observable.
- ReBAC: Decide access through relationships such as owner, member, parent organization or delegated administrator. It fits collaborative and hierarchical products but requires a clear relationship model.
Enforce object-level authorization on every request that addresses a resource. A valid session and a guessed identifier must never be enough. For multi-tenant systems, propagate a verified tenant context from the identity boundary and enforce it again at the data boundary. Database row-level security can provide another layer, but it does not replace correct application policy or safe privileged paths.
Create a policy test matrix. Each row describes an identity, tenant, resource state, action and expected decision. Include denied cases, cross-tenant access, support impersonation, suspended users and stale membership. Run these tests in CI and against the production authorization configuration before high-risk policy changes.
Data protection
Classify data before deciding how to protect it. At minimum, distinguish public data, internal operational data, customer-confidential data, credentials and regulated or highly sensitive data. The classification should drive storage, logging, export, retention and support-access rules.
Encryption needs an ownership model. Record which service owns each key, who can use or rotate it, what happens during key failure and how encrypted backups are restored. Customer-managed keys can support some enterprise requirements, but they also add availability and support consequences. Offer them when the product and operating model can carry those consequences.
Data deletion is a distributed workflow. A request may touch primary storage, indexes, caches, analytical stores, files, backups and downstream vendors. Define which copies are deleted immediately, which expire through retention, how the workflow is verified and what evidence support teams can provide without exposing more data.
Secrets and workload identity
Do not place secrets in source code, container images, build logs or client bundles. Use a managed secret store or workload identity mechanism and restrict retrieval by environment and service identity.
Rotation is only useful if applications can adopt the new credential safely. Design dual-key or overlapping-validity behavior where an integration cannot change atomically. Test revocation as well as rotation. A runbook that rotates a credential but cannot prove the old credential stopped working is incomplete.
Prefer short-lived workload credentials over static cloud access keys. Separate build identity from runtime identity. A build system usually needs permission to publish an artifact, not permission to read production customer data.
Secure delivery pipeline
The delivery pipeline is part of the production attack surface. Protect source control, build runners, artifact registries and deployment credentials as production systems.
"type": "flow", "title": "Keep release identity intact across the delivery boundary", "steps": [ ], "caption": "Record which source and build produced the deployed artifact. Verification needs an approved producer policy, not merely the presence of a signature." }} />
Set a release policy that distinguishes exploitable risk from scanner noise. Define which findings block a release, who can approve a time-bound exception and what evidence closes the exception. Track the deployed artifact and dependency versions so incident response can answer where a vulnerable component is running.
Logging, detection and privacy
Security logging should help reconstruct an event without creating a second sensitive-data store. Log identity, action, resource reference, decision, policy version, request correlation and outcome. Avoid request bodies, tokens and unnecessary personal data.
Protect audit events from ordinary application modification. Define retention based on investigation and contractual needs. Test detections by generating known events, such as a denied administrative action or suspicious credential reuse, then verify that the signal reaches the correct owner with enough context to act.
Useful detection coverage includes:
- repeated authentication or authorization failures with rate and identity context;
- unusual administrative access or privilege changes;
- secrets retrieved from unexpected workloads or environments;
- bulk data export or access patterns outside the normal operating window;
- security controls disabled, bypassed or returning errors;
- deployment of an unapproved or untraceable artifact.
Failure and incident design
Write failure behavior before the first incident. If the identity provider is unavailable, decide which read or operational paths remain safe. If the authorization service times out, define whether cached decisions may be used for that action at all. Bind any cache to subject, tenant, action, resource and policy version; establish expiry and revocation behavior. Do not allow a stale decision to silently preserve revoked administrative or cross-tenant access. If a security event pipeline is unavailable, decide whether the application can continue and how the visibility gap is recorded.
Prepare an incident runbook with containment actions that engineers can execute without improvising dangerous database changes. Include credential revocation, account suspension, feature isolation, artifact rollback, evidence preservation and communication ownership. Rehearse at least one scenario before launch and after material architecture changes.
Verification evidence before release
| Evidence | What it demonstrates | Accountable owner | |---|---|---| | Threat model | In-scope assets, boundaries and abuse cases considered | Architect and security owner | | Authorization matrix | Allowed and denied resource-level behavior tested | Service owner | | Artifact record | Deployed software linked to reviewed source and build | Platform owner | | Restore and revocation exercises | Recovery and containment under tested conditions | Operations owner | | Exception register | Residual risk, compensating controls and expiry visible | Authorized risk owner |
Do not use a passing scanner as the release decision. A scanner can identify classes of issues, but it cannot prove correct authorization, safe business workflows, complete data deletion or effective incident ownership.
Anti-patterns
- Security by obscurity: Hidden URLs and undocumented parameters are not access controls.
- Hardcoded secrets: Credentials in source, examples, images or logs spread faster than teams can rotate them.
- Front-end-only authorization: Hiding a button does not prevent a direct API request.
- Global administrator shortcuts: Shared support accounts destroy attribution and usually accumulate permanent access.
- Scanner-driven security: Tool output without threat context, ownership or verification creates queues, not security.
- Permanent exceptions: A risk acceptance without an expiry and accountable owner becomes an undocumented feature.
- One shared tenant context: Reusing cached or mutable tenant state across requests can create cross-tenant exposure.
Owned implementation sequence
The following sequence is a planning template. Scope and duration depend on the system; do not treat it as a delivery promise.
1. Architect and product owner: map and prioritize
- Document identities, sensitive assets, trust boundaries and external dependencies.
- Choose one critical user journey and write its abuse cases.
- Build the first authorization matrix and identify missing denied-case tests.
- Inventory secrets, privileged identities and production access paths.
2. Service and platform owners: close the highest-consequence gaps
- Fix direct object access and cross-tenant authorization gaps before cosmetic hardening.
- Move exposed or static credentials into a controlled secret or workload-identity path.
- Protect build and deployment permissions and record the artifact that reaches production.
- Add audit events for administrative and data-export actions.
3. Security and operations owners: make controls observable
- Create alerts for high-risk authentication, privilege and export events.
- Connect each alert to an owner and response action.
- Test credential revocation, account suspension and one containment path.
- Review logs for sensitive data and remove fields that do not support operations or investigation.
4. Service owner: establish the release gate
- Agree the release-blocking severity and exception process.
- Add threat-model and authorization evidence to the change-review template.
- Run a tabletop incident using the actual architecture and current on-call contacts.
- Record the next control improvements as owned engineering work, not an unprioritized security backlog.
Recovery and exception record
| Change or failure | Safe response | Evidence before reopening access | |---|---|---| | Policy release denies legitimate users | Restore a known compatible policy or a scoped fallback | Negative tests still deny prohibited access | | Credential is exposed | Revoke or constrain it and activate incident response | Replacement works; old credential is rejected | | Key change prevents reads | Use the tested key-recovery procedure | Authorized data access and backup restoration verified | | New permission grants excess access | Stop the grant and assess use during exposure | Scope and effects reviewed; correct policy deployed | | Audit path is unavailable | Apply the predefined action-specific degraded mode | Evidence gap recorded and collection restored |
Do not roll back to a compromised credential merely to restore service. A code or policy rollback cannot undo an export or disclosure. Preserve relevant evidence and assign the exposure assessment to the security and data owners.
Boundary / protected asset / owner:
Threat and consequence:
Control and authoritative inputs:
Allowed case / denied cases / outage case:
Test environment, version and result:
Recovery action and irreversible effects:
Residual risk, compensating control and approver:
Exception expiry and review trigger:Acceptance checklist
"The threat model includes support, build, backup and third-party paths", "Sessions, token formats and federation protocols are documented on separate dimensions", "Worked policy tests include cross-tenant, revoked-user and changed-approval cases", "Secrets and keys have rotation, revocation and recovery owners", "Artifact and policy versions can be traced to a production action", "Control outages and rollback were exercised without bypassing critical checks", "Residual risks have authorized owners, compensating controls and review triggers" ]} />
Limitations and next step
The tests demonstrate behavior for the modeled system and conditions. They do not prove that every threat is covered or establish compliance with a law or audit framework. Confirm applicability with the relevant legal, privacy and audit owners. Revisit the model when identities, data flows, deployment paths or business actions change.
Use the security hardening checklist to turn accepted design decisions into production configuration and evidence. Bring unresolved boundaries to security and compliance engineering.