JanssenProject / JanssenProject/jans
feat(jans-auth-server): Jans Attestation Token Service
- Dominant language
- Java
- Stars
- 648
- Forks
- 174
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 110
Description
## 1. Summary
The Jans Attestation Token Service (ATS) verifies hardware and confidential-computing evidence and converts it into a short-lived, provider-neutral **Attestation Token**. The token describes the verified runtime state of a workload so that Cedarling, the Jans Auth Server, Trustee, KMS integrations, gateways, and applications can use that state in authorization and secret-release decisions.
ATS complements the Jans [Agent Identity via JWT-SVID design](https://github.com/JanssenProject/jans/blob/jans-auth-server-14988/docs/janssen-server/auth-server/oauth-features/agent-identity-jwt-svid.md). A JWT-SVID answers **who the workload is and whether it possesses its enrolled key**. An Attestation Token answers **where and in what security state the workload is running now**.
ATS is not an identity provider, OAuth authorization server, SPIFFE Workload API, or general policy decision point. Its job is narrower: challenge, verify, normalize, and sign attestation results.
## 2. Motivation
The JWT-SVID design establishes a hardware binding during agent enrollment:
1. A key is generated in a TEE, TPM, enclave, or other hardware security boundary.
2. Attestation evidence proves that the public key is hardware-resident.
3. Jans Auth Server binds that key to a client registration.
4. Later JWT-SVID requests require DPoP using the enrolled key.
This proves identity and continuing possession of the enrolled key. It does not necessarily prove that the current runtime still satisfies the required security posture. For example, key possession alone does not establish that:
- The current workload measurement is approved.
- Debug mode remains disabled.
- The firmware and Trusted Computing Base (TCB) remain current.
- The workload is executing on the expected TEE platform.
- The current image, configuration, GPU, or confidential VM is acceptable.
- Attestation was evaluated using the latest enterprise policy.
ATS closes this gap by supporting fresh or periodically renewed attestation independently of JWT-SVID issuance.
## 3. Design principles
### 3.1 Separate identity from posture
JWT-SVIDs remain stable identity credentials with short lifetimes. Attestation Tokens represent more volatile runtime posture and may have substantially shorter lifetimes.
### 3.2 Never let a workload attest itself
ATS runs outside the workload being evaluated. It may run in the same confidential Kubernetes cluster, but it must be isolated in a separate namespace, service identity, and administrative trust domain.
### 3.3 Delegate evidence verification
ATS should not initially implement raw AMD SEV-SNP, Intel TDX, TPM, NVIDIA, Azure, GCP, or AWS verification logic itself. It delegates to configured vendor, cloud, or RATS verifiers and validates their signed results.
### 3.4 Normalize without discarding provenance
ATS maps provider-specific evidence into a stable set of claims while retaining the evidence type, verifier identity, policy identifier, and measurement references needed for audit and troubleshooting.
### 3.5 Bind every result
An Attestation Token must be bound to the workload identity, the workload key, the evidence challenge, the intended audience, and the policy under which the evidence was evaluated.
### 3.6 Make tokens useful offline
Consumers should normally verify Attestation Tokens locally using cached ATS signing keys. Online introspection may be added for consumers requiring immediate status.
## 4. Scope
### 4.1 In scope
- Issuing single-use attestation challenges.
- Receiving EATs, quotes, or signed attestation results.
- Dispatching evidence to a configured verifier adapter.
- Validating verifier identity, signature, freshness, and response integrity.
- Evaluating an operator-defined attestation acceptance policy.
- Normalizing verified results into common claims.
- Issuing short-lived, signed Attestation Tokens.
- Publishing verification keys.
- Producing security and audit telemetry.
- Supporting Kubernetes and standalone deployment.
### 4.2 Out of scope
- Issuing JWT-SVIDs or OAuth access tokens.
- Assigning SPIFFE identities.
- Deciding application access by itself.
- Replacing Cedarling or another PDP.
- Replacing vendor attestation services.
- Releasing secrets directly in the initial implementation.
- Persisting raw evidence indefinitely.
- Providing an X.509 certificate authority or SPIFFE Workload API.
## 5. Architecture
```mermaid
flowchart TD
W["Confidential workload"] -->|challenge request| A["Attestation Token Service"]
A -->|nonce| W
W -->|evidence + key proof| A
A -->|verify evidence| V["Vendor or RATS verifier"]
V -->|signed result| A
A -->|Attestation Token| W
W -->|JWT-SVID + Attestation Token| C["Cedarling / relying party"]
A -->|verification keys| C
C -->|authorized release| K["Trustee / KMS"]
```
### 5.1 Components
| Component | Responsibility |
| --- | --- |
| Challenge service | Generates a cryptographically random, single-use nonce and records its expiry and requested context. |
| Evidence endpoint | Authenticates the caller, accepts evidence, and enforces request limits. |
| Verifier router | Selects an adapter based on evidence type, platform, tenant, and policy. |
| Verifier adapters | Call Azure Attestation, Intel Trust Authority, Trustee, AWS Nitro validation, Google Cloud attestation, NVIDIA, or other supported verifiers. |
| Result validator | Verifies the signed verifier response and binds it to the original nonce and workload key. |
| Claim normalizer | Produces a stable Jans claim model from provider-specific results. |
| Attestation policy evaluator | Determines whether the verified state meets a named operator policy. |
| Token issuer | Signs a short-lived Attestation Token with dedicated keys. |
| Key publisher | Publishes ATS verification keys and rotation metadata. |
| Audit publisher | Emits structured events without leaking sensitive evidence. |
## 6. Trust model
ATS is trusted to state that:
1. Evidence was evaluated by an accepted verifier.
2. The evidence was fresh and tied to a service-generated challenge.
3. The attested key matches the workload key identified in the request.
4. The verified measurements passed a named attestation policy.
5. The normalized claims faithfully represent the verifier result.
ATS does not state that the workload is authorized to perform a business action. That decision belongs to Cedarling or another policy decision point.
The relying party must independently validate:
- The Attestation Token signature, issuer, audience, and expiration.
- The relationship between the Attestation Token subject and JWT-SVID subject.
- The relationship between their key-binding claims.
- Whether the attestation policy and result are sufficient for the requested capability.
## 7. Protocol
### 7.1 Obtain a challenge
```http
POST /jans-attestation/restv1/challenges
Content-Type: application/json
Authorization: DPoP
DPoP:
{
"audience": "https://payments.example.com",
"policy_id": "production-agents-v4",
"evidence_type": "application/eat+cwt"
}
```
Example response:
```json
{
"challenge_id": "c_7f42c6",
"nonce": "V9g0...",
"expires_in": 60,
"accepted_evidence_types": ["application/eat+cwt"]
}
```
The challenge is single-use and bound to the requested audience, policy, caller identity, and key thumbprint.
### 7.2 Submit evidence
```http
POST /jans-attestation/restv1/tokens
Content-Type: application/json
Authorization: DPoP
DPoP:
{
"challenge_id": "c_7f42c6",
"evidence_type": "application/eat+cwt",
"evidence": "",
"audience": "https://payments.example.com"
}
```
ATS verifies that:
- The challenge exists, is unused, and has not expired.
- The authenticated subject and proof key match the challenge binding.
- The evidence contains or cryptographically covers the issued nonce.
- The evidence binds the same public key used by the workload.
- The configured verifier accepts the evidence.
- The verifier result satisfies the selected attestation policy.
On success, ATS consumes the challenge and returns an Attestation Token. Challenges are consumed atomically to prevent concurrent replay.
### 7.3 Error response
```json
{
"error": "attestation_failed",
"error_description": "The workload measurement is not accepted by the selected policy.",
"correlation_id": "8ba5..."
}
```
Production responses must not reveal detailed verifier diagnostics. Full details belong in access-controlled audit records.
## 8. Attestation Token
The initial format is a signed JWT. A future profile may use a CWT where constrained environments require it. The token is not a JWT-SVID and should use a distinct media type and `typ` value.
Example protected header:
```json
{
"alg": "ES256",
"kid": "ats-2026-09",
"typ": "at+jwt"
}
```
Example claims:
```json
{
"iss": "https://op.example.org/jans-attestation",
"sub": "spiffe://op.example.org/agent/3f9c",
"aud": "https://payments.example.com",
"iat": 1788888000,
"exp": 1788888060,
"jti": "at_91d2...",
"cnf": { "jkt": "9XKt..." },
"attestation": {
"result": "pass",
"evidence_type": "application/eat+cwt",
"tee": "sev-snp",
"verifier": "azure-attestation",
"measurement": "sha384:...",
"debug": false,
"tcb_status": "current",
"policy_id": "production-agents-v4",
"policy_version": 12,
"verified_at": 1788887998
}
}
```
### 8.1 Required claims
| Claim | Purpose |
| --- | --- |
| `iss` | Identifies the ATS trust domain. |
| `sub` | Identifies the attested workload, normally using its SPIFFE ID. |
| `aud` | Restricts use to the intended consumer or resource. |
| `iat`, `exp` | Bounds the freshness window. |
| `jti` | Supports correlation and optional replay detection. |
| `cnf.jkt` | Binds the result to the workload key. |
| `attestation.result` | Indicates that evidence passed the named policy. Failure tokens are not issued. |
| `attestation.evidence_type` | Records the evidence format. |
| `attestation.tee` | Identifies the verified execution technology. |
| `attestation.verifier` | Identifies the verifier used. |
| `attestation.policy_id` | Identifies the acceptance policy. |
| `attestation.policy_version` | Makes the evaluated policy version auditable. |
| `attestation.verified_at` | Records when verification completed. |
Provider-specific claims should appear only in an explicitly namespaced extension object. Raw evidence should not be embedded in the token.
### 8.2 Lifetime
The default lifetime should be 60 seconds, configurable per attestation policy with a conservative maximum. A consumer may require a smaller maximum token age than the token's remaining lifetime.
## 9. Relationship to JWT-SVID
| Property | JWT-SVID | Attestation Token |
| --- | --- | --- |
| Primary assertion | Workload identity | Current runtime posture |
| Subject | SPIFFE workload identity | Same SPIFFE workload identity |
| Durable anchor | Enrolled hardware-bound key | Fresh evidence and verifier result |
| Proof | DPoP demonstrates key possession | Nonce-bound evidence demonstrates current attestation |
| Typical lifetime | 5–15 minutes | Seconds to a few minutes |
| Issuer | Jans Auth Server | Jans Attestation Token Service |
| Main consumer | Services authenticating the workload | PDPs, secret brokers, and high-assurance services |
Consumers should require the following equality checks:
```text
attestation_token.sub == jwt_svid.sub
attestation_token.cnf.jkt == jwt_svid.cnf.jkt
attestation_token.aud == protected_resource
```
A JWT-SVID must not be treated as evidence of current platform posture merely because its key was attested during enrollment.
## 10. Authorization integration
ATS provides verified facts; Cedarling determines their meaning for a capability.
Example conceptual Cedar inputs:
```json
{
"principal": "spiffe://op.example.org/agent/3f9c",
"action": "payments::Action::\"transfer\"",
"resource": "payments::Account::\"merchant-7\"",
"context": {
"identity_key_bound": true,
"attestation_result": "pass",
"tee": "sev-snp",
"debug": false,
"tcb_status": "current",
"attestation_policy": "production-agents-v4",
"attestation_age_seconds": 8
}
}
```
An application may accept a JWT-SVID alone for low-risk operations while requiring a fresh Attestation Token for high-impact capabilities such as releasing secrets, accessing regulated data, or transferring funds.
## 11. Deployment
ATS should run as a stateless service in the customer's control plane, normally as a Kubernetes deployment in a dedicated namespace such as `jans-trust`. It should not run inside the workload it attests.
Recommended deployment controls:
- Dedicated Kubernetes service account and workload identity.
- Network policy allowing only required verifier, KMS, telemetry, and consumer paths.
- Signing keys held in KMS or HSM; private keys never stored in application configuration.
- Separate signing keys from OIDC, JWT-SVID, and other Jans token families.
- Horizontally scalable API pods.
- A shared, low-latency challenge store supporting atomic consume operations.
- Configuration and measurement allowlists delivered through signed, versioned policy bundles.
- Optional confidential-computing deployment for ATS itself, without making that a prerequisite for the MVP.
### 11.1 Availability behavior
ATS fails closed: it does not issue a token if the verifier, challenge store, signing service, or policy evaluation is unavailable. Existing Attestation Tokens remain locally verifiable until expiration.
## 12. Security considerations
### 12.1 Replay
Use unpredictable, short-lived, single-use nonces. Bind the nonce to the caller, key, audience, evidence type, and policy. Consume it atomically.
### 12.2 Relay and cuckoo attacks
Evidence must bind the attested workload key and nonce. ATS must compare that key with both the authenticated caller's proof key and the `cnf.jkt` placed in the resulting token.
### 12.3 Time-of-check/time-of-use
Attestation cannot guarantee that runtime state remains unchanged indefinitely. Keep token lifetimes short and let high-risk policies constrain maximum attestation age.
### 12.4 Verifier compromise
Configure explicit verifier trust anchors and accepted algorithms. Record which verifier produced each result. Support rapid verifier removal without changing the stable normalized claim contract.
### 12.5 Policy rollback
Attestation policies must be versioned and protected against rollback. Tokens include both policy identifier and version.
### 12.6 Information disclosure
Measurements and platform identifiers may reveal deployment details. Apply audience restriction, minimize claims, avoid raw evidence in tokens and logs, and encrypt transport end to end.
### 12.7 Algorithm and key separation
ATS signing keys are dedicated to Attestation Tokens and published independently. Verifiers must reject keys intended for another token family.
## 13. Configuration model
Illustrative configuration:
```yaml
issuer: https://op.example.org/jans-attestation
tokenLifetimeSeconds: 60
maximumTokenLifetimeSeconds: 300
signingAlgorithms:
- ES256
challenge:
lifetimeSeconds: 60
store: redis
verifiers:
- id: azure-attestation
evidenceTypes:
- application/eat+jwt
endpoint: https://example.attest.azure.net
trustAnchorRef: azure-attestation-jwks
- id: trustee
evidenceTypes:
- application/eat+cwt
endpoint: https://trustee.jans-trust.svc.cluster.local
policies:
source: signed-bundle
refreshSeconds: 60
keys:
provider: kms
keyRef: jans-ats-signing-key
```
Secrets, credentials, and private key material must be referenced through the deployment secret mechanism rather than embedded in this configuration.
## 14. Observability and audit
ATS should emit metrics and OpenTelemetry traces for:
- Challenges issued, expired, consumed, and replayed.
- Verification latency and outcome by verifier and evidence type.
- Policy evaluation outcome by policy identifier and version.
- Token issuance count and latency.
- Verifier availability and error rate.
- Signing and KMS latency.
Audit events should include `correlation_id`, subject, audience, key thumbprint, verifier, evidence type, policy identifier and version, result, measurement digest when permitted, and issued token `jti`. They must not include raw evidence, private keys, bearer tokens, or DPoP proofs.
## 15. Administrative API
The MVP may use static configuration. A later administrative API can manage:
- Verifier definitions and trust anchors.
- Evidence-type routing.
- Attestation policies and measurement allowlists.
- Token lifetime limits.
- Signing-key rotation.
- Tenant-specific mappings.
All administrative changes require strong authentication, authorization, versioning, and audit events. Policy publication should support staged rollout and rollback to a previously valid, signed version.
## 16. Implementation phases
### Phase 1: Enrollment verifier extraction
- Implement a standalone service façade over one verifier.
- Accept the enrollment-time evidence used by the JWT-SVID design.
- Return a normalized internal verification result to Jans Auth Server.
- Establish KMS-backed service identity, telemetry, and error handling.
This phase improves separation of concerns but does not yet issue an Attestation Token.
### Phase 2: Runtime Attestation Token MVP
- Add challenge and token endpoints.
- Bind evidence to JWT-SVID subject and DPoP key.
- Issue audience-restricted JWT Attestation Tokens.
- Publish dedicated verification keys.
- Integrate tokens as Cedarling context.
### Phase 3: Multi-provider verification
- Add verifier routing and adapters.
- Define the stable normalized claim vocabulary.
- Add provider-specific extension namespaces.
- Add signed, versioned attestation policies.
### Phase 4: Secret release and federation
- Integrate Trustee and cloud KMS release conditions.
- Add online introspection where required.
- Define cross-domain ATS trust and issuer allowlists.
- Add high-assurance conformance tests and interoperability profiles.
## 17. Open questions
1. Should the token use a Jans-defined `at+jwt` type initially or profile an emerging standard Attestation Result format?
2. Should ATS require a JWT-SVID for all runtime requests, or also support OAuth access tokens and mutually authenticated workloads?
3. Which normalized claims are portable across SEV-SNP, TDX, Nitro, TPM, confidential GPU, and platform-specific evidence?
4. Should measurement acceptance be evaluated by the external verifier, ATS, or both?
5. What maximum attestation age should apply to each risk tier or GovOps capability?
6. Should ATS expose introspection, or are short lifetimes and local verification sufficient?
7. How should federated organizations express trust in another operator's ATS policies and verifier set?
## 18. Decision summary
For the JWT-SVID MVP, Jans Auth Server can call a verifier directly during enrollment; a separate ATS is not mandatory. ATS becomes valuable when Janssen needs continuous or on-demand runtime attestation, multiple verifier integrations, policy-consumable posture claims, or attestation-gated secret release.
The recommended long-term model is therefore:
- **Jans Auth Server issues identity:** JWT-SVID.
- **ATS issues verified runtime posture:** Attestation Token.
- **Cedarling combines identity, posture, authority, and transaction context:** authorization decision.
- **Trustee or KMS enforces authorized secret release:** runtime effect.
Contributor guide
Assessment
This issue has not been assessed yet.