Firebase and Clerk
Firebase Authentication
Firebase Phone Auth sends its verification SMS itself. Its documentation offers no way to plug in your own SMS sender for that flow, so Bridge cannot deliver Firebase's codes.
You can still sign users in to Firebase with a phone number verified by Bridge: check the number with Bridge Verify on your server, then hand the client a Firebase custom token.
// Your server (Node.js), with firebase-admin and @kroszborg/bridge
import { Bridge } from '@kroszborg/bridge';
import { getAuth } from 'firebase-admin/auth';
const bridge = new Bridge();
// POST /auth/phone/start { phone }
export async function start(phone: string) {
await bridge.otp.send({ to: phone });
}
// POST /auth/phone/finish { phone, code } -> { token } or 401
export async function finish(phone: string, code: string) {
const { valid } = await bridge.otp.verify({ to: phone, code });
if (!valid) return null;
const auth = getAuth();
const user = await auth.getUserByPhoneNumber(phone).catch(() => auth.createUser({ phoneNumber: phone }));
return auth.createCustomToken(user.uid);
}// The client
import { getAuth, signInWithCustomToken } from 'firebase/auth';
const { token } = await (await fetch('/auth/phone/finish', { method: 'POST', body: JSON.stringify({ phone, code }) })).json();
await signInWithCustomToken(getAuth(), token);The user ends up signed in to Firebase with the phone number on their account, and Firebase never
sends an SMS. bridge.otp.verify throws for 404 when no code is pending for the number; handle
it like a wrong code.
Clerk
Clerk sends SMS through its own gateway by default, but its
SMS templates have a
Delivered by Clerk setting. Turn it off for a template and Clerk stops sending that SMS; your
app delivers it instead, from the sms.created webhook. Clerk's templates page does not say which
plans include this; check your Clerk dashboard.
To deliver with Bridge:
- In Clerk, turn off Delivered by Clerk for the SMS templates Bridge should send (for example the verification code).
- Add a Clerk webhook endpoint in your app subscribed to
sms.created, and verify each request as Clerk's webhook guide describes (Clerk signs webhooks through Svix). - Send the message Clerk rendered:
// After verifying the webhook request with Clerk's tooling
if (evt.type === 'sms.created' && !evt.data.delivered_by_clerk) {
await bridge.messages.send(
{ to: evt.data.to_phone_number, message: evt.data.message },
{ idempotencyKey: evt.data.id }, // a retried webhook does not send the SMS twice
);
}to_phone_number, message and delivered_by_clerk are fields of Clerk's SMS message object.
Clerk still generates and checks the code. Because Bridge sees an ordinary message, the code is
stored and shown in full in Bridge until message retention removes it.
If you would rather not depend on Clerk's SMS at all, use the Firebase pattern above: verify the number with Bridge Verify on your server, then create or sign in the Clerk user with Clerk's backend API.
Better Auth
Better Auth's phone number plugin calls a sendOTP function you write whenever a code must go out. Point it at Bridge with the SDK.
n8n, Zapier and Make
Workflow tools talk to Bridge with plain HTTP: an HTTP request step sends an SMS or a code, and a webhook trigger starts a workflow when Bridge reports something.