The Missing Foundation of Non-Human Identity
Traditionally, authentication has been framed in terms of “something you are,” “something you know,” and “something you have.” For a long time, human users on the web logged in using an email address (something you have) and a password (something you know). Two-factor authentication layered on additional “somethings” to strengthen that model. Biometrics introduced “something you are.”
On top of that, organizations can rely on human process like onboarding, background checks, and government documents to establish and reinforce who a person is. These processes do a lot to smooth out the rough edges of issueing and maintaining identity at a large scale for sensitive systems.
In other words, people and our organizations came with some built-in identity primitives and processes that the software industry has taken advantage of at the application layer. The effect of this is that focus and effort up until this point has almost entirely been on authentication: ways to prove those innate identity attributes of a human utilizing all the nice out of band organizational process where convenient.
Machine identity—non-human identity, NHI—does not have that luxury. Machines don’t have memorized passwords or fingerprints. They authenticate only by presenting artifacts we’ve provisioned or embedded beforehand, so the problem looks different from the start. Historically this gap wasn’t a source of pain because the number of machines was tiny relative to the number of humans interacting with them. Machine identity stayed in a “good enough” holding pattern. The push from cloud computing, containers, microservices, and edge functions has changed that a bit. Efforts like SPIFFE/SPIRE began emerging to solve workload identity in specific environments.
Now we are at the precipice of something much larger. We will soon have orders of magnitude more machine identities than human ones. Machines that decide for themselves what actions to take—and then go attempt them—are about to multiply across the internet. AI agents won’t be monolithic services with clear boundaries; they’ll be swarms of small, semi-autonomous entities doing work on our behalf. The number of unique identities is going to skyrocket.
The problem with machine identity is that the industry has been working backwards from authentication to identity, as if identity and authentication were the same thing (because they mostly are for human users). Because we understand authentication so well, it became the natural place to start. Many niches have solved non-human identity for their own environments, but almost all of this work is anchored in authentication patterns or workload-specific assumptions. Even thoughtful emerging work like WIMSE still centers on credentials and usage patterns rather than the deeper structure of where machine identity actually comes from.
As I’ve been digging through this space over the last couple of months, I’ve found myself unsatisfied. I’m a top-down thinker; I need a clean conceptual model before I can make sense of the details. I feel adrift in a sea of NHI minutiae. If all I needed was to stick identity on Kubernetes pods, SPIFFE/SPIRE would probably be enough.
I’m trying to build an identity and authorization platform that can handle any kind of machine, and for that I need a foundation broader than any single ecosystem. I want my webapps, kubernetes pods, AI agents, microservices, and edge functions to all have identity so I can clearly define how they are allowed to interact. I need a clear definition of what machine identity is before I can use it as a foundation instead of a byproduct.
We need a clear, foundational model of machine (non-human) identity that is grounded in where identity originates and not just in the process of authenticating it.
At its core, identity is just a stable, unique set of bytes that one entity uses to identify itself to others without confusion. The simplest version is an opaque secret, but that’s brittle because anything that gets a copy can impersonate the identity perfectly. A keypair is much better. The private key can be kept safe; the public key can be freely shared. With asymmetric cryptography, the entity can prove itself. That alone is enough to ground identity, but you can extend it by signing metadata—names, attributes, context—and presenting that bundle to others. You can also use that signed bundle alone, assuming it was signed and issued by an authoritative source and securely provisioned.
This leads to what I think is the right model. When assigning identity to any machine, you’re really answering two structural questions: where does this identity originate, and what privileges does it begin with? Once you’ve answered those, you still need to decide how that identity will live and change over time—its lifecycle. The first question is the identity origin or bootstrap point. The second is what I call the initial policy state. The lifecycle dimension is identity continuity.
When you put these pieces together, you can describe any machine identity system.
I’ll start with identity origin, because that is the bedrock.
Identity origin
When you point at a machine or workload and say “this is service A” or “this is device 12,” that statement isn’t magic. It’s anchored in something you’ve decided to trust. Maybe the machine holds a private key. Maybe your cloud provider signs a blob about the environment. Maybe your manufacturing line burned in a certificate at the factory. In all cases, something upstream is vouching for that identity.
Identity must come from somewhere. More specifically, there must be some root from which trust flows: a safe starting point from which you can cryptographically derive new identities.
Working backwards from the machine you are creating can lead to the maddening “turtles all the way down” problem. You have a secret to identify your machine but in order to safely store that secret, you need to encrypt it at rest. So how do you store that secret? Where is the blasted bottom turtle? A good talk on this problem can be found here.
The truth is that with isolation mechanisms, trusted hardware, secrets managers, or building on top of platforms that encrypt at rest, we can convince ourselves to an acceptable degree that in-memory code can operate on secrets safely enough that a perfect bottom turtle isn’t necessary—or rather that whatever we’ve built upon has implemented the bottom turtle.
From there, identity for machines emerges in one of three ways: self-proven, attested, and asserted.
Self-proven identity
A self-proven identity is one in which the entity produces cryptographic proof that it is itself. Effectively, it tells others who it is so that the others can uniquely identify it going forward. The entity vouches for itself.
This form of identity shows up constantly in lower layers of systems like SSH keys, TLS connections without certificates, and peer-to-peer protocols. More recently it appears in application-layer features like passkeys.
If a device can prove it holds the private key corresponding to a public key you’ve seen before, you accept that identity. This is identity with nothing attached, just the ability to prove possession. This form of identity starts with zero meaning or context. For things like TLS or peer-to-peer protocols, that is fine as it is just used to determine that the entity you started talking to is the same entity you are still talking to.
To give this identity meaning though, you need some other mechanism. In the passkey example inside a corporate environment, you might send a second-factor challenge to a known corporate email. Once the passkey proves it controls that email address, the organization can derive meaning: a name, a team, a role. The identity itself is bare; the meaning comes from somewhere else.
Self-proven identities are also tricky to establish since you need to either trust on first use (TOFU) or have an out-of-band exchange that establishes trust with the other party. Human beings and our organizations trust one another through a long-running body of work or a stand-in like a credit score. Maybe a self-proven machine system could be built similarly.
If your machine is operating in an environment you trust, you aren’t starting from nothing. You can often use that environment to securely create a new identity: attested identities.
Attested identity
An attested identity emerges when something you trust vouches for the environment in which the machine is running. You don’t control the underlying compute, but you trust the entity who does. The platform vouches for the identity.
This is the world of cloud instance metadata documents, TPM attestation, hardware-backed security modules, and mobile devices with tightly controlled secure enclaves. The attester holds a keypair or emits signed metadata that you trust. You verify that signature and use it as the root of identity. In this model, the cloud provider or hardware manufacturer effectively becomes your bottom turtle.
Another example of attestation is a human provisioning a machine. Ideally, the human should have some keypair of their own to attest the new machine identity with. This gives the machine identity a proper, provable cryptographic lineage. It’s also possible to lean on human systems like organizational process to safely provision a small number of machines (or however many your process can sustain).
The limitation is that you usually either can’t subdivide or scale this identity safely. The attestation speaks about the whole environment; humans can only provision so many machines. If you want unique identities per Kubernetes container running inside an attested VM, you don’t have much to work with unless you build an entire secure orchestration stack on top. You can’t simply take the attestation blob and add “this is container foo-7.” Containers can lie.
Attestation is a powerful starting point to create a trusted root identity from which to derive more. This leads to the final pattern.
Asserted identity
An asserted identity is one that emerges from something you directly control and trust enough to embed a root credential. This entity can then assert new identities. The issuer vouches for the identity.
The best real-world example is IoT manufacturing. You set up a secure process that generates device identities and installs them at manufacturing time using a carefully protected keypair. Another example is a CI/CD system that receives its own identity through attestation and then asserts new identities for the jobs it runs.
A key characteristic of asserted identities is that the chain of trust is downward: root → delegates → subdelegates. Delegate identities should not inherit all the root’s rights, just the subset appropriate to their function. They also shouldn’t be given rights to do something that the root should never be able to do. Because the root is effectively creating the new delegate identity, the root always has the power of that delegate, whether or not it uses it.
Initial policy state
With those three identity origins understood, the next question is what privileges an identity begins with the moment it’s established. Privileges don’t start arbitrarily; they start in one of three states:
- Zero default privileges
- A minimal baseline every identity gets
- Explicit privileges bound to identity at issuance
Zero default
Some identities begin with zero privilege at all. SSH keys begin life like this. A raw keypair has no meaning until someone adds its public key to the authorized_keys file on a server. Passkeys begin with no access to anything until they’re registered. IoT devices before enrollment and SSO identities before role assignment both fit the same pattern. Identity exists, but nothing in the system authorizes it yet.
To gain permissions from absolute zero, you either need manual intervention like a human adding an SSH key to authorized_keys, or some other “god-like” orthogonal system or process that intervenes to give capability after the identity has been made, since the identity has no capability to do so itself.
Minimal baseline
Other identities begin with a minimal default baseline—just enough privilege to let the entity participate in the system or phone home or identify itself. In a distributed system, this might allow a new node to gossip its existence to neighbors, perform a health check, or request configuration. In IoT, it might be the ability for a device to report that it came off the manufacturing line. The identity doesn’t get meaningful permissions, only a narrow set needed for bootstrapping more.
Another way to look at this is to define the set of permissions that everything in the system should be able to do. This is your minimal baseline.
Explicit privileges
Finally, some identities begin with explicit privileges bound to them at creation. This can only happen when the identity carries enough information—names, roles, structured metadata—to bind policy to it directly. Also, depending on the identity’s origin:
Self-proven identities: cannot have any explicit privileges set unless your system allows trusting a new identity to assert its identifiers (name, role, etc.) or you have a second factor to gain that information.
Attested identities: are unlikely to have explicit privileges set at time of creation. Because you are relying on another party’s attestation, you likely have no control over the identifiers and metadata presented. Preconfiguring policy using structured metadata you don't control will likely lead to a brittle system.
Asserted identities: you fully control the root identity and how new identities are issued, including their metadata. Because of this control, you can create mappings from that metadata to explicit policy that is defined before the identity emerges in the system. A CI/CD job identity might immediately be allowed to fetch dependencies or publish artifacts. A workload identity issued from a parent might inherit a precise subset of the parent’s privileges. IoT devices often receive identities whose serial number or type implies clear policy constraints.
Putting identity origin together with initial policy state gives us a nearly complete way to reason about machine identity. It at least gets us most of the way to determining how to build or implement initial identity in your system. The final piece, identity continuity, describes the model for the lifecycle of an identity and completes the picture.
Identity continuity
The final dimension of the model is how the identity exists over time. Unlike humans, whose identity is generally continuous (you are the same person today as you were yesterday), machine identity falls into two distinct continuity models: disposable and durable.
This isn’t a different kind of identity; rather it’s a lifecycle property that builds on top of the origin and initial policy state. It answers the questions of how and when an identity is rotated or expired.
Disposable identity
A disposable identity is one that is tightly coupled to the ephemeral existence of the workload itself. The identity is never rotated; it is replaced together with a new instantiation of the workload. There are two primary reasons why an identity might be treated as disposable: either the workload is sufficiently short-lived, or the process of minting an identity and re-deploying the workload is sufficiently easy.
When the credential expires or the software needs to be updated, you don’t transform it. You destroy the machine (the container, the function, the job) and spin up a new one with a fresh identity derived from its origin.
This is the likely state for asserted identities in modern cloud architecture, like CI/CD jobs or auto-scaling groups. You can even treat a deployed webapp as disposable since re-deploying is often trivial. For instance, you can create a root identity to issue your webapp’s identity as part of CI/CD, assign an expiration of 24 hours, and automate a new deployment every 24 hours.
The benefit is that there is no complex exchange protocol to manage. If an identity is compromised, your remediation is simply to kill the workload and recreate it with a new identity from a non-compromised root.
Durable identity
Durable identity represents an entity that persists longer than its cryptographic credentials. The “machine” remains, but its keys or signed metadata must change. This introduces the problem of continuity: how does the system know that the entity holding new credentials B is the same entity that held old credentials A?
This requires a mechanism to extend trust. Depending on the identity origin and other factors unique to your system, you need to determine how to exchange identity for a fresh one and ensure that the rest of your system trusts the new one and stops trusting the old.
For self-proven identities, this is the hardest path. The machine must sign its new public key with its old private key, effectively saying, “I used to be key A, I am now key B.” This is a “trust on update” pattern.
For attested or asserted identities, the machine returns to its origin point of trust to request a new credential. It must prove it is still the same identity and provide any necessary materials that were needed to establish that trust in the first place.
Durable continuity is necessary for IoT devices, hardware security modules, long-running database servers, and anything where “re-deploying” isn’t an option. It may also be necessary where building and maintaining an exchange protocol is easier or cheaper than re-provisioning, or where user experience requires it like in long-running web sessions where OAuth refresh tokens keep a user’s identity active (forcing your user to reauthenticate too much will make them stop using your app).
Rotation triggers (when)
Whether disposable or durable, the event that forces a change is driven by a few core factors: hygiene, lineage compromise, entity compromise, or identity leakage.
Hygiene: cryptographic material deteriorates with use. If you sign enough packets, a mathematical adversary can eventually derive your key. In practice this is rarely hit in most application-layer systems, but it’s still good practice to rotate before theoretical limits, and especially before keys are reused across many contexts.
Lineage compromise: if an upstream signing key (the root) is compromised, all downstream identities are suspect and must be mass-revoked and re-issued.
Entity compromise: if the machine itself is breached, the identity is burned. In a disposable model, you kill the machine. In a durable model, you must revoke the specific keys and trigger a recovery flow (often requiring human intervention or a separate attestation channel). Any identities derived from this point become part of the compromised lineage.
Identity compromise: identities, especially longer-lived ones, are commonly leaked in other channels (API keys uploaded to GitHub) or, more rarely, intercepted during transmission. In this case, the underlying entity may still be safe but its identity is not. If material used to derive identities is leaked, that’s a lineage compromise. If only a signed metadata document is leaked, the blast radius is smaller but still real.
Once you have these three pieces—origin, initial policy state, and continuity—the benefits become obvious.
Benefits of starting with identity in your system
Once you determine how a non-human identity originates, what its initial policy state is, and how its lifecycle is managed, most of the architectural choices fall into place. If your identity is attested and begins with zero privilege, you can build enrollment flows. If it’s asserted and begins with explicit privilege, you can build rich delegation. If it’s self-proven and begins with nothing, you can layer additional proofs or second factors to contextualize it. If it’s disposable, you can lean on re-deployments for rotation. If it’s durable, you can design continuity and recovery protocols explicitly.
The benefits of grounding your system in proper identity rather than starting from authentication are significant. Authentication methods like OAuth can be convenient but also push developers toward sloppy handling of the underlying secrets and keys. Those keys are the actual identity; if lost or duplicated, impersonation becomes trivial. Opaque secrets make monitoring and auditing difficult. They also tie you tightly to whichever provider issued them. When you begin with identity, authentication becomes a flexible choice rather than a constraint. You can mint short-lived authorization tokens at the application layer, treat identity as an API key, or feed identity into a centralized, high-performance policy engine like Zanzibar. Identity-first keeps your options open.
Strong identity also enables composition. You can combine identities in ways that are extremely difficult to steal or replicate. A hardware identity can sign a workload identity which can sign an agent identity. The combination yields precise, powerful policy. An attacker would need to compromise every layer to impersonate the entity. Starting from identity gives you the raw material to build this level of security.
Furthermore, because identity at its heart uniquely identifies an entity within your system, you get an easy starting point for precise accounting of who did what and when.
If you completely model identity and how it is securely distributed in your system, identities will be very hard to steal en masse and very hard to use once stolen outside their intended environment. In fact, I believe it is possible to build a system in which a perfect “bottom turtle” isn’t necessary because identities can be made cryptographically useless if stolen (DPoP, hardware attestation, or challenge-responses), and a system with fully provisioned identity is one with incredible monitoring capability.
This, I think, is the right lens for understanding non-human identity. Once you know where identity comes from, what it can do at the moment of creation, and how it evolves over time, everything else becomes much clearer.
If we want secure, composable, large-scale machine systems, identity has to come first. Everything else follows from that. I hope this model helps provide a conceptual foundation that’s been missing for machine identity.
If this model resonates with how you're thinking about machine identity, I'd love to hear from you. If you violently disagree or have clear examples where it breaks down, I want to hear those too. I'm building an identity and authorization platform around these ideas, and I'm always looking for people who are wrestling with similar problems in real systems—or just passionate folks who want to talk about this stuff.
If you're curious what that platform looks like in practice, check out What is Hessra for concrete examples of how we're applying these ideas.
Appendix: Mapping Existing Systems to the Model
Here’s how some common machine identity systems fit into the three dimensions of this model. These aren’t the only possible classifications, but they reflect how they’re typically used in practice.
| System | Identity Origin | Initial Policy State | Continuity (Typical) |
|---|---|---|---|
| SSH public key | Self-proven | Zero default | Durable |
| Web server TLS cert (public website) | Asserted (CA) | Explicit (domain access) | Durable |
| mTLS client cert for internal service | Asserted | Explicit | Durable or disposable |
| Cloud VM instance metadata (e.g. AWS IMDS) | Attested | Minimal baseline or zero | Durable |
| SPIFFE/SPIRE workload identity | Attested → Asserted | Minimal baseline or explicit | Disposable (pods) |
| Kubernetes service account + RBAC | Asserted | Explicit | Disposable (pod) |
| CI/CD job token (GitHub Actions, etc.) | Asserted | Explicit | Disposable |
| IoT device cert burned at manufacture | Asserted | Explicit | Durable |
| WebAuthn / passkey | Self-proven | Zero default | Durable |
| SaaS API key (scoped) | Asserted | Explicit | Durable |
| P2P node key (libp2p, etc.) | Self-proven | Minimal baseline | Durable |
| Hardware security module (HSM) identity | Attested / Asserted | Explicit | Durable |
| AI Agent or subagent | Asserted | Explicit | Disposable |