DEV Community

Vihaan Gupta
Vihaan Gupta

Posted on

AuthLM: Why Your LLM Router Shouldn't Also Be Your Credential Manager

I've now written the same OAuth device-code flow three times, for three different AI providers, in three different projects. Each time I copy-pasted from the last one and adjusted for whatever quirks the new provider had. Each time I got the refresh-token rotation slightly wrong somewhere, because it's a boring detail that's easy to skip until a token dies in production for no obvious reason.

That's the actual reason AuthLM exists.

Auth keeps getting treated as an afterthought

Look at how most tools handle credentials for AI providers today:

  • Plaintext JSON in a config file (llm keys's approach)
  • Read straight from environment variables and hope nothing rotates
  • Hand-rolled OAuth, once, buried inside whatever router or agent framework you're building None of that is really inference's job. An inference library's job is to send a prompt and get tokens back. Whether your OpenAI key still works, whether your Anthropic OAuth token needs a refresh, or where the secret is actually stored is a different problem with different failure modes. It deserves its own layer instead of getting bolted onto whichever router you picked.

What "auth-only" actually means

AuthLM does exactly one job: get you a working, validated credential for a provider, and get out of the way. It doesn't route requests, pick models, or care what you do with the credential afterward. Its API surface is deliberately narrow:

import authlm
from datetime import timedelta
from openai import AsyncOpenAI

await authlm.connect("openai", alias="default", method_id="api_key")

cred = await authlm.get_valid_credential(
    "openai", alias="default", margin=timedelta(minutes=5)
)

client = AsyncOpenAI(api_key=cred.secret)
Enter fullscreen mode Exit fullscreen mode

That's it. Whatever you use for actual inference — LiteLLM, the raw SDKs, llm — plugs in on the other side of cred.secret.

The parts that are actually annoying to build yourself

A few things AuthLM handles that are easy to get wrong on your own:

OS keychain storage by default. macOS Keychain, Windows Credential Manager, Linux Secret Service, via keyring. Falls back to an encrypted file (Fernet, PBKDF2 at 600k iterations) when no keychain is available, not to plaintext.

Refresh token rotation, done atomically. Some providers rotate the refresh token on every use. Persist the new access token but drop the new refresh token, and your next refresh fails with a dead token and no obvious reason why. AuthLM centralizes this so it only has to be correct once.

Multiple accounts per provider. Credentials are keyed by (provider, alias), so a personal and a work OpenAI key coexist without you inventing your own namespacing scheme.

Fingerprint-based drift detection. AuthLM stores a truncated hash of the secret alongside the metadata, so authlm status can flag when a credential changed outside of AuthLM — manual rotation, keychain edits — instead of silently working off a stale assumption.

Validation that's never automatic. validate() makes a real API call to confirm a credential still works, but only when you explicitly ask for it. No surprise network calls on every connect() or list().

What it isn't

AuthLM isn't a model router, isn't a SaaS-auth platform, and isn't a secret broker for running agents. For those, use LiteLLM, Nango or Composio, or Infisical Agent Vault, respectively. The whole pitch is doing one narrow thing well and composing with whatever you already use for the rest.

It's also genuinely early. v0.1.0 ships four first-party providers (OpenAI, Anthropic, Google, OpenRouter), three connection methods, and a five-command CLI. There's no plugin system yet, no long tail of providers, no Vault or 1Password backend. Those are roadmap items, not things in the box today — I'd rather undersell what's here than have you find out the hard way.

Try it

pip install authlm
Enter fullscreen mode Exit fullscreen mode

It's Apache-2.0, on PyPI, and the source is at github.com/vihaan-g/AuthLM. If you've hit the refresh-token-rotation bug yourself, or think auth-only is the wrong call and this should just live inside a router, I'd genuinely like to hear the argument — open an issue or reply here.

Top comments (0)