HN user

ymyms

68 karma

building hessra.net: easy identity and authorization for any machine, service, or agent

identity and authorization suck still, and I think its because most tools/protocols are built on crappy primitives. i'm trying to build better ones using biscuits

do you have something you want to give identity and/or fine-grained authorization but it's too much effort? tell me about it. any auth problems at all? i'm happy to help (even if it means you use something other than my thing).

jake@hessra.net

Posts1
Comments39
View on HN

I was shocked by this as well. I think it's a natural property of large organizations and it takes great effort and great leaders to fight it.

The way I think about it is that building something truly successful comes with a tremendous amount of momentum. So much momentum that growth for these companies still occurs.

The people hired into a mature organization are literally there just to keep the lights on and let the momentum do its work. They also create and grow their little fiefdoms.

You can try and build something and innovate there, but it takes a deeply concerted effort to try and sustain it. Even if something is made wildly successful and is growing 50-100% year over year, it still likely pales in comparison to the 0.005% growth of the large core business.

Even if the new innovation is given space to breath, it can be killed at any point by the core business as the fiefdoms look over and say: that should be part of my org, or those resources can be better spent on the core business. So instead of waiting the years it takes for the new, small thing to grow large enough to be important it is easily killed by the parts of the organization just keeping the lights on.

There are definitely salient points in the article and I appreciate its value in imploring us to really stop and consider the ramifications of what this technology might deliver. I think the analogy to cars and the unintended consequences for all manner of society is particularly apt.

That said, the final point is one I take issue with:

For example, I’ve got these color-changing lights. They speak a protocol I’ve never heard of, and I have no idea where to even begin. I could spend a month digging through manuals and working it out from scratch—or I could ask an LLM to write a client library for me. The security consequences are minimal, it’s a constrained use case that I can verify by hand, and I wouldn’t be pushing tech debt on anyone else. I still write plenty of code, and I could stop any time. What would be the harm?

To me, there is no intrinsic value in solving this problem other than rote problem solving reps to make you a better problem solver. There isn't anything fundamental about the protocol they've never heard of that operates the lights. It's likely similar to many other well-thought out protocols in the best case and in the worst case is something slapped together.

There are certainly deeper, more fundamental concepts to learn like congestion control algorithms in TCP. Most things in software though are just learning another engineer's preferences for how they thought to build something.

I poke at this because if an exercise only yields the benefit of another rep of solving a problem, then it holds less water to me. I personally don't think there will be fewer problems to solve with this technology, just a different sort at a different layer of the stack.

I'm making capability security for distributed systems. The primitives and engine are both open source. Primitives: https://github.com/Hessra-Labs/hessra-tokens Engine: https://github.com/Hessra-Labs/hessra-cap

It's built using biscuits and written in rust. I'm really into it. Using capability security as a model makes building things feel like they snap together a lot more naturally. At least for me.

I've also got a blog post describing it in more detail: https://www.hessra.net/blog/what-problem-led-me-to-capabilit...

They apparently are working on and are going to release 2(!) different versions of siri. Idk, that just screams "leadership doesn't know what to do and can't make a tough decision" to me. but who knows? maybe two versions of siri is what people will want.

A human SWE can use an LLM to refactor and reduce some of the debt just as easily too. I think fundamentally, the possible rate of new code and new technical debt introduced by LLMs is much higher than a human SWE. Left unchecked, a human still needs sleep and more humans can't be added with more compute.

There's an interesting aspect to the LLM debt being taken on though in that I'm sure some are taking it on now in the bet/hopes that further advancements in LLMs will make it more easily addressable in the future before it is a real problem.

All code is technical debt though. We can't spend infinite hours finding the absolute minima of technical debt introduced for a change, so it is just finding the right balance. That balance is highly dependent on a huge amount of factors: how core is the system, what is the system used for, what stage of development is the system, etc.

I also feel like it makes me more productive but measuring software engineering productivity is famously difficult. If there was an easy way to measure it, managers at bigco would have employed it with abandon years ago.

Huh? Where did I say that's what I like? I'm just trying to discuss for discussion's sake. Personally, I want a world that rewards the people who put their thought, care, and craftsmanship into something more than those that don't. In order to live in that world, I think we need to discuss the parts (maybe the whole) that don't and why that might be.

I didn't mean to imply LoC as a measurement of productivity. What I really mean is more "amount of useful code produced to a level the human-using-the-llm determines to be useful".

To try and give an example, say that you want to make a module that transforms some data and you ask the LLM to do it. It generates a module with tons of single-layer if-else branches with a huge LoC. Maybe one human dev looks at it and says, "great this solves my problem and the LoC and verbosity isn't an issue even though it is ugly". Maybe the second looks at it and says, "there's definitely some abstraction I can find to make this easier to understand and build on top of."

Depending on the scenario and context, either of them could be correct.

