Skip to main content

Authentication Triggers

Beta

This feature is in beta. Core behavior is stable, but some APIs or configuration may change before general availability.

Run backend logic during sign-up, sign-in, token refresh, password reset, sign-out, account deletion, and email verification.

Authentication triggers are App Functions with trigger.type = 'auth'. This page keeps the auth-specific view inside the Authentication section. For the full App Functions model, see Function Trigger Types.

Terminology
  • Access Rules decide whether a client operation is allowed.
  • Authentication Triggers run backend logic on auth lifecycle events.
  • Authentication Delivery Hooks customize outbound email and SMS delivery under auth.handlers.email.onSend and auth.handlers.sms.onSend.

Quick Example

Place authentication trigger files in the functions/ directory:

// functions/restrict-company-domain.ts
import { defineFunction, FunctionError } from '@edgebase/shared';

export default defineFunction({
trigger: { type: 'auth', event: 'beforeSignUp' },
handler: async ({ data }) => {
const email = String(data?.after?.email ?? '');
if (!email.endsWith('@company.com')) {
throw new FunctionError('forbidden', 'Only company emails are allowed.');
}
},
});

Supported Events

Trigger EventBlockingctx.data?.after payload
beforeSignUpYesDraft signup payload such as id, email, displayName, avatarUrl
afterSignUpNoSanitized created user
beforeSignInYesSanitized user about to sign in
afterSignInNoSanitized signed-in user
onTokenRefreshYesSanitized user whose token is being refreshed
beforePasswordResetYesUsually { userId }
afterPasswordResetNoSanitized user after password change/reset
beforeSignOutYes{ userId }
afterSignOutNo{ userId }
onDeleteAccountNoSanitized user snapshot before deletion
onEmailVerifiedNoSanitized verified user

Common Uses

  • Reject signups from blocked email domains
  • Create profile rows or tenant membership after signup
  • Revoke sessions or audit password resets
  • Inject dynamic claims during token refresh
  • Clean up external systems when an account is deleted

Create a Profile After Signup

import { defineFunction } from '@edgebase/shared';

export default defineFunction({
trigger: { type: 'auth', event: 'afterSignUp' },
handler: async ({ data, admin }) => {
const user = data?.after;
if (!user?.id) return;

await admin.db('app').table('profiles').insert({
userId: String(user.id),
displayName: String(user.displayName ?? 'New User'),
});
},
});

Add Claims on Token Refresh

onTokenRefresh is the only authentication trigger whose return value is fed back into token generation.

import { defineFunction } from '@edgebase/shared';

export default defineFunction({
trigger: { type: 'auth', event: 'onTokenRefresh' },
handler: async ({ data, admin }) => {
const userId = String(data?.after?.id ?? '');
if (!userId) return;

const { items } = await admin.db('app').table('subscriptions').list({
limit: 1,
filter: [['userId', '==', userId]],
});

return {
plan: items[0]?.plan ?? 'free',
subscriptionStatus: items[0]?.status ?? 'inactive',
};
},
});

Behavior

  • Blocking trigger events can reject the auth operation by throwing.
  • Non-blocking trigger events run via ctx.waitUntil() and do not affect the client response once the main auth action succeeds.
  • The timeout for blocking authentication triggers is fixed at 5s.
  • ctx.auth is always null; use ctx.data?.after for user information.
  • ctx.admin.auth.createUser() and ctx.admin.auth.deleteUser() are intentionally unavailable inside authentication triggers.

Next Steps