AIAI EngineerJun 30, 2025· 18:41

Securing Agents with Open Standards — Bobby Tiernay and Kam Sween, Auth0

Bobby Tiernay and Kam Sween from Auth0 argue that production-grade AI agents must be secured using open identity standards like OAuth 2.1, token exchange, and SIBA to avoid the pitfalls of shared secrets, overly broad scopes, and lost audit trails. They explain that agents need a clear user identity to prevent the confused deputy problem, and that access should be scoped per user and per API with short-lived tokens from a vault. For retrieval-augmented generation, they advocate fine-grained authorization at the retrieval layer, not inside the LLM. Kam demonstrates a local trading agent that uses SIBA (client-initiated back-channel authentication) to request user approval via push notification without a browser, after the user authenticates once. The talk emphasizes that these patterns—async user consent, token exchange, and centralized credential management—are live today in standards and platforms like Auth0 and OpenFGA, enabling developers to build secure agents without reinventing the wheel.

Transcript

Intro0:00

Bobby Tiernay0:15

Hi everybody. I'm Bobby, this is Kam, and we're both engineers here at Auth0. We've both been working a lot in the AI space lately, trying to come up with clear ways for identity and access control that's designed for a world where agents are center stage.

That's included our work on our Auth for GenAI platform, our Auth0 MCP server, and our own first-party agent called Tenant Security Manager. Just like everyone here, we're learning from the community as well as we do this. The main thing is trying to get to grips with what delegation and access means in a world where agents are acting on users' behalf.

Today we want to share some of those lessons that we've learned in this journey, and what's actually worked, what hasn't worked, and a few practical ways that you can get started with identity and accessright from the start. But I had to splash this slide because we were told we could have opinions as long as we showed it.

Here we go. To kick things off, let's talk about the security challenges of smarter agents as they start to do more things in the real world. Once they're moving beyond chat and actually doing things in the real world, cracks are starting to appear, and it's pretty clear.

Challenges1:16

Bobby Tiernay1:34

Secrets end up in prompts, scopes get too broad, and troubleshooting gets really, really hard when you don't have theright visibility. Agents are out there making decisions, taking actions on behalf of users, but it's very easy to lose track of what's really going on.

Things might look fine on the surfaceright up until there's a security incident and you realize you don't have enough data to trace what actually happened. This is where a lot of the GenAI risks begin. OWASP calls it excessive agency, but really it's just a fancy way of saying giving agents too much access without guardrails.

Access here means calling APIs, pulling data, using tokens, touching credentials, and keys. If that access isn't scoped, monitored, and tied to a real user, you're wide open to abuse and unintended behavior. There's other OWASP risks too, like sensitive data exposure, but that often comes back to the same root cause.

If an agent reaches into something they shouldn't, it's usually because no one told it not to. If you've been listening to the talks here, it's pretty clear that agents aren't just responding to prompts anymore. They're actually doing real things, calling APIs, kicking off workflows, changing your systems.

That means they're moving through your stack, touching real user data, interacting with real external systems. It all needs to happen under theright context, not just on behalf of your app, but on behalf of your users, individuals. Here's what this looks like in practice.

On the left, you see a pattern that's very common, an agent calling an API using a shared key pulled from an environmental variable. That key probably gets reused across users, environments, maybe even different services. It works, but it's fragile.

Patterns3:10

Bobby Tiernay3:27

You can't tell who did what, and rotating secrets and keys is manual and risky, and the access is way too broad. On theright, things are looking better. Instead of a shared static key, the agent asks your backend for a token that's just for the one user and one API.

The backend uses something like token exchange to hand out short-lived tokens, and the agent can safely use that. Now you've got a real record of who did what, and you can easily rotate tokens, support multiple upstream systems, and manage all of this in a centralized way.

We've seen that this approach scales much better even if you have dozens or hundreds of agents. It's a small tweak in your flow, but a big step up in how you handle risk. We've talked about the secrets and shared credentials problem, but underneath it all is identity.

