Ah, this is great feedback -- I don't think we do enough to articulate how much we're doing beyond that simplified explanation of device fingerprinting on those docs. I'll get that page updated, but 2 main things worth mentioning:
1. We have a few proprietary fingerprint methods that we don't publicly list (but do share with our customers under NDA), which feed into our ML-based browser detection that assesses those fingerprint data points against the entire historical archives of every browser version that has been released, which allows us to discern subtle deception indicators. Even sophisticated attackers find it difficult to figure out what we're fingerprinting on here, which is one reason we don't publicly document it.
2. For a manual attacker running attacks within a legitimate browser, our Intelligent Rate Limiting (IntRL) tracks and rate-limits at the device level, making it effective against attackers using a real browser on their own machine. Unlike traditional rate limiting that relies on brute traits like IP, IntRL uses the combo of browser, hardware, and network fingerprints to detect repeat offenders—even if they clear cookies or switch networks. This ensures that even human-operated, low-frequency attacks get flagged over time, without blocking legitimate users on shared networks.
CAPTCHAs have been ineffective as a true "bot detection" technique for a while as tools like anti-captcha.com allow for outsourcing it to real humans. BUT they have been successful at the economic side of raising the cost of programmatic traffic on your site (which is good enough for some use cases)
As the author of this agent detection post, we agree that CAPTCHA and vanilla browser/device fingerprinting is quickly not going to be very valuable in isolation, but we still see a lot of value in advanced network/device/browser fingerprinting
The main reason is that the underlying corpus & specificity of browser/device/network data points you get from fingerprinting makes it much easier to build more robust systems on top of it than a binary CAPTCHA challenge. For us, we've found it very useful to still have all of the foundational fingerprinting data as a primitive because it let us build a comprehensive historical database of genuine browser signatures to train our ML models to detect subtle emulations, which can reliably distinguish between authentic browsers and agent-driven imitations
That works really well for the OpenAI/BrowserBase models. Where that gets tricky is the computer-use agents where it's actually putting its hands on your keyboard and driving your real browser. Still though, it's valuable to have the underlying fingerprinting data points because you can still create intelligent rate limits on particular device characteristics and increase the cost of an attack by forcing the actor to buy additional hardware to run it
Very much agreed that's the long-term goal, but I think we'll live in a world where most apps don't support oauth for a while longer (though I'd love for all of them to -- we're actually announcing something next week that makes this easy for any app to do)
But we're also envisioning an interim period where users are delegating to unsanctioned external agents (e.g. OpenAI Operator, Anthropic Computer Use API, etc.) prior to apps catching up and offering proper oauth
LinkedIn always hits me with those frustrating custom CAPTCHAs where you have to rotate the shape 65 degrees -- they've taken a pretty blunt, high-friction approach to bot detection
I think most apps should primarily start with just monitoring for agentic traffic so they can start to better understand the emergent behaviors they're performing (it might tell folks where they actually need real APIs for example), and then go from there
Hey there, I'm the author of the post. I'm actually pretty sympathetic to your viewpoint, and I wanted to clarify my stance.
I actually spent years working at a "good bot" company (Plaid), which focused on making users' financial data portable. The main reason Plaid existed was that banks made it hard for users to permission their data to other apps -- typically not solely out of security concerns, but to also actively limit competition. So, I know how the "bot detection" argument can be weaponized in unideal ways.
That said, I think it’s reasonable for app developers to decide how their services are consumed (there are real cost drivers many have to think about) -- which includes the ability to have monitoring & guardrails in place for riskier traffic. If an app couldn't detect good bots, that app also can't do things like 1) support necessary revocation mechanisms for end users if they want to clawback agent permissions or 2) require human-in-the-loop authorization for sensitive actions. Main thing I care about is that AI agent use remains safe and aligned with user intent. For your example of an anonymous read-only site (e.g. blog), I'm less worried about that than an AI agent with read-write access on behalf of a real human's account.
My idealistic long-term view though is that supporting AI agent use cases will eventually become table stakes. Users will gravitate toward services that let them automate tedious tasks and integrate AI assistants into their workflows. Companies that resist this trend may find themselves at a competitive disadvantage. Ultimately, this has started to happen with banking & OAuth, though pretty slowly.
We built Stytch's B2B SaaS solution with this specific shortcoming in mind -- most other solutions aren't actually built with an organization-first data model (they're user-first like Auth0 but support the general concept of orgs), which makes it difficult to offer those per organization controls in an ergonomic manner.
To your point, the market will decide, but I'm hopeful passkeys will ultimately be one of the key solutions here. Already seeing a lot more app adoption (e.g. Shopify, Google, Docusign) than original webauthn given some of the UX problems that brought with it
Co-founder of Stytch (http://stytch.com/) here -- would love to see if you think we're a fit. We have a generous free tier and we're more reasonably priced that tools like Auth0, but not as cheap as tools like Cognito + Firebase auth. If pricing is a concern, would love your feedback on your optimal cost-structure as we have some startup programs and are always looking to make pricing more compelling for early-stage projects.
TL;DR as a dev tools company, we took a lot of inspiration from how Stripe built their product, including their very simple approach to self-serve pricing. However, we found there are some key reasons this approach doesn't translate well to our market and actually led to worse customer outcomes overall.
By removing some of the simplicity in our pricing model, we were able to reduce costs for 90% of our pay-as-you-go customer base.
> this worked for a little bit longer, but he proceeded to get on a VPN, and then another when i blocked that IP, then another when i blocked that IP, etc, etc.
Beyond VPNs, I've even seen attackers leverage residential IP networks which makes VPN detection ineffective as well [1]. If you ever need a more permanent identifier to ban users on, consider using a device/browser fingerprinting tool [2]. It helps avoid the whack-a-mole issue of more sophisticated attackers churning IPs/emails/user agents/etc.
Also, a tip for anyone that feels like the low hanging fruit prevention methods aren't working (e.g. CAPTCHA, rate limits, etc.)
Consider installing a device fingerprinting system -- this has be the single most effective solution we've seen our customers integrate for more sophisticated bot problems: https://stytch.com/docs/fraud#device-fingerprinting. I'd recommend against the off-the-shelf solutions (e.g. open source ones) because many of them are easily reverse engineered, so they work well for low-level threats but not for persistent ones. In addition to our solution, Arkose and Fingerprint Pro are a couple ones I'm aware of
I find it particularly frustrating that they force you to upgrade to Verify to solve the problem unless you want to build out a lot of your own internal risk detection (which we ended up doing instead)
With the rise of AI APIs, I expect we'll see similar attack vectors for apps that integrate APIs from OpenAI or Stability. There won't be a colluding telecomm, but the API output (a completed task) is relatively fungible and far more valuable in itself than a SMS API response. Something to keep in mind if you're building an AI application: https://stytch.com/blog/securing-ai-against-bot-attacks/
Ah yes, good call out! Didn't mean to exclude Google's contributions to this step forward in auth. I was super excited to read those additional details in Google announcement earlier this week. For those that haven't seen it: https://android-developers.googleblog.com/2022/10/bringing-p...
There have been two main problems with WebAuthn as a primary factor. The first is that the UX experience of WebAuthn as a primary factor - either for "passwordless" or "usernameless" scenarios - has been pretty rough. The WebAuthn W3C group has put together a document that goes into far more detail [1]. One of the items out of that discussion was a standards change [2] that was merged in a few months ago. Now it's up to browser vendors to implement that change over the coming months and years.
The second problem with WebAuthn is that device based authentication has been historically risky for consumer users long-term. It's unreasonable to expect an individual to have access to their phone, yubikey, or laptop over a period of years. In the B2B space, this isn't as big of a deal. Getting an IT admin that works for your company to reset your access and issue a new credential is not a complex problem. Not so in the B2C space. Devices get lost or stolen, and then the service operator needs to build out an alternative recovery method that needs to be as secure as WebAuthn (ideally, without infringing on the user's privacy via KYC methods). New developments like Apple's PassKeys are super interesting and have the potential to really be a game changer for B2C WebAuthn adoption.
In summary, WebAuthn probably can't replace the password for your application today, unless your users are tech savvy and OK with the lock-out risk. However, the space going through some exciting changes and it may be much more feasible in a few years!
No problem – I’m happy to engage in good-faith discussions like this one when there are valid nuances to explore.
One callout I’d like to make is that there are two kinds of SDKs. Client-side ones (like Javascript SDKs) and Server-side ones (NodeJS, Go, Python, etc.). The server-side ones are capable of setting HttpOnly cookies, because the server-side ones run on the server and not in a browser context. This is true for both Auth0 and Stytch, and someone using any of the Stytch server-side SDKs will have HttpOnly protection.
Client-side only SDKs are never capable of setting first-party HttpOnly cookies without the aid of a proxy. In fact, there is no truly secure storage mechanism addressable by clientside javascript. All writable storage is accessible to all javascript loaded in the domain - that is to say that if at any point the Auth0 SDK has access to a token, any XSS attack running in the same document will also have access.
Auth0 has numerous clientside SDKs, but we’ll look at their most popular one - @auth0/auth0-spa-js. This SDK stores refresh tokens in a cache [1] in a few ways:
- By default, in memory, which makes exfiltration harder but still very possible via client-side JS. Wrapping a token in a closure doesn’t mean it isn’t addressable - a hacker can monkeypatch and listen to window.fetch for example. This also means that login state is not preserved across tabs or page refreshes, which is quite frankly extremely frustrating to both developers and users
- Auth0 also supports an iframe based flow, which breaks on browsers that use ITP2 such as Safari [2] - so 20% of all users on desktop and 25% of all users on mobile.
- Finally, for customers who do not want the above restrictions, Auth0 allows localstorage [3] to be configured as a cache storage. Local storage is just as open to XSS exfiltration as non-HTTPOnly cookies.
So while yes, Auth0 does not set cookies, their refresh tokens are still accessible client-side in many common deployment scenarios, and are still vulnerable to the same XSS exfiltration vulnerability that HTTPOnly cookies protect against.
Overall, the main reason that Google’s security team, Auth0’s security team, and our security team are comfortable with offering a non-HTTPOnly session management solution in a JS SDK comes down to:
1. HTTPOnly as a security layer can help prevent exfiltration, but if an app already has an XSS vector, it’s already severely compromised, making such a layer moot.
2. As an auth company (whether you’re Stytch vs. Auth0 vs. Google Firebase), you need to make a decision on how much flexibility you want to offer developers. Our stance is that when additional flexibility and an improved developer experience do not create any practical security risk, we should provide that better developer experience to our customers.