My gut says that is not a property of LLM evangelists, but a property of current internet culture in general. People with strong, divisive, and engaging opinions seem to do well (by some definition of well) online.

I mean, isn't driving the business forward really what matters (outside of academia, open source, and other such endeavors). We live in a hyper competitive market. All else being equal, if company A can produce "millions of lines of slop", constantly living on the knife-edge of disaster but not falling over it, they will beat company B that artificially slows themselves down. Up until the point company A implodes, but that's not necessarily a given if pre-LLM companies are any indication.

"I find LLMs useful as a sort of digital clerk - searching the web for me, finding documentation, looking up algorithms. I even find them useful1 in a limited coding capacity; with a small context and clear guidelines."

I am curious why the author doesn't think this saves them time (i.e. makes them more productive).

I never had terribly high output as a programmer. I certainly think LLMs have helped increased the amount of code that I can write, net total, in a year. Not to superhuman levels or even super-me levels, just me++.

But, I think the total time spent producing code has gone down to a fraction and has allowed me more time to spend thinking about what my code is meant to solve.

I wonder about two things: 1. maybe added productivity isn't going to be found in total code produced, because there is a limit on how much useful code can be produced that is based on external factors 2. do some devs look at the output of an LLM and "get the ick" because they didn't write it and LLM-code is often more verbose and "ugly", even though it may work? (this is a total supposition and not an accusation in any way. i also understand that poorly thought out, overly verbose code comes with problems over time)

I'm working on https://www.hessra.net/

We've built a new auth platform with some new identity primitives and capability-style tokens using biscuits.

Right now, I'm trying to figure out ways to apply it and am looking into offering integrations with extremely fine-grained access control that wouldn't have it otherwise. So adding a fine-grained access layer in front of stuff like backend-for-frontend (BFF) systems, brownfield stuff with poor auth, or even OAuth stuff that just have really coarse scopes.

Are there any integrations out there that people want but the access control is bad for them? I'll build one for you!

You are very on base. In fact, there is a deep conflict that needs to be solved: the non-determinism is the feature of an agent. Something that can "think" for itself and act. If you force agents to be deterministic, don't you just have a slow workflow at that point?

I'm working on https://www.hessra.net/

It's a full identity and authorization platform targeted for service-to-service use cases. But my focus the last couple months has been to make provisioning identity super easy, and I think I've done that (at least compared to something like SPIRE).

So if anybody has CI/CD pipelines, AI agents, edge-functions, or multi-cloud workloads they want to give auditable identity, I can help!

Another benefit is that you can provision ephemeral resources with an identity that has an expiration to match the resource’s lifecycle. Then, you don’t need to figure out rotation at all, just redeploy with a newly minted identity included.

I’ve been working on an identity/authorization system for machines and kept getting stuck on a basic question: what is machine identity, independent of any one stack (Kubernetes, cloud, OAuth, etc.)?

This post proposes a simple model based on where identity originates (self-proven / attested / asserted), what privileges it has at birth, and how it lives over time (disposable vs durable). I’ve also mapped common systems like SSH, SPIFFE/SPIRE, API keys, IoT, and AI agents into it.

I’d be very interested in counterexamples, ways this breaks down in real systems, or prior art I’ve missed.

Building https://www.hessra.net/, an authorization system based on the Biscuit token format (decentralized, signed, and attenuable). The goal is to push beyond JWTs and Zanzibar-style policy engines by giving every machine-to-machine request its own embedded, verifiable authorization logic in a small capability token. These tokens can be delegated, restricted, and verified locally with no extra network calls required after getting the token.

Early use case is replacing API keys with identity tokens that expire, delegate, and prove possession and then can be used for easy step up to fine-grained authorization. There's some pretty interesting authorization stuff you can do, like having multiple parties sign off before a token is valid or requiring a series of micro-services sign a token for it to be valid.

I have the nano-texture display on my M4. At this point, I don't think I can go back to standard glass. For text work, I find there are no downsides. If you work more with color and detailed art, I think that's the only case where you need to put extra thought into it. Otherwise get it

I think my ideal would be a MacBook Air with both the nano-texture and higher 120hz refresh rate the Pro has. With that, I'll trade an extra second of compile time for my rust projects for the smaller form factor.

Another idiomatic pattern is using shadowing to transform something using itself as input:

let x = Foo::new().stuff()?; let x = Bar::new(x).other_stuff()?;

So with the math example and what the poster above said about type changing, most rust code I write is something like:

let x: plain_int = 7

let x: added_int = add(x, 3);

let x: divided_int = divide(x, 2);

where the function signatures would be fn add(foo: plain_int, int); fn divide(bar: added_int, int);

and this can't be reordered without triggering a compiler error.

Biscuits are in the same family as macaroons in that they are bearer tokens that can be attenuated offline, but they go further. A biscuit carries a chain of signed “blocks” that can contain facts, rules, and checks in a small Datalog-like logic language. That lets the token itself express richer authorization context, not just restrictions.

