A non-human identity (NHI) is any identity used by software rather than a person: service accounts, API keys, OAuth clients, workload identities and, increasingly, AI agents. An AI agent is an NHI with an unusual property, because it can decide at runtime which tools to call and sometimes acts on behalf of a human user. In Keycloak terms, the clean model is one OAuth client per agent (or per agent class), a service account with only the roles that agent needs, short-lived tokens bound to a specific audience, and token exchange delegation when the agent acts for a user. The model to avoid is the common shortcut of a single shared “bot” account with a long-lived secret that every agent reuses.
This post explains what the NHI category actually covers, why AI agents stretch it, which service account habits fail an audit, and how the Keycloak 26.8 feature set maps onto an NHI program. The same model applies to any OAuth 2.0 authorization server, including identity management as a service platforms, and we use Keycloak, the open-source option, to illustrate it.
What is a non-human identity?
A non-human identity is a credential and an account that lets software authenticate to other software without a person typing a password. The OWASP Non-Human Identities Top 10, published in 2025, describes NHIs as identities “such as service accounts, API tokens, and workload identities” that “are designed for programmatic access to cloud resources and services.” The OWASP project’s introduction attributes the risk to excessive permissions, long-lived credentials, poor credential management and a lack of monitoring.
It helps to split the space into three groups, because each one is governed differently:
- Humans sign in interactively, have a manager, and leave the company through an HR process that disables their account.
- Workloads are services, jobs and pipelines. They run fixed code, so their access needs are predictable and stable.
- AI agents are workloads too, but their behaviour is not fixed. A language model chooses which tool to call next, so an agent’s real access is whatever its credentials allow, not whatever its prompt intends.
That last point is why AI agents push NHI from a hygiene topic to a design topic. With a cron job, an over-broad credential is a latent risk. With an agent, the model can find and use that extra access when a prompt injection or a bad plan tells it to.
Are AI agents non-human identities?
Yes. An AI agent that calls APIs with its own credentials is a non-human identity, and it should be inventoried, owned and reviewed like any other. Where agents differ is that many of them also act on behalf of a user, which means the token they present carries two identities at once: the agent (the actor) and the human (the subject).
Standards already have a place for this. RFC 8693, the OAuth 2.0 Token Exchange specification, defines an act (actor) claim that identifies the party doing the acting, while the token’s sub claim still names the user it is acting for. Keycloak 26.8.0, tagged on 1 October 2026, uses exactly that claim for its token exchange delegation feature, which we cover below. So the honest answer is that an agent is an NHI when it works for itself, and an NHI acting for a human when it works for a user, and your tokens should say which one is happening.
We covered the protocol-level patterns (client credentials, delegated access, MCP) in authenticating AI agents with Keycloak. This post stays at the governance layer: how many identities, with what scope, owned by whom.
Why is one shared bot account a problem?
A single service account shared by every agent is a problem because it erases the information an auditor and an incident responder both need: which agent did this, who owns it, and what would break if you revoked it. Several entries in the OWASP NHI Top 10 for 2025 describe this exact shape, including NHI9 (NHI Reuse), NHI5 (Overprivileged NHI), NHI7 (Long-Lived Secrets) and NHI1 (Improper Offboarding).
Here is how those risks usually show up with LLM applications.
Shared secrets across agents
When three agents share one client secret, the audit log shows one client making every call. If the secret leaks from one agent’s environment, you have to rotate it everywhere at once, which usually means an outage, so in practice nobody rotates it. OWASP lists this pattern as NHI9 (NHI Reuse) and the secret itself as NHI2 (Secret Leakage).
Human-equivalent roles on machine clients
A tempting way to make an agent work quickly is to give its service account the same roles as the developer who built it. That turns every agent into a copy of a senior engineer, including permissions the agent never needs. OWASP calls this NHI5 (Overprivileged NHI), and it is more dangerous with agents than with fixed workloads because the agent can be talked into using what it has.
Humans using the agent’s credentials
A related failure runs the other way: engineers grab the agent’s secret to debug something by hand. OWASP lists this as NHI10 (Human Use of NHI). OWASP describes the result as a “lack of auditing and accountability due to indistinguishable activity”, because the audit log no longer tells you whether a person or the agent made a call. Per-client events in your audit logs only help if each identity is used by exactly one party.
Nobody owns the identity
Agents get prototyped, demoed and abandoned. If the identity has no owner and no expiry, it stays active long after the project ends, which is NHI1 (Improper Offboarding).
How do you model AI agents as NHIs in Keycloak?
You give each agent, or each class of identical agents, its own confidential OAuth client with a service account, and you scope that client tightly. Keycloak already has every piece needed, and the 26.8 release made two of them more useful for agents.
One client per agent or agent class
Create a separate client for each agent that has its own owner, purpose or risk level. Enable Client authentication and Service account roles on it so it can use the client credentials grant, and put the owning team and purpose in the client’s description so the admin console doubles as an inventory. Agents that are genuinely identical (for example, ten replicas of the same support agent) can share one client, because they share an owner and a blast radius.
If the agent runs in Kubernetes, you can avoid a stored secret entirely. Keycloak’s server administration guide documents client authentication with “Signed JWT issued by an Identity Provider”, which accepts client assertions such as Kubernetes service account tokens or SPIFFE JWT SVIDs. In Keycloak 26.8.0’s feature list, federated client authentication and the Kubernetes service accounts provider are default features, while the SPIFFE provider is still preview.
Audience, scope and lifetime defaults
Each agent’s tokens should name the API they are for and expire quickly. In practice that means:
- Assign only the client scopes and roles the agent’s tools need, and remove the default scopes it does not use.
- Add an audience mapper so the token’s
audclaim names the specific API or MCP server, and have that server reject tokens with any other audience. Our MCP server 401 audience post shows the mapper configuration. - Shorten the access token lifespan on the agent’s client in its advanced settings, so a leaked token is useful for minutes rather than hours.
Rotation and revocation without redeploying the model
Keycloak 26.8.0 promoted Client Secret Rotation from preview to supported. According to the server administration guide, a client policy can keep up to two secrets active at once, so the agent can pick up the new secret before the old one expires. Rotation is not a background job, though: it happens when the client is updated, either through Regenerate Secret in the admin console or through the Admin REST API, so you still need a scheduled task or pipeline that triggers it.
Revocation is simpler when each agent has its own client. Disabling that one client stops new tokens for that agent without touching any other agent, and short access token lifespans limit how long already-issued tokens stay useful.
The design choice that makes all of this workable is the one-client-per-agent rule. Rotation, revocation, audit and offboarding all become per-agent operations, and none of them require you to retrain, re-prompt or redeploy the model itself.
How should an agent act on behalf of a user?
An agent acting for a user should get a token that names both the user and the agent, not borrow the user’s own token. Keycloak 26.8.0 moved token exchange delegation to preview for this case. According to the 26.8.0 release notes, users can delegate access to a client through OAuth consent using the delegation:client:<client-id> parameterized scope, and the resulting token “includes an act claim identifying the client as the actor.”
The release notes add two safeguards that matter for agents. Client delegation “does not grant Admin API access even if the client holds service account credentials,” so a leaked delegation token cannot be used to administer the realm. And delegation is authorized through Fine-Grained Admin Permissions V2, using delegate and delegate-members scopes, which gives you a central place to decide which agents may act for which users.
Keycloak’s token exchange guide lists the practical requirements. You enable it with --features=token-exchange-delegation,parameterized-scopes. The user-facing client that requests the delegation:client:<client-id> scope must have Consent required turned on, and the user approves the delegation again in every login session because that consent is never stored permanently. The agent itself (the actor client) must be a confidential client with a service account and Standard Token Exchange enabled, because it exchanges the user’s token for a delegated one at the token endpoint. That delegated token is access-token only, with no refresh token, and its audience and scopes come from the agent client’s own configuration, so it carries only what the agent is allowed to have:
{
"sub": "0fa1e5d4-3c2b-4a19-8765-0123456789ab",
"act": {
"sub": "9b8c7d6e-5f4a-4b2c-9d0e-fedcba987654",
"client_id": "support-agent"
}
}
Here sub is the user and act is the agent’s service account and client ID, which is what a resource server should log. Without a matching FGAP V2 permission, the delegation scope is silently dropped and the login still succeeds, so check the issued token rather than assuming delegation happened. Because this is a preview feature, test it on a non-production realm first. Our posts on how Keycloak token exchange works and Cross-App Access (ID-JAG) for AI agents cover the wider token exchange picture.
Where do zero standing privilege and agent gateways fit?
They sit on top of the identity model described above, not in place of it. Zero standing privilege means an agent holds no long-lived access and receives narrowly scoped, short-lived tokens only when a task needs them. Agent gateways put a policy check in front of each tool call. Both assume you can already tell agents apart, which is exactly what one client per agent gives you.
For the policy check itself, Keycloak can answer per-call authorization questions through the standard AuthZEN API, which we explain in using Keycloak as an AuthZEN policy decision point. For how the large identity vendors are packaging agent identity, see our look at agentic IAM and Okta’s agent SSO and the comparison of Bedrock AgentCore Identity and Keycloak agent OAuth.
On Skycloak these are ordinary upstream Keycloak clients, so they stay exportable if you move. For the role design that agent clients draw from, see our role-based access control overview.
Frequently asked questions
What is the difference between a non-human identity and a service account?
A service account is one kind of non-human identity. NHI is the broader category, which the 2025 OWASP NHI Top 10 describes as including service accounts, API tokens and workload identities. In Keycloak, a service account is attached to a confidential client and used with the client credentials grant.
Should every AI agent have its own identity?
Every agent with its own owner, purpose or risk level should. Separate identities let you revoke, rotate and audit one agent without affecting others. Identical replicas of the same agent can share one Keycloak client, because they share an owner and an expected behaviour. OWASP lists identity reuse as NHI9 in its 2025 Top 10.
How do you rotate an AI agent’s client secret in Keycloak?
Keycloak 26.8.0 made Client Secret Rotation a supported feature. A client policy keeps up to two secrets active, so the agent can switch before the old secret expires. Rotation happens on a client update, through Regenerate Secret or the Admin REST API, so schedule it from a pipeline.
Can an AI agent authenticate to Keycloak without a stored secret?
Yes. Keycloak supports client authentication with signed JWTs issued by an identity provider, such as Kubernetes service account tokens or SPIFFE JWT SVIDs. In Keycloak 26.8.0 the Kubernetes service accounts provider is a default feature, while SPIFFE is still preview, so agents in Kubernetes can use their pod identity instead of a secret.
How do you show that an agent acted for a user?
Use a delegated token that carries both identities. RFC 8693 defines the act claim for the actor, and Keycloak 26.8.0’s token exchange delegation (preview) issues tokens with an act claim identifying the agent’s client while the subject remains the user, which keeps audit logs unambiguous.
Sources
- OWASP, Non-Human Identities Top 10 (2025), https://owasp.org/www-project-non-human-identities-top-10/2025/ (source at https://github.com/OWASP/www-project-non-human-identities-top-10)
- IETF, RFC 8693 “OAuth 2.0 Token Exchange”, section 4.1 “act (Actor) Claim”, https://datatracker.ietf.org/doc/html/rfc8693#section-4.1
- Keycloak, Securing Applications guide, “Token exchange delegation”, https://github.com/keycloak/keycloak/blob/26.8.0/docs/guides/securing-apps/token-exchange.adoc
- Keycloak, 26.8.0 release notes, “Token exchange delegation with consent, FGAP authorization, and audit trail (preview)” and “Client Secret Rotation (supported)”, https://github.com/keycloak/keycloak/blob/26.8.0/docs/documentation/release_notes/topics/26_8_0.adoc
- Keycloak, Server Administration Guide, “Client Secret Rotation”, https://github.com/keycloak/keycloak/blob/26.8.0/docs/documentation/server_admin/topics/clients/oidc/con-secret-rotation.adoc
- Keycloak, Server Administration Guide, “Confidential client credentials” (Signed JWT issued by an Identity Provider), https://github.com/keycloak/keycloak/blob/26.8.0/docs/documentation/server_admin/topics/clients/oidc/con-confidential-client-credentials.adoc
- Keycloak, feature profile (
Profile.java) at 26.8.0, https://github.com/keycloak/keycloak/blob/26.8.0/common/src/main/java/org/keycloak/common/Profile.java