If your agent doesn't have identity, it doesn't matter how well you scope your tokens or rotate tokens, you still don't have real control here. Identity is what connects actions to users. It lets you understand what happened, trace the activity, and decide what should happen next.

Identity4:18

Bobby Tiernay4:34

But before we talk about delegation and scope, we need to get identityright. If identity is the part we're often missing, the next question is, who is the agent actually working for? If you don't have a clear answer, chances are it's just running as a service account, and that's how you get the confused deputy problem that you've been hearing a lot about this week.

The agent has access, but it doesn't know who it's acting for, what it should avoid. The fix is to anchor that behavior into real users using standard flows like OAuth 2.1, RAR, and token exchange to tightly control what the agent can do.

That includes refreshing tokens properly and preserving upstream identity. Here's how it works in practice. When an agent needs to act, it doesn't grab a key from a static config. Instead, it asks your backend for help. The backend reaches into a vault, fetches a credential, and uses token exchange to mint a token that's short-lived just for this user and API.

That token never sits with the agent. It's handed off, used, and gone. This keeps your agent focused on doing its job, not carrying around secrets. It lines up with familiar OAuth standards, so you're not inventing the wheel, which you should never do with identity.

Let's shift gears now to the RAG systems. When you're using RAG, you're not just handing data to the model, you're making choices about what it sees. Not every user should unlock the same data context. This is where fine-grained authorization matters.

RAG5:48

Bobby Tiernay6:02

You don't want the agent deciding access inside your LLM. You want that enforced much earlier at the retrieval layer where policy enforcement can kick in. You want to do this so that none of your sensitive data leaks out, and you keep your company and your users secure.

CIBA6:22

Bobby Tiernay6:22

Earlier we covered how to scope access, which agent can see, but sometimes that's not enough. You also need to control when and how that access is provisioned. That's where client-initiated back-channel authentication, which is a mouthful, or SIBA comes in.

Instead of showing a UI, the agent sends a request to the authorization server. The server reaches out to the user on a trusted device via something like a push notification, and then the user decides whether to approve, deny, or ask for more information.

This pattern is really great for agents running in the background or in scenarios where there's no screen to direct the user to. Kam's going to show the demo where this really comes to life. Keep this flow in the back of your mind when you see that.

Of course, we can't talk about secure agent execution without talking about MCP. MCP servers are showing up everywhere these days. What started as local standard I/O input on your laptop is quickly turning into a core part of remote distributed systems.

MCP7:08

Bobby Tiernay7:25

Once you put it on the network, security can't be an afterthought. This pattern here uses OAuth 2.1 flow. The user signs in through the browser, MCP server handles the token minting behind the scenes, agent gets scoped and bound upfront, and the token is issued.

The client never exposes third-party credentials. The key takeaway is that when every tool and action runs on a shared server, the need for solid guarantees about who's making each request and doing what they're actually doing becomes critical. To bring this all together, Kam's going to show what this looks like in practice.

He's going to go through the SIBA flow in an example. Kam, over to you.

Demo8:04

Kam Sween8:04

Sweet. Thanks, Bobby. A lot of talking points. This is going to be a challenging demo. Thanks for outlining some of the security and identity challenges that are facing production-grade AI agents. Building on that overview, you can actually find this demo alongside a ton of other really great working demos at the following URL that I've got highlighted in the package.json of this little application.

For our scenario, we're going to do a local AI trading assistant that's going to make local tool calls to a broker service in order to buy stock. We tried to make this as applicable as possible. The AI agent is going to initiate the request, but the user is going to have to explicitly approve it before it's executed.

I don't have enough screens, so I'm going to pull another one up. This will be really fun. Bear with me. This is going to really emphasize three critical components for us. We're going to have user identification and context, which is going to identify the user so that the agent can act on their behalf.