Key differences from macaroons:

- Crypto model: Macaroons use HMAC, so every verifier needs the shared secret. Biscuits use public/private keypairs so any verifier with the public key can check validity.

- Expressiveness: Macaroons only add caveats (restrictions). Biscuits can encode facts, rules, and checks, enabling more complex policies to travel with the token. so you can attest and attenuate (and do some other tricky stuff if you want)

- Delegation: Both support attenuation, but biscuits do it with signed blocks that are verifiable and can be chained across services.

So conceptually similar, but biscuits aim to be more decentralized and policy-rich.

biscuit-based identity and authorization

I’m working on https://www.hessra.net/, an identity + authorization service built around [Biscuits](https://www.biscuitsec.org/) instead of JWTs. The goal is to decompose auth primitives so they’re easier to use in service-to-service cases, while also showing off what Biscuit tokens make possible.

JWTs feel like problems waiting to happen. I think biscuits give stronger guarantees and are harder to get wrong.

One piece I’ve shipped is an identity token that can be delegated offline. For example, “company:alice” can delegate to “company:alice:agent,” and that token can then be used to request an authorization token. This makes for a neat API key model: you can issue a simple opaque identity token to your customer (e.g. “customer123”) without having to maintain a DB of hashes/expirations, since those are encoded into the token. Later, you can upgrade security by exchanging the identity token for an authorization token, or let customers delegate access (e.g. “customer123:marketing”).

I’ve also been experimenting with higher-order authorization flows:

• Service chains: each step in a request’s path (edge → app → DB) can add attestations, so later services can validate the full chain.

• Multi-party authorization: requiring two independent services/orgs to co-sign an authorization token, useful for cross-org or on-prem deployments.

Right now I’m building an OAuth 2.1 profile where the identity token replaces a refresh token and the authorization token stands in for the access token. I’m especially interested in hearing where people find OAuth clunky in practice, or stories from folks who’ve built auth systems with other token types (macaroons, biscuits, etc.) or for use cases where OAuth didn’t fit well.

I agree with pretty much everything the author has said. I’ve been looking at the problem more on the enterprise side of things: how do you control what agents can and can’t do on a complex private network, let alone the internet.

I’ve actually just built an “identity token” using biscuit that you can delegate however you want after. So I can authenticate (to my service, but it could be federated or something just as well), get a token, then choose to create a delegated identity token from that for my agent. Then my agent could do the same for subagents.

In my system, you then have to exchange your identity token for an authorization token to do anything (single scope, single use).

For the internet, I’ve wondered about exchanging the identity token + a small payment (like a minuscule crypto amount) for an authorization token. Human users would barely spend anything. Bots crawling the web would spend a lot.

I'm working on hessra.net, a token-based authorization system for machines and built using biscuits. The idea is that any service/machine/IoT device can authenticate to the service and get authorization tokens for each request based on policy. Then the tokens can be included with the request and verified without any further RTTs using the service's public key. The tokens are meant to be single-use and scoped to a single request.

Besides the simple "get token and send to a thing that uses it to authorize a request" there's a couple of things we've built/are building on top:

service-chains: for a given resource, you can configure the token so that it needs to be signed by notable components along the path of the request, and at each step along the path check that it was signed by expected components up to that point. the thinking is this could really cut down on lateral movement in a system

multi-party authorization: for a given resource, you can configure N authorization services that also need to sign the token based on their policy. the token only authorizes if all parties have signed it. this could be useful for managing capabilities of software deployed into customer environments or perhaps for b2b agents to get signoff from both b's for doing an action

One of my favorite ways to use AI is to get me started on things. I tend to drag my feet when starting something new, but LLMs can whip up something quick. Then I look at what it did and usually hate it. Maybe it structured the code in way that doesn't mesh with the way I think or it completely failed to use some new/esoteric library I rely on.

That hate fuels me to just do the work myself. It's like the same trick as those engagement-bait math problems that pop up on social media with the wrong answer.

This is a goldmine of a thread. Thanks for linking it. In it at some point, you say,

"I tend to be pretty chill about little islands of mTLS, like "all the Consul clients need a cert". That, to me, solves a practical problem. I am way less chill about attempts to create coherent PKI namespaces for all the components of an app, tied together with mTLS.

People should use Macaroons!" along with some earlier bits about mTLS not affording much security if you have secure requests.

I've been thinking about machine identity+authorization and thus far have been thinking about it in a way where a machine would have some firm identity (like an X.509 cert) and use it to authenticate (like using mTLS) to get an authorization token.

Maybe I am putting words in your mouth, but do you sort of suggest skipping the identity part and just leaning into a full capability token? In this case macaroon, that acts as identity and then acts as authorization when attenuated and used?