Compliance & Privacy · 2026-03-29
SOC 2 Type II for Identity APIs: The Audit Controls Few Will Tell You About
By J. W. Bouckaert
SOC 2 Type II for identity-layer APIs
Most SOC 2 guidance stops at the Trust Services Criteria categories: Security, Availability, Processing Integrity, Confidentiality and Privacy. Those categories apply to identity-layer APIs, but they say little about the controls such an API needs. An identity platform issues cryptographic assertions about who a person is, whether their device or number shows signs of compromise, and whether an AI agent is authorized to act for them.
A SOC 2 Type I report covers the design of controls at a point in time. A Type II report covers whether those controls operated effectively over an observation period, commonly 3 to 12 months. For identity APIs that process carrier signals, issue verifiable credentials and run passkey ceremonies, the operating evidence is what a reader of the report relies on.
This article covers five control areas for identity-layer APIs and the evidence an auditor can ask for in each.
Five control areas for identity APIs
SOC 2 examinations use the AICPA Trust Services Criteria (TSC). The criteria are written in general terms, so the service organization decides how to meet them. For an identity API, five areas carry most of the weight:
| Control area | TSC mapping | Identity API requirement |
|---|---|---|
| Tamper-evident audit logging | CC7.2, CC7.3 | API calls, mutations and administrative actions recorded where clients cannot change them |
| Key management | CC6.1 | Keys created, stored, rotated and retired under a documented procedure |
| Tenant isolation | CC6.1, CC6.3 | Access to one tenant's data limited to that tenant, enforced below the application where possible |
| Credential lifecycle | CC6.2, CC6.3 | Credentials issued with a recorded scope, with defined validity and a revocation path |
| Access scope enforcement | CC6.1, CC6.3 | API keys, agent delegates and user sessions limited to the operations they need |
Each of these areas is easier to build in from the start than to retrofit.
Control 1: Tamper-evident audit logging
Auditor expectations
CC7.2 covers monitoring system components for anomalies and analyzing them to determine whether they are security events. CC7.3 covers evaluating security events to determine whether they are incidents. For an identity API, that means signal ingest, credential issuance, key rotation, agent delegation and administrative changes should each produce an audit record.
Audit records should be append-only for every client role. No tenant user or API key should be able to modify or delete an entry after it is written.
In practice
An audit log schema for an identity API commonly captures these fields:
| Field | Type | Purpose |
|---|---|---|
tenant_id | UUID | Tenant isolation for multi-tenant platforms |
actor_id | UUID (nullable) | The authenticated user, API key or system process |
actor_type | Enum | For example user, system, api_key, agent_delegate |
actor_ip_hash | Text | Keyed HMAC-SHA-256 digest of the source IP under a server-held pepper; the raw address is never stored |
action | Text | Machine-readable action identifier, such as key.rotate or credential.issue |
resource_type | Text | The resource acted on, such as api_key |
resource_id | Text | Specific resource identifier |
changes | JSONB | Before and after state for mutations |
result | Enum | For example success, failure, denied |
error_message | Text | Failure reason, sanitized, with no stack traces |
created_at | Timestamptz | Server-side timestamp |
created_at should be set by the server. A client-supplied timestamp lets anyone holding a stolen API key backdate their activity.
Enforcing append-only records
Two database mechanisms keep client roles from changing audit rows:
- Grants: client roles get no
UPDATEorDELETEprivilege on the audit table, enforced at the PostgreSQL role level.
- Row-level security: policies on the audit table allow
SELECTto the roles that may read it and define noUPDATEorDELETEpolicy.
A database owner or service role can still bypass both. Hash-chaining each row to the previous one, and signing periodic checkpoints of the chain, makes a change by such a role detectable. An auditor can ask for the role configuration and for the output of the chain verification.
Control 2: Key management
Auditor expectations
The CC6.1 points of focus include protecting encryption keys during generation, storage, use and destruction. An auditor will look for a documented procedure for each key type and evidence that the procedure was followed during the period.
Rotation design
Key types in an identity API differ in how they can rotate:
| Key type | Rotation approach |
|---|---|
| Tenant API keys | Issue a new key, move clients to it, then revoke the old key |
| Credential signing keys | Publish the new public key before signing with it, and keep the old public key available for as long as credentials signed with it must verify |
| Session keys | Ephemeral per session, destroyed on teardown |
| Keys derived from a master secret | Rotating the master changes every derived key, so credentials signed before the change stop verifying unless the old keys are kept |
When a signing key rotates, verifiers must still be able to check what the old key signed. A rotation that withdraws the old public key at once causes verification failures for anything signed before the change.
Evidence the auditor reviews
- Rotation records: timestamped audit entries showing when each key was rotated, by whom, and whether the rotation was scheduled or manual.
- Procedure: the documented intervals and overlap periods, and the code or configuration that implements them.
- Failure handling: evidence that a failed rotation, such as a write error during the key swap, cannot leave the system with no active key.
Control 3: Tenant isolation
Auditor expectations
For a multi-tenant identity API, CC6.1 and CC6.3 cover limiting access to one tenant's data to the users authorized for it. Enforcement below the application layer reduces the impact of an application bug.
Limits of application-layer isolation
A common pattern filters tenant data in application code:
// Application-layer isolation
const events = await db.query(
"SELECT * FROM events WHERE tenant_id = $1",
[currentTenantId]
);
This holds until a developer forgets the WHERE clause, a new endpoint skips the middleware, or an ORM generates an unfiltered query. One missing filter can expose every tenant's data.
Database-layer enforcement
PostgreSQL row-level security (RLS) filters every query against a protected table for the roles the policy covers, whatever the application sends. An example policy that ties rows to the tenants a signed-in user belongs to:
-- Database-layer tenant isolation
ALTER TABLE events ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_members_read ON events
FOR SELECT
TO authenticated
USING (tenant_id IN (
SELECT tenant_id FROM tenant_members WHERE user_id = current_user_id()
));
With this policy, a query from a signed-in user without a WHERE tenant_id = ... clause returns only rows for that user's tenants. Server code that runs as a role which bypasses RLS still needs its own tenant filter, and that filter needs tests.
Isolation verification
An isolation test can:
- Authenticate as a user of Tenant A
- Run an unfiltered
SELECTon a tenant-scoped table - Confirm only Tenant A's rows come back
- Attempt an
UPDATEon a Tenant B row by ID - Confirm zero rows change
Control 4: Credential lifecycle management
Auditor expectations
CC6.2 covers registering and authorizing users before issuing credentials, and removing credentials when access is no longer authorized. CC6.3 covers authorizing, modifying and removing access. For identity APIs, credentials include API keys, verifiable credentials, cached proofs and agent delegation tokens.
Each credential type needs four lifecycle properties:
| Property | Requirement |
|---|---|
| Issuance | Recorded in the audit log with issuer, scope and expiry |
| Expiration | A defined maximum validity, or a documented reason for none |
| Revocation | A single API call or dashboard action, with the time it takes effect documented |
| Re-attestation | Triggered by risk signals such as a SIM swap or a key compromise |
Time-bounded credentials
SOC 2 does not set expiration periods. The organization sets them in its own policy, and the auditor tests whether the system followed that policy during the period. A credential with no expiry needs a documented compensating control, such as periodic review and revocation on offboarding.
Revocation reach
Revocation has to reach every component that accepts the credential:
- The API layer, which rejects requests made with a revoked key
- The credential status endpoint, which returns the revoked status in its status list
- The agent trust engine, which deactivates delegation tokens
- The cached proof store, which marks proofs invalid
A component that keeps accepting a revoked credential is a gap an auditor can find by testing it.
Control 5: Access scope enforcement
Auditor expectations
CC6.1 covers logical access security over protected information assets. For identity APIs, API keys, user sessions and agent delegates should each be limited to the operations they need.
Scoped API keys
An identity API key should carry scopes, and each endpoint should check for its scope. PasskeyBridge API keys carry scopes such as these:
| Scope | Operations permitted |
|---|---|
ingest | Submit signals to the ingest endpoint |
events, metrics | Read the tenant's Prometheus-format metrics export |
vc_issue | Issue credentials and create OID4VCI offers |
vc_verify | Verify presentations and build OpenID4VP requests |
vc_revoke | Revoke, suspend and reinstate credentials |
spatial | Submit spatially bound attestation data |
scim | SCIM provisioning |
okta_hooks | Okta event hook ingestion |
A request whose key lacks the endpoint's scope is refused with HTTP 403 and the reason missing-scope. A key scoped only to ingest cannot issue credentials.
Agent scope narrowing
Agent delegates add a second layer. In PasskeyBridge, a tenant admin creates a delegate with a list of scopes, and every verify call checks the requested scope against that list. Each delegate also carries a trust score that falls on signals such as velocity spikes, error bursts and scope violations:
Trust 0.7 or above -> full delegated scopes
Trust 0.4 to 0.7 -> read-only scopes
Trust floor to 0.4 -> verify only
Below the floor -> delegate deactivated (default floor 0.2)
The original scope list is kept, and the time and reason of each narrowing are recorded with an audit entry. A tenant can set its own thresholds.
SOC 2 does not mention agents. A control like this is evidence that access changes with risk signals between manual access reviews.
The observation period
In a Type II examination, the auditor tests how controls operated during the period through samples of logs, rotation records, access changes and credential events.
- Audit logs must cover the period. Logs deleted before the examination ends cannot serve as evidence.
- Rotations must follow the stated schedule. A policy of rotating every 90 days, with no rotation in 180 days, is an exception.
- Isolation failures get reported. An incident of cross-tenant exposure during the period can appear in the report even after it is fixed.
- Expirations must be enforced. A credential still accepted after its
expires_atis a failed lifecycle control.
PasskeyBridge's audit log
PasskeyBridge's audit log records the fields in the table above, with additional actor types and results. Its row-level security allows tenant admins to read their own tenant's rows and gives client roles no write path. Each row is hash-chained, and the chain is checkpointed every five minutes with HMAC-SHA-256 and an ML-DSA-65 signature, anchored to the latest NIST Randomness Beacon pulse. The one sanctioned change to chained rows today, the 90-day retention purge of events, is written to the chain as an amendment record, and chain verification reports any other change as tampering.
PasskeyBridge is preparing for SOC 2 and does not hold a SOC 2 report.
Consequences for your identity stack
If you are building or evaluating an identity API, treat these five areas as design requirements. Moving from a mutable log to an append-only one takes a migration. Moving from application-layer filtering to database-enforced isolation takes changes across the data access layer.
Further reading
- AICPA Trust Services Criteria (2017, revised points of focus 2022): the criteria SOC 2 examinations use.
- SOC 2 Readiness for Identity Startups in 2026: our guide to SOC 2 readiness in the identity space.
- The Zero-Knowledge Audit Trail: Proving Provenance Without PII: keeping an audit trail without storing personal data.
- The CISO's Guide to Zero-PII Identity Verification: compliance mapping for GDPR Art. 25 and CCPA §1798.100.
- NIST SP 800-53 Rev. 5: Security and Privacy Controls: the federal control catalog, with published mappings to the TSC.
- PostgreSQL Row-Level Security Documentation: reference for database-enforced tenant isolation.