We're going to use the token vault to prevent us from embedding any kind of secrets or sensitive data inside of our actual code. Then we're going to use SIBA or client-initiated back-channel authentication to request user consent before the agent executes sensitive actions.

It's worth highlighting, this is going to require an identity provider that supports SIBA. Auth0 is the company we work for. But importantly, like SIBA is part of the OIDC specification, so this is going to become more ubiquitous over time.

Taking a look at the app that's driving this demo,

zoom out a couple here. Catalog IntelliJ, I'm going to hide this too. There we go. We're using a pretty simple TypeScript CLI application. Anybody speak TypeScript in the room? Show of hands. Few. Okay. Allright. The Python demo will come later.

This is basically just going to expose a command line interface for the user, which is configured with a stock trading tool. Let me make sure that a couple of prereqs that I need are true. Bear with me one second.

Allright. I do not see what I'm looking for, but that should be fine, hopefully.

Rolling back. In a more mature trading environment, it would probably look something like this. You'll have this user who's going to specify buy some stock at a certain threshold, which will get dispensed as a user action that'll interface with your chatbot.

There'd be some sort of polling system that would be capable of understanding what the real-time value of that stock trade is over time. Then at the time where whatever threshold is defined, at that point, it would then execute the trade.

Prior to executing the trade, it would dispatch a SIBA request to make sure that the user is able to authenticate that at the last mile. Now, with today's stock volatility being what it is, it'd be a real challenge to define any reliable trade rule based on vibes and truth social posts.

We're going to alide certain elements of this stack. That was a joke. I hope you enjoyed that. Stay on the script now. We're going to take a look at the actual application. This is the primary agent configuration and runtime definition inside of this stack.

You can see it's bifurcated into two primary methods. You've got the generate messages method, which is basically the handler that's interfacing between the LLM and the user. Here, we're passing in this buy tool, which we're going to dig into a little bit more.

Then subsequent to that, you have the main method, which is going to run on the main thread. Here's where we're going to define the context and bind it to a particular thread for this particular session. This is going to give us the ability to durably identify who is using this particular

session. Within that, let's take a look at the actual tool call. Here we have the definition of a tool call. Instead of this application, you'll note that it's wrapped in two higher-order component functions. There's this use device flow.

Taking a look at that, this is basically how it is that we are bootstrapping the OIDC wrapper within this application. That's going to enable us to have an auth client bootstrap for the application. This enables me to use access tokens on behalf of a user, basically.

There's a whole lot of configuration that goes into that. Stepping back, there's another handler, this use SIBA higher-order component. This is basically going to enable this application to intercept a tool call in which we want the user to be able to approve or deny behavior.

That's really the heart of SIBA. It's also where we provide configuration information to our identity provider about how we're going to use the resources. In our case, we're using a blocking callback down here, which is going to actually pause the application while it's running in order to wait for the approval.

You could wire this up with an asynchronous flow or polling or however you wanted to, but for the sake of this demo, this was a lot easier. One last thing that I'll highlight here, inside of the buy tool call, the way that we're handling credentials here on line 28, this prevents us from embedding client secrets directly inside of the code, which is a nice utility method.

In Auth0, we call this our token vault. It's dissimilar from like 1Password or like a credential manager. This is managing tokens, not credentials. Just a little bit of a note there. Let's get these services running. Fingers crossed we don't run into any super fun Wi-Fi issues.

May the Wi-Fi gods be forever on our side. As that comes up, even with local AI agents, identity matters, especially when you're using multiple users with multiple agents involved or if the agent has access to user data or user files.

It's crucial to know who is interacting with what and at what time, especially once compliance gets into this, it gets a lot more robust. We're not using a fully stateful service to preserve and persist the user's identity. Instead, we're going to authenticate the user through the UI.

You'll notice that little blurb will pop up. After that, when the AI agent needs to perform a sensitive action, like executing a trade, we're going to rely on SIBA. That means no additional user-facing UI is required after the user has given us their tokens.

I'll give you a little bit of a demo of that. We're definitely aware that identity standards like OAuth 2.0, OIDC, SIBA, these are not always top of mind or super interesting for developers when you're building great applications. That's why we're highlighting that there are solutions to these problems.

There's open standards that are evolving over time, and a lot of those are live today. That can be something to be thought of in the progenition of an application instead of as an afterthought. One thing that we run into repeatedly while building this demo is determining just how much complexity is needed to effectively showcase these sorts of scenarios.

Please let us know how we struck that balance. You can email Bobby directly. He loves feedback. Allright. Now for the fun part, let's try and buy some stocks with this. If the Wi-Fi gods are on our side, buy me 10 stocks of CICO, just some company.

What this is going to do is the LLM is going to process the intent and it's going to select the buy stock tool. The agent is going to send, I love Wi-Fi, it's my favorite thing. Let's see if there isn't a way around.

I can just sort of talk through this at a high level. We'll take a look at this piece of our demo. What would have ideally happened is we would execute that trade because we had bootstrapped our middleware inside of this application.

It would prompt me to log in. Once I logged in, then the agent would have tokens to use on my behalf as a user. That would then execute a trade. It's not actually executing a trade. I have like a local trade service running, so you're not missing many highlights.

Don't worry. Then once I authenticated, then SIBA would immediately dispatch a notification to Auth0's backend and it would blow up my phone and I would get a little notification that's like, hey, would you like to approve and authorize this trade?

One nice thing about the notification that I get is it's not just going to tell me, hey, something happened, would you like to approve it? I'm just going to be left generically in the middle of the ether trying to figure out where this notification came from.

It's actually going to say this agent tried to do this action, which in this case is purchasing 10 shares of something on your behalf. Would you like to approve that downstream flow? Then I have the autonomy as an end user to determine whether or not I'm going to advance that flow or cancel that flow.

One other thing that I would have shown is once I've authenticated the agent to act on my behalf, subsequent trades no longer need me in the loop outside of the SIBA flow. Once I've authenticated in, the authorization flow is then just dispatched to SIBA, which is pretty cool.

Going back to my notes, let me see how many things that I missed. A bunch of things, but that's okay. In summary, we saw, well, kind of I talked through how an agent can identify and act on behalf of a specific user, how to store access credentials securely, and how to use SIBA to get explicit user approval for high-risk actions like trading without a browser to be required.

These patterns are live. They exist in defined standards like OIDC, SIBA, rich authorization requests, Auth0 developer previews have attempts at a lot of these things or actual production versions of a lot of these things. I'd encourage you guys to check some of those things out.

Some of these are GA, like our SIBA, I believe, is GA or at least in early access inside of our platform. That's pretty cool. Thanks. That's my demo.

Bobby Tiernay17:05

Allright. Just moving back here, go to the next slide.

Outro17:05

Kam Sween17:08

Cool.

Bobby Tiernay17:11

As Kam was saying, we're trying to make this easier for developers. The standards are great. It means you're not reinventing things over and over again, but there's still a lot of building blocks that you would have to build.

Auth0 and other platforms have similar things, but we're trying to wrap this all up in a nice experience for developers. The async user confirmation with SIBA is like a very key component here, as well as calling APIs on BAF users, things like token exchange and token vault, as well as fine-grained authorization for RAG.

You don't have to use our platform for this. We have OpenFGA that can snap into this type of thing as well. User authentication and authorization generally is something that we do, we think deeply about. With that,

here's what you can take with you. It's a nice QR code. We'd love to talk to anyone who's struggling with these challenges, what you've hit in your day-to-day life. Just come talk to us after the talk. I'm also part of the OpenMCP spec, driving some of those discussions as well.

We're very interested in improving that for everybody. It's not just about Auth0, working with other open source libraries like MCP Auth, which is another great thing. Very deeply interested in this space.

Kam Sween18:35

Thanks.

Bobby Tiernay18:35

Thank you.