Table of contents

Guide

Agentic Ops

Access Control

User authentication: a guide for developers in the era of autonomous AI agents

Guillaume Rigal

0 min read

Authentication looks solved. Then an agent signs in with a user's credentials, and you find out what your setup actually assumed.

User authentication has been settled for a long time. A person types something, your system verifies it, and the session that follows belongs to that person. Every decision downstream was made on that assumption: how long a session lasts, what gets written to the log, who can cut access off and how fast.

AI agents break the assumption, and they are already in production. An agent connected to a backoffice signs in, calls the API, reads records, and increasingly changes them. Ask the obvious questions and the answers get uncomfortable quickly. Whose credentials is it using? If they belong to a user, does it get everything that user can do, on every record they can reach, at machine speed? When that credential leaks, who can cancel it, and how long does it take?

Nothing there is exotic. It is the same authentication you already have, asked about a caller it was never designed for.

So this guide is that re-examination, in two halves. The basics first: authentication versus authorization, how a login works today, and which of SSO, SAML, OIDC, SCIM and MFA covers what. Skim it if you build this regularly, but it is worth a look, because most teams have one gap in there and it tends to be the same one. Then the agent half: how an agent authenticates, how to think about the credential you hand it, when it needs an identity of its own, and what your log has to record once software is acting for somebody.

What is the difference between authentication and authorization?

Authentication establishes who is calling. Authorization decides what they may do. Authentication happens once, at the start of a session, and produces an identity. Authorization happens on every single request, using that identity.

If you are here, this is probably the table you wanted.


Authentication

Authorization

The question

Who are you?

What are you allowed to do?

When

Once, at the start of a session

Every request

Produces

An identity, usually carried in a token

A yes or a no

Fails as

401 Unauthorized, which is misnamed and means unauthenticated

403 Forbidden

Owned by

Your identity provider, or your login code

Your permission model

The two fail differently, and teams debug the wrong one constantly. If somebody can sign in but cannot see what they expect, that is authorization, and reading the login flow will not help.

The agent question above is this confusion at scale. "The agent authenticates as the user" answers only the first column. What the agent may then do is a permission model, covered in our guide to user roles and permissions. Everything below is authentication.

How does user authentication actually work?

The three steps have not changed: present a credential, verify it, receive proof of the verification so you do not repeat it on every request. What has changed is how much of that you write, and the answer is almost none. Every method that became standard in the last few years moves the risky part elsewhere:

  • OAuth 2.0 and OpenID Connect turned "let this application act for this user" into a protocol rather than a per-integration design decision.

  • Hosted identity providers took password storage, reset flows, breach detection and MFA enrollment off your roadmap.

  • Passkeys and WebAuthn removed the shared secret. No password to steal, and the credential is bound to your domain, so it will not fire on a convincing copy of your login page.

  • Magic links and one-time codes removed the password from the user's side, not from yours. A usability improvement, not a security one.

What none of them decides is the part that determines what your logs are worth: how long a credential stays valid, and how you cancel it.

Most systems now issue a short-lived access token plus a longer-lived refresh token, and the split exists for one reason. A signed token cannot be withdrawn once issued, so a short access token caps how long a stolen one is useful and the refresh token is the thing you can actually cancel. Expiry is not a nuisance setting. In a token system it is most of the revocation you have. Choose it deliberately, and shorter for anything non-interactive.

Which of SSO, SAML, OIDC, SCIM and MFA do you actually need?

Teams buy one of these and assume they bought the others. That gap is why leavers keep their access.


Stands for

What it does

The job it covers

SSO

Single sign-on

One login across many applications

Convenience, and one place to enforce policy

SAML

Security Assertion Markup Language

The older SSO protocol, XML-based, still standard in enterprise

How the login is transported

OIDC

OpenID Connect

The newer one, JSON-based, sits on top of OAuth 2.0

How the login is transported, and who the user is

SCIM

System for Cross-domain Identity Management

Pushes user creation, updates and deactivation from your identity provider into each application

Lifecycle. This is what removes a leaver everywhere

MFA

Multi-factor authentication, called 2FA when there are exactly two factors

Requires a second proof beyond the password

Making a stolen password insufficient

SSO without SCIM is the gap almost everybody has. SSO means a leaver can no longer sign in through the identity provider. It does not mean their account is gone, their roles are revoked, or the API key they created two years ago stopped working. Closing that needs SCIM, or an offboarding process somebody runs. The wider version of that problem, joiners and movers as well as leavers, is in our guide to permission management.

The MFA factors are not equivalent either. SMS is phishable and SIM-swappable. Only a hardware key or passkey survives a convincing phishing page, because the credential will not present itself to the wrong domain.

