Detect AI agents in login flows¶
AI agents can sign in to applications on behalf of users, either by driving a browser or by calling endpoints directly. WSO2 Identity Platform lets you detect these requests with a conditional authentication script and then block them or require a human to complete the sign-in.
WSO2 Identity Platform provides two built-in conditional authentication templates in the AI Agents category of the script editor.
| Template | Behavior |
|---|---|
| AI Agent Blocking | Denies the sign-in when an AI agent is detected. Otherwise, the application's login steps run as usual. |
| AI Agent Human-in-the-Loop | Runs the first login step, which an agent may complete, and then requires a human-only verification step when an AI agent is detected. |
Both templates detect agents that identify themselves with Web Bot Auth. To detect other agents, extend the detectAgent() function with the methods below.
Prerequisites¶
-
You need to register an application with WSO2 Identity Platform. You can register your own application or use one of the sample applications provided.
-
Make sure your load balancers and proxies forward the Web Bot Auth headers (
Signature,Signature-InputandSignature-Agent) to WSO2 Identity Platform. -
To use the AI Agent Human-in-the-Loop template, users must be able to complete the human-only verification step, for example with a registered passkey.
Apply a template¶
-
On the WSO2 Identity Platform Console, click Applications.
-
Select the relevant application and go to its Login Flow tab.
-
Add the template using your preferred editor:
-
Click Start with default configuration to define the login flow starting with the
username and passwordlogin. -
Turn on Conditional Authentication by switching the toggle on.
-
Select the AI Agents > AI Agent Blocking or AI Agents > AI Agent Human-in-the-Loop template.
-
Switch to the Visual Editor tab, and expand Predefined Flows > Conditional Login Flows > AI Agents.
-
Click + ADD next to AI Agent Blocking or AI Agent Human-in-the-Loop.
-
Click Confirm to replace any existing script with the selected predefined script.
-
-
Extend
detectAgent()if needed, and click Update to confirm.Important
As a security measure, WSO2 Identity Platform does not allow the usage of two consecutive periods (
..) in authentication scripts.
How it works¶
Both templates call detectAgent(context) in onLoginRequest. The default detectAgent() returns true when the request has a Signature-Agent header, or a Signature-Input header with the tag="web-bot-auth" parameter:
var detectAgent = function (context) {
// Header names are lower-case.
var headers = context.request.headers;
var signatureInput = String(headers['signature-input'] || '');
// Match the tag parameter exactly, e.g. sig1=("@authority");tag="web-bot-auth".
return !!headers['signature-agent'] || /;\s*tag="web-bot-auth"\s*(;|,|$)/.test(signatureInput);
};
AI Agent Blocking denies the sign-in with the message in the errorMessage parameter. For API-based (app-native) requests, the template fails the flow instead of showing an error page.
AI Agent Human-in-the-Loop runs step 1 for every user. When an AI agent is detected, it then runs step 2, so the sign-in can't continue until a human completes it.
Choose a human-only verification step¶
Step 1 is your application's usual sign-in, and an agent may complete it. Step 2 must be a factor that only the user can complete, on their own device or with biometrics. The template uses a passkey by default.
| Step 2 option | Suitability |
|---|---|
| Push notification | Recommended. The user approves the sign-in on their own mobile device, wherever the agent runs. |
| Passkey | Recommended. The user verifies with biometrics or a device PIN on their own device. |
| TOTP, email OTP or SMS OTP | Not recommended. An agent with access to the user's authenticator, mailbox or messages can complete it. |
Warning
Don't enable progressive enrollment for the step 2 factor in this flow. An agent that holds the user's password could enroll its own device.
Note
Find out more about the scripting language in the Conditional Authentication API Reference.
Ways to identify AI agents¶
No single signal identifies every AI agent. Add the checks that fit your application inside detectAgent(), above the final return statement.
Web Bot Auth¶
Recommended. Built into both templates.
Web Bot Auth uses HTTP Message Signatures (IETF draft-ietf-webbotauth-httpsig-protocol) so that an agent can prove who it is. A signed agent sends the Signature, Signature-Input (with tag="web-bot-auth") and Signature-Agent headers, and publishes its public keys at <origin>/.well-known/http-message-signatures-directory.
Declaring itself as an agent is enough to deny a request or require a step-up. It doesn't prove identity, because any client can send these headers. Authentication scripts can't verify HTTP signatures, so verify them at the edge (your WAF, CDN or reverse proxy) before you trust or allow-list an agent. Configure the edge to verify the signature against the signer's key directory, add a trusted header such as x-verified-agent, and strip that header from all incoming client requests. The script then reads the trusted header:
// Add near the other top-level variables.
var trustedAgents = ['https://agent.example.com'];
// Add inside detectAgent(), above the declared-agent check.
var verifiedAgent = context.request.headers['x-verified-agent'];
if (verifiedAgent) {
// A verified agent is an agent, unless you trust it explicitly.
return trustedAgents.indexOf(String(verifiedAgent)) < 0;
}
User agent markers¶
Known agents and browser automation tools often put a marker in the User-Agent header.
// Add near the other top-level variables.
var agentUserAgentPattern = /HeadlessChrome|ChatGPT|Claude|Google-Agent|Perplexity|Playwright|Puppeteer|Selenium/;
// Add inside detectAgent().
var userAgent = String(context.request.headers['user-agent'] || '');
if (agentUserAgentPattern.test(userAgent)) {
return true;
}
Warning
Clients can set any User-Agent value, so this check is easy to spoof. Prefer Web Bot Auth for agents that sign their requests.
Agent provider IP ranges¶
Some AI agent providers publish the IP ranges their agents use. Get the current lists from each provider's documentation, and match context.request.ip against them. Copy the convertIpToLong, getIpAddrInLong and isCorporateIP functions from the built-in IP-Based template into your script.
// Add near the other top-level variables. Replace with the ranges published by the providers.
var agentIpRanges = ['203.0.113.0/24', '198.51.100.0/24'];
// Add inside detectAgent().
if (isCorporateIP(context.request.ip, agentIpRanges)) {
return true;
}
Note
The helper functions handle IPv4 only. context.request.ip honors the X-Forwarded-For header, so configure your load balancer to overwrite this header with the real client address.