Building AIP: An ATProtocol Authorization Gateway

AtmosphereConf was an incredible experience. The people, talks, and energy were everything I hoped they’d be. The days since have been harder. Some difficult conversations and difficult decisions have come out of the conference, and I’m still processing a lot of it. I don’t want to dwell on that here; it doesn’t feel good. Instead, I want to look back at the work we did at Graze Social and share the parts that feel good. This is one of a series of posts doing that.

OAuth is the first challenge most developers face when building in this space. If you want to make an app and need users to sign in, you quickly find yourself dealing with token management, identity resolution, and XRPC proxying before you even start on your main product. AIP was created to help organize that process.

The idea grew out of many talks with Devin, Boris, and others in the ATProtocol developer community. While explaining some of the OAuth work I was doing, I realized OpenID Connect was much easier to set up than I thought. Having one configured endpoint as an authorization gateway would simplify things for everyone—not just for ATProtocol apps, but for anything that already uses OIDC.

That ended up being the best part. AIP works with Discourse, WordPress, Matrix, and existing OIDC libraries, and none of them need to know anything about ATProtocol. The ATProtocol Community Discourse has used it since we set it up, and no one even notices. It’s tech that works quietly in the background, and that feels great. I’m really happy with the result.

The Rust Port

AIP began as a Python app that used Redis for both queuing and caching. It mostly worked, but I had trouble getting token refresh to work reliably. Eventually, I decided to rewrite it in Rust and use some of the OAuth code I’d already built for Smoke Signal.

This was one of the first Rust components in the Graze Social tech stack, so there was a lot to figure out beyond the code itself. Building, configuring, deploying, and fitting it into the existing infrastructure all had to be worked out. I really appreciate Casey’s patience and support through all of that.

Switching to Rust paid off in ways I didn’t expect. The ATProtocol flavor of OAuth has a lot of edge cases, especially with identity resolution and management. Working through these made the whole process second nature. After a year of building, testing, deploying, and fixing bugs in AIP, explaining OAuth to other developers became much easier.

Teaching

That confidence led to the OAuth Masterclass and later the OAuth workshop at this past AtmosphereConf. The material wasn’t something I sat down and designed from scratch. It grew out of the accumulated experience running AIP in production and handling all the strange edge cases. After fixing token refresh issues so many times, explaining it just became natural.

What I Learned

It’s been great to see people start using AIP. I’ve found about a dozen cases where other developers and teams are using it, which is more than I expected for a piece of infrastructure.

The work that surprised me most was with MCP and agentic platforms. AIP fully supports agent authentication using dynamic client registration (RFC 7591), which is key for authenticated agents in this space. Developing and testing this taught me a lot about how agentic systems work with OAuth, and that experience has been really valuable.

I’m proud of AIP. The Masterclass, the workshop, and the agent authentication work all came from spending a lot of time on this problem and making sure we got it right.

AIP is open source under the MIT license.

GitHub - graze-social/aip: ATmosphere Authentication, Identity, and Permission Proxy

ATmosphere Authentication, Identity, and Permission Proxy - graze-social/aip