How does an AI agent authenticate?

Everything above assumed a person at a keyboard. This is where that stops being true, and where the practices that worked for people need revisiting rather than replacing.

An agent authenticates in one of two shapes, and they are not interchangeable.

Delegated: the agent acts as a user. The user signs in, authorizes the agent, and it receives a token carrying their identity. Every request it makes is that user's request. This is what OAuth was designed for, and it is the right shape whenever a person asked for the specific work.

Standing: the agent acts as itself. The agent holds a credential representing itself and holds exactly the role you attached to that identity: a defined set of operations on a defined set of records, decided when you created the account rather than inherited from anybody. This is the right shape when nothing human triggered the run, and what that role should look like when an agent rather than a person holds it is covered in our guide to role-based access control.

The difference is governance. A delegated token dies when the user's access is revoked, so somebody is already maintaining it without meaning to. A standing credential is maintained by nobody unless you assign an owner.

Treat the agent as an adversary, and the questions get easier

The sharpest position we have heard comes from security teams in regulated fintech, and it is worth borrowing whatever you are building. They treat an AI agent as an adversary by default. Not because it is expected to misbehave, but because it is software holding a credential: anything you hand it is assumed leakable, and anything leaked is assumed replayed to pull data out.

The assumption is useful because it replaces an unanswerable question with three answerable ones.

Ask

Why it decides the risk

How narrow is the identity behind the credential?

A stolen token is worth exactly what the identity can reach. Narrowing the identity is the only control that caps the damage rather than shortening it

How long does the credential live?

Lifetime is the difference between an incident and a window. An agent making rapid calls does not need an hour

How fast can it be revoked, and by whom?

If revocation requires an admin, a ticket and a deploy, it will not happen on the day it matters

Two settings follow directly. Shorten the lifetime, since a non-interactive caller is not inconvenienced by refreshing. And declare which clients you accept, because an OAuth flow authorizes any registered client by default: a token from a client you never registered is rejected before it reaches your data.

It does not buy you a credential that is safe by construction. The realistic goal is a small blast radius and fast revocation, not an unstealable token.

How this works in Forest. Both shapes exist, and the test above decides which one you are in.


Delegated

Standing

The agent signs in as

A user, by OAuth or an application token

A service account, with credentials of its own

It can reach

What that user can reach, no more and no less

What its own role and scopes allow

The log names

That user

The service account, under its own name

Revoked by

The user who issued the token, with no admin in the loop

An administrator, by disabling the account or rotating its credentials

Use it when

A person asked for this specific action

The run is scheduled or event-driven, with nobody behind it

An assistant running on an operations analyst's machine is the left column. It signs in with that analyst's account, inherits their role and scopes, and its calls appear under their name. A nightly reconciliation job is the right column, and no person's credentials should be anywhere near it.

Narrowing a delegated agent below what its user can reach uses the mechanism you already use for people: point it at a separate account with a narrower role. Neither column has a special agent path, which is the part worth taking away. The permission model you already review is the one governing the agent.

How does a service account work for AI and automation?

A service account is an identity that belongs to software rather than to a person. It has credentials, it holds a role, it appears in your logs under its own name, and nobody signs in as it.

It exists for attribution. In an audited system every action has to be traceable to an entity, human or not, and "the system did it" is not an answer a regulator accepts when a scheduled job moves money at three in the morning. The entity needs a name, and the name has to outlive whoever configured it.

Four things make an account a service account rather than a shared credential:

  • A named owner. A person is accountable for it. The account is not theirs and nobody logs in as it.

  • Its own grant, built from the operations the automation performs, rather than copied from a person's role.

  • Its own line in the log, under its own name.

  • A review date, because nothing else will ever prompt anybody to look at it. Service accounts belong in the same access review as people, and they are the item most often left out of it.

For instance, in Forest a service account is a first-class identity on the same permission model as any human user: its own role, its own scopes, its own line in the activity log. The practical consequence is that it gets reviewed where people get reviewed, rather than living in a spreadsheet of integrations that nobody owns and nobody opens.

Why a shared API key fails an audit. A key pasted into three services and a password manager is not an identity. It is a password with no owner. That creates four problems, and in a regulated business they compound:

  • No attribution. The log says the key acted. It cannot say which service, which person, or which of the four people who hold it.

  • No revocation. Cancelling it breaks everything that shares it, and nobody knows the full list, so it does not get cancelled.

  • No scope. Keys are almost always issued broad, because narrowing one means finding out what uses it.

  • No rotation. For the same reason. A credential nobody dares rotate is a permanent credential.

One identity per caller removes all four at once. It costs nothing at the moment you create an integration and is expensive eighteen months later.

