Skip to content

Remote Identity attestation#130

Open
abergs wants to merge 4 commits into
mainfrom
remote-attestation
Open

Remote Identity attestation#130
abergs wants to merge 4 commits into
mainfrom
remote-attestation

Conversation

@abergs
Copy link
Copy Markdown
Member

@abergs abergs commented May 5, 2026

📔 Objective

This PR adds Remote Identity Attestation.

Today, when an remote client (agent) connects to your client, the protocol gives you no way to know which platform it's running on. It's Trust-on-first-use, without any confirmed identity.

This PR adds a draft spec for an optional attestation extension: the agent's platform signs a short-lived token during pairing, vouching for the clients's identity, and the client can show additional UI or enforce policy ("only accept connections from this platform") before serving any credentials.

The token is cryptographically bound to the exact Noise session, so it can't be replayed or redirected.
The token adds authenticated metadata about the requester without requiring user configuration (e.g. domain name of the remote, and possible other relevant metadata)

📸 Screenshots

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

abergs added 3 commits May 5, 2026 14:18
- Move jku from payload claim to COSE protected header (label 32, RFC 9596)
- Drop aud claim; session binding via external_aad already ties the token
  to a specific peer pair, making aud redundant
- Redraw overview diagram to show the three-party flow clearly
- Fix stale cross-references and RFC 8152 citation
- Add security note explaining why session binding subsumes both jti
  replay prevention and aud audience binding
- Add EAT alignment and custom claim vocabulary to open items
- Trim references to only those cited in the document body
Copy link
Copy Markdown

@iinuwa iinuwa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall; added things that might be useful additions, and one question about the evaluation of exp in the verification logic.

Comment thread remote-attestation.md Outdated
└──────── (3) fetch JWKS ──────────────────│ UserClient │
│ (verifies) │
└──────────────┘
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit: the main document presents the remote client on the right and the user client on the left. It might be worth swapping these to be something like this

UserClient                              Remote Client                   Vendor
    |                                         |                           | <Publishes signing keys>
    |  <--  establishes Noise tunnel  -->     |                           |
    |                                         | - requests attestation -> |
    |                                         | <--- signs attestation--- |
    |  <------- presents attestation -------- |                           |
    | -------------------- requests signing keys ---------------------->  |
    | <verifies attestation>                  |                           |
    |  <----- continues communication ------> |                           |

Comment thread remote-attestation.md
### 4.2 JWKS publication (issuer requirements)

The issuer MUST publish a JWKS (RFC 7517) at an HTTPS URL on the
same origin as `iss`. The token names this URL via the `jku` header
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"origin" typically refers to scheme + hostname (e.g. https://example.com/) in the web world, but below, we define iss to be equal to just a hostname. We should either use the full origin for iss, or use the term "hostname" here. Doesn't matter to me which.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iinuwa Yeah to be honest I sort of want to do away with jkuand just have iss that points to the public key. And we grab the hostname of iss as the Vendor.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I started thinking that would require a tiny bit more parsing on the client side, which might cause some issues, but they should be validating that that the jku hostname matches iss, so they have to do URL parsing regardless. On the other hand, splitting jku from iss means you need to make sure to validate that they match, which a client might forget to do and trust

{
  "iss":"app.com",
  "jku":"https://evil.com/jwks.json"
}

It'd be slightly abnormal to have a URL directly to the key in iss though. OIdC/OAuth2 handles this by having a .well-known address based on the issuer. In our case, the path can be anything. For that reason, I like splitting jku over iss, but I can see both sides.

Another alternative is following OIdC a .well-known path, which might not be a bad idea. Hosting .well-known on top-level domains can be annoying, but since the organization providing an agent is probably technically savvy, it can be worked around.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While abnormal, I still don't see any downsides with it, and you would need to do less comparisons as you point out.

I haven't fully considered if redirect impact things or not.

Well-known is not a bad idea, and may serve as a compliment but I worry about it being seen as more complex. A direct url is easy to reason about.

Comment thread remote-attestation.md
Implementations are free to express the same policy in any form
(config file, API, UI, code).

## 8. Security considerations
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another consideration is security UX for domains:

If the hostname is displayed in clients for TOFU attestations, the client SHOULD use some means for the user to securely display those to users to make appropriate trust decisions. These techniques can be borrowed from browsers, e.g.:

  • assist with detecting homograph attacks by rendering with Punycode orshowing warnings when non-ASCII characters are present
  • highlighting the registrable domain suffix according to PSL, while de-emphasizing subdomains underneath that
  • etc.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, agreed! Is there a complete list of advice to follow that we may want to add here?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a W3C or IETF standard, but I found this list of guidelines from Chromium: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/url_display_guidelines/url_display_guidelines.md.

Comment thread remote-attestation.md
2. `sub` equals `hex(SHA256(remote_client_pubkey))` of the peer that
completed the Noise handshake.
3. `iat` is within `[now - SKEW, now + SKEW]`.
4. `exp`, if present, satisfies `exp ∈ (now, now + MAX_LIFETIME]` and
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if signer's clock is ahead at all, all tokens will fail validation on this step:

now = 0
iat = 1
exp = 301
exp - iat = 300 <= MAX_LIFETIME = true
(now, now + MAX_LIFETIME] = (1-300]
301 ∈ (1-300] = False

I think we need to compare (iat, iat + MAX_LIFETIME] instead, which should be fine since we checked that the clock skew was acceptable, and the period between iat and exp is valid.

now = 0
iat = 1
exp = 301
exp - iat = 300 <= MAX_LIFETIME = true
(iat, iat + MAX_LIFETIME] = (1-301]
301 ∈ (1-301] = False

also works if the signer's clock is slow:

now = 30
iat = 0
exp = 300
exp - iat = 300 <= MAX_LIFETIME = true
(iat, iat + MAX_LIFETIME] = (1, 301]
300 ∈ (1, 301] = true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants