rustauth-stripe
Server-side Stripe billing integration for RustAuth.
What It Is
rustauth-stripe adds Stripe customer and subscription behavior to an
RustAuth server. It is server-side only: browser helpers should call the HTTP
endpoints exposed by this plugin.
What It Provides
- User and organization Stripe customer linking.
- Customer creation on sign-up.
- Checkout Session creation for subscription upgrades.
- Subscription cancel and restore endpoints.
- Billing portal session creation.
- Active subscription listing.
- Stripe webhook signature verification.
- Local subscription synchronization from checkout and subscription lifecycle webhooks.
- Schema contributions for
user.stripeCustomerId,organization.stripeCustomerId, andsubscriptionstorage.
Quick Start
use ;
use RustAuth;
let auth = builder
.secret
.base_url
.plugin
.build?;
# let _ = auth;
# Ok::
Run your adapter migration flow after enabling the plugin so the Stripe fields and subscription table exist.
Endpoints
When subscriptions are enabled, the plugin registers:
POST /subscription/upgradePOST /subscription/cancelPOST /subscription/restoreGET /subscription/listGET /subscription/successPOST /subscription/billing-portalPOST /stripe/webhook
Mount these under your RustAuth base path. With /api/auth, Stripe webhooks
should target /api/auth/stripe/webhook.
Webhooks
The webhook endpoint validates the stripe-signature header with the secret
passed to StripeOptions::new. Use the signing secret from the Stripe dashboard
as-is (including the whsec_ prefix); the plugin uses it verbatim as the HMAC
key, matching Stripe's official libraries.
It currently handles checkout completion and subscription created, updated,
canceled, and deleted events.
Use StripeOptions::on_event when your application needs to observe raw Stripe
events after RustAuth has processed them.
Database hooks that create or sync Stripe customers are best-effort: failures are not returned to the sign-up or update flow, so monitor Stripe API errors in your application logs if you rely on automatic customer creation.
Organization Billing
use ;
let options = new
.organization;
Lifecycle hooks accept plain async closures (no Box::pin at the call site):
use ;
let options = new.subscription;
Organization support contributes organization.stripeCustomerId and uses the
organization as the billing reference when requests specify
customerType = "organization".
Testing
Tests can inject a fake transport without network calls:
use StripeClient;
use Arc;
let client = with_transport;
Test-mode smoke (manual)
For end-to-end validation against Stripe test mode (real API + Checkout + webhooks), use the server-side runbook — no example app required:
- SMOKE.md — full checklist, env vars, DB checks, log grep patterns
- .env.smoke.example — template (copy to repo root
.env) scripts/stripe-smoke.sh— env checks and CLI/curl hints
Database hooks are best-effort. Built-in webhook handlers skip non-actionable events, but retryable processing failures return an error so Stripe can retry. During smoke, grep logs for the messages listed in SMOKE.md §10.
Status
Experimental beta. Customer, subscription, billing portal, and webhook behavior exist, but public APIs may change before stable release.
Stripe failures during database hooks (sign-up customer, email sync, seat sync)
are best-effort: they are logged and do not fail the underlying user operation,
matching Better Auth 1.6.9. Built-in webhook handlers skip non-actionable events,
but retryable processing failures and the optional on_event hook can fail the
webhook response.
Webhook events handled
Built-in handlers (non-actionable skips return HTTP 200; retryable processing failures return an error so Stripe can retry):
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updated(includes cancel-at-period-end sync)customer.subscription.deleted
Other event types invoke on_event only; a failing on_event returns STRIPE_WEBHOOK_ERROR.
Organization billing
customerType: "organization" requires configuring .authorize_reference(...) on SubscriptionOptions. Without it, endpoints return AUTHORIZE_REFERENCE_REQUIRED.
Better Auth compatibility
Server-side Stripe billing plugin. Aligned with Better Auth 1.6.9 where it matters; RustAuth is not a line-by-line port. For route-level parity, test counts, differences, and gaps, see UPSTREAM.md.
Links
- SMOKE.md — test-mode manual smoke checklist
- Root README
- Repository