What should your log record when an agent acts?

Four fields. The middle two are the ones teams leave out and regret.

Field

What goes in it

Who is accountable

The user, on a delegated call. The service account, otherwise

What made the call

The assistant, the scheduled job, the interface, a direct API call

Which application held the token

Delegated calls only

What changed

The record, the field, the value before, the value after

Two examples, so it is clear what lands where.

A support analyst asks their assistant to issue a refund. Accountable identity: the analyst. Origin: the assistant. Record only the assistant and the log says a robot issued a refund. Record only the analyst and the refund looks like she clicked it herself, so six months later nobody can tell an integration was involved.

A nightly job re-screens the sanctions list. Accountable identity: the service account. There is no second name, and that is correct. The origin still matters, because a call from the reconciliation service and a call from somebody's laptop using that service's key should not look the same in the log.

That is the whole specification. It is tedious to build, easy to defer, and urgent on the day somebody asks for a year of evidence. It is also not your product.

Which is the argument for putting a backoffice on infrastructure that already does it. Forest sits on top of the databases and data sources you already have, gives every user and every service account an identity on one permission model, and records every operation and action against the record, field by field. Forest's MCP Server exposes that same model to AI clients, so an agent arrives already inside the permissions and already in the audit trail rather than as a new integration to govern separately. It is the layer regulated fintechs including Qonto and Swan run their operations on.

Wiring an agent to your data takes a day. Building the identity, permission and audit layer that makes it safe to do so takes a quarter. Forest gives you that layer already built.

Frequently asked questions about user authentication

Should an AI agent have its own login?

Only if nothing human triggered the work. If a user asked for a specific action, the agent should carry that user's identity, so their permissions and their name apply. If the run is scheduled or event-driven with nobody behind it, it needs a standing identity of its own. A customer filling in a form on your website does not count as a human user: they hold no permissions in your system, so there is nothing to inherit, and that run needs a service account.

Is OAuth authentication or authorization?

Authorization. OAuth grants an application permission to act on somebody's behalf. OpenID Connect is the layer on top that adds authentication, telling you who the person is.

What about agents that belong to another company?

Same starting point. A partner's agent, or a tool one of your own teams bought, still needs an identity you issued and a grant you control. That case is covered in permissions beyond your own team.

Authentication is where accountability starts

Everything downstream of the login inherits what the login established. A permission model cannot scope what it cannot identify, and an audit trail cannot name what was never distinguished.

None of the work differentiates your product, which is the argument for not building it. What an identity is permitted to do, once you know who it is, is in our guide to user roles and permissions.

More questions about user authentication

How should you store passwords?

Hash them with a slow, memory-hard algorithm built for the purpose: Argon2id, scrypt or bcrypt. Never a general-purpose hash like SHA-256, which is fast, and fast is the wrong property here. Every password gets its own random salt, stored alongside the hash.

If you use a hosted identity provider you are not storing passwords at all, which remains the right answer for most teams.

Is biometric authentication worth implementing?

Not directly, and you almost certainly should not try. The biometric check happens on the user's device and never reaches your server: a fingerprint or a face unlocks a passkey held in the device's secure hardware, and what you receive is a cryptographic signature.

So the practical way to offer biometrics is to support passkeys and WebAuthn, which gives you phishing resistance in the same move. Handling raw biometric data yourself brings storage, consent and regulatory obligations that are not worth taking on.

How do you protect against brute force attacks?

Rate limit by account and by source address, and keep the two independent. An attacker spraying one common password across ten thousand accounts never trips a per-account limit.

Prefer increasing delays after failed attempts over a hard lockout, since a lockout is itself a denial-of-service vector: anyone who knows a colleague's email can lock them out. Then watch the pattern rather than the count. Many accounts, one source, one password is credential stuffing, and it looks nothing like somebody forgetting their password.

What makes a good password policy today?

Shorter than the rules most teams still enforce. Current guidance has moved away from forced composition rules and scheduled expiry, because both push people toward predictable patterns: a capital at the front, a digit and an exclamation mark at the end, incremented every quarter.

What replaces them is length as the main lever, a check of new passwords against known breached lists, and a forced change only when there is evidence of compromise rather than on a calendar.

LEVEL UP YOUR OPS GAME

Every action traced, for every human, AI agent, BPO, LLM, and workflow.

LEVEL UP YOUR OPS GAME

Every action traced, for every human, AI agent, BPO, LLM, and workflow.

LEVEL UP YOUR OPS GAME

Every action traced, for every human, AI agent, BPO, LLM, and workflow.

The operational infrastructure regulated companies grow on

Copyright © 2026 Forest

Design by Alasta & Built by Reiya Studio