Hi, everybody. I'm Bobby. This is Cam, and we're both engineers here at Auth0, and 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 world where agents are center stage. So that's included our work on our Auth4Gen AI platform, our Auth0 MCP server, and our own first-party agent called Tenant Security Manager.
And 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. And 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 access right from the start.
But I had to splash this slide because we were told we could have opinions as long as we showed it. So 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. And once they're moving beyond chat and actually doing things in the real world, cracks are starting to appear, and it's pretty clear.
Secrets end up in prompts, scopes get too broad, and troubleshooting gets really, really hard when you don't have the right visibility. So 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 surface right 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 Gen AI risks begin. The OAuth calls it excessive agency, but really that's just a fancy way of saying giving agents too much access without guardrails. And 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.
And there's other OAuth risks too, like sensitive data exposure, but that often comes back to the same root cause. If an agent reaches it into something it shouldn't, it's usually because no one told it not to. And 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. And that means they're moving through your stack, touching real user data, interacting with real external systems. And all needs to happen under the right 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, and 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. You can't tell who did what, and rotating secrets and keys is manual and risky.
And the access is way too broad. On the right, things are looking better. Instead of a shared static key, the agent asks your back end for a token that's just for the one user and one API. The back end uses something like token exchange to hand out short-lived token, 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. And 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.
So 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. And identity is what connects actions to users. It lets you understand what happened, trace the activity, and decide what should happen next.
But before we talk about delegation and scope, we need to get identity right. So if identity is the part we're often missing, the next question is, who's 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.
And here's how it works in practice. When the 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 in API.
That token never sits with the agent. It's handed off, used, and gone. And this keeps your agent focused on doing its job, not carrying around secrets. And it lines up with familiar OAuth standards, so you're not inventing the wheel, what you should never do with identity. And 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. And not every user should unlock the same data context. This is where fine-grained authorization matters. You don't want the agent deciding access inside your LOM. You want that enforced much earlier at the retrieval layer where policy enforcement can kick in.
So you want to do this so that none of your sensitive data leaks out and you keep your company and your users secure. Early 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 CBA 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 a user to. And Cam's going to show the demo where this really comes to life. So keep this flow in the back of your mind when you see that. And 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. And 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 up front. And the token is issued. The client never exposes third-party credentials. The key takeaway is that when every tool in 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.
All right. So to bring this all together, Cam's going to show what this looks like in practice. He's going to go through the CBA flow, an example. Cam, over to you. Thanks, Bobby. A lot of talking points. This is not going to be a challenging demo. So thanks for outlining some of the security and identity challenges that are facing production-grade API agent or AI agents.
Building on that overview, you can actually find this demo alongside of 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.
Right? 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. I'm going to pull another one up. This will be really fun. Bear with me.
All right. So this is going to really emphasize three critical components for us. So 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 like, you know, secrets or sensitive data inside of our actual code.
And then we're going to use SEBA 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 SEBA. You know, our Auth0 is the company we work for. But importantly, like SEBA is part of the OIDC specification.
So this is going to become more ubiquitous over time. So taking a look at the app that's driving this demo. Zoom out a couple here. Cattle of IntelliJ. I'm going to hide this too. There we go. Okay. So we're using a pretty simple TypeScript CLI application. Anybody speak TypeScript in the room?
Show of hands. View. Okay. All right. All right. The Python demo will come later. So 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. All right. I do not see what I'm looking for. But that should be fine, hopefully. So rolling back in a more mature trading environment, it would probably look something like this. So you'll have this user who's going to specify, you know, buy some stock at a certain threshold, which will get dispensed as a user action that'll interface with your chat bot.
There'd be some sort of polling system that would be capable of understanding what, like, the real-time value of that stock trade is over time. And then it would, at the time where whatever threshold is defined, at that point, it would then execute the trade. And prior to executing the trade, it would dispatch a CBA request to make sure that the user is able to authenticate that, right, 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 true social posts. So we're going to elide certain elements of this stack. That was a joke. I hope you enjoyed that. Stay on the script now.
So we're going to take a look at the actual application. So 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. So within that, let's take a look at the actual tool call. So 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.
So there's this use device flow. Take 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.
So there's a whole lot of configuration that goes into that. Stepping back, there's another handler, this use CBA high order component. So this is basically going to enable this application to intercept the tool call in which we want the user to be able to approve or deny behavior. And that's really the heart of CBA.
It's also where we provide configuration information to our identity provider about how we're going to use the resources. So 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 one password or like a credential manager. This is managing tokens, not credentials. So just a little bit of a note there. So 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, so 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, you know, user data or user files, right? So it's crucial to know who is interacting with what and at what time, especially like once compliance gets into this, it gets a lot more robust.
So we're not using a fully stateful service to preserve and persist the user's identity. So instead, we're going to authenticate the users through the UI. So you'll notice that a 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 SEBA.
That means no additional user-facing UI is required after the user has given us their tokens. And I'll give you a little bit of a demo of that. So we're definitely aware that identity standards like OAuth 2, OIDC, SEBA, 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. So that can be something to be thought of in the progenation of an application instead of as an afterthought. So 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. All right. So now for the fun part, let's try and buy some stocks with this. If the Wi-Fi gods are on our side. So buy me 10 stocks as well. So 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. So what would have, you know, ideally happened is we would execute that trade because we have bootstrapped our middleware inside of this application.
It would prompt me to log in. And 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. And then once the trade, or once I authenticated, then CBA 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?" And 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?" And 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 CBA flow.
So once I've authenticated in, the authorization flow is then just dispatched to CBA, which is pretty cool. So going back to my notes, let me see how many things that I missed. A bunch of things, but that's okay. So 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 and access credentials securely, and how to use CBA to get explicit user approval for high-risk actions like trading without a browser to be required.
So these patterns are live. They exist in defined standards like OIDC, CBA, rich authorization requests, Auth0 developer previews have, like, attempts at a lot of these things or actual production versions of a lot of these things. So I'd encourage you guys to check some of those things out. And some of these are GA, like our CBA, I believe is GA, or at least in early access, instead of our platform.
So that's pretty cool. Thanks. That's my demo. All right. So just moving back here, go to the next slide. Cool. But as Cam was saying, like, 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.
The Auth0, other platforms have similar things. But we're trying to wrap this all up in a nice experience for developers. So the async user confirmation with CBA is, like, a very key component here, as well as calling APIs on BAP 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. And user authentication and authorization generally is something that we do. We think deeply about. And with that, here's what you can take with you. It's a nice QR code.
And 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 open MCP spec, driving some of those discussions as well. We're very interested in improving that for everybody. So it's not just about Auth0, working with other open source libraries like MCP auth, which is another great thing.
So very deeply interested in this space. Thanks. Thank you. Thanks. Thank you.