Skip to content

Authentication

import { Tabs, TabItem } from ‘@astrojs/starlight/components’;

svelte-firekit exposes two authentication primitives:

  • firekitAuth — methods for signing in, registering, and managing users
  • firekitUser — reactive object that always reflects the current auth state
import { firekitAuth } from 'svelte-firekit';
await firekitAuth.signInWithEmail('[email protected]', 'password');
await firekitAuth.signInWithGoogle();
await firekitAuth.signInWithGithub();
await firekitAuth.signInWithFacebook();
await firekitAuth.signInWithApple();
await firekitAuth.signInWithTwitter();
await firekitAuth.signInWithMicrosoft();

Use the redirect flow on mobile or when popups are blocked. Call getRedirectResult() when the app loads to pick up the pending result.

// Trigger the redirect
await firekitAuth.signInWithGoogleRedirect();
// On app load — returns null if no pending redirect
const result = await firekitAuth.getRedirectResult();
await firekitAuth.signInWithSAML('saml.my-provider');
await firekitAuth.signInWithOIDC('oidc.my-provider', ['email', 'profile']);
// Step 1 — send SMS, pass the ID of a div where the reCAPTCHA will render
const { confirm } = await firekitAuth.signInWithPhoneNumber('+1234567890', 'recaptcha-container');
// Step 2 — confirm the code the user entered
await confirm('123456');
await firekitAuth.signInAnonymously();
await firekitAuth.signInWithCustomToken(serverIssuedToken);
// Register with email + password; optionally set a display name
await firekitAuth.registerWithEmail('[email protected]', 'password', 'Jane Doe');
// Update profile
await firekitAuth.updateUserProfile({ displayName: 'Jane', photoURL: 'https://...' });
// Change email (requires recent sign-in)
await firekitAuth.updateEmail('[email protected]');
// Change password
await firekitAuth.updatePassword('newPassword', 'currentPassword');
// Password reset email
await firekitAuth.sendPasswordReset('[email protected]');
// Email verification
await firekitAuth.sendEmailVerification();
// Sign out
await firekitAuth.signOut();
// Delete account (requires current password for email users)
await firekitAuth.deleteAccount('currentPassword');
// Step 1 — send verification SMS
const verificationId = await firekitAuth.startPhoneMFAEnrollment('+1234567890', 'recaptcha-container');
// Step 2 — confirm the code
await firekitAuth.completeMFAEnrollment(verificationId, '123456', 'My Phone');
const factors = firekitAuth.getMFAEnrolledFactors();
// Unenroll a specific factor
await firekitAuth.unenrollMFA(factors[0]);

When a sign-in requires MFA, Firebase throws a MultiFactorError. Catch it and use the resolver to complete the flow:

try {
await firekitAuth.signInWithEmail(email, password);
} catch (err) {
// err is a MultiFactorError
const resolver = firekitAuth.getMFAResolver(err);
// Start the SMS challenge for the first enrolled factor
const verificationId = await firekitAuth.startMFASignIn(resolver, 0, 'recaptcha-container');
// Complete after the user enters the code
const result = await firekitAuth.completeMFASignIn(resolver, verificationId, '123456');
}

firekitUser is a reactive singleton. Read its properties anywhere in your Svelte components — no subscription needed.

<script lang="ts">
import { firekitUser } from 'svelte-firekit';
</script>
{#if firekitUser.loading}
<p>Loading auth state…</p>
{:else if firekitUser.isAuthenticated}
<p>Welcome, {firekitUser.user?.displayName}</p>
<p>Email: {firekitUser.user?.email}</p>
{:else}
<p>Not signed in</p>
{/if}
PropertyTypeDescription
userUserProfile | nullCurrent user profile or null
loadingbooleantrue while the initial auth state is being resolved
isAuthenticatedbooleantrue when signed in and not anonymous
isAnonymousbooleantrue when the session is anonymous
initializedbooleantrue after the first auth state has been received

In SvelteKit load functions you may need to wait for the auth state before proceeding:

+page.ts
import { firekitUser } from 'svelte-firekit';
export async function load() {
const user = await firekitUser.waitForAuth();
if (!user) {
return { redirect: '/login', status: 302 };
}
return { user };
}

On the server waitForAuth() resolves immediately with null.

Use these components for declarative auth gating directly in templates.

<script lang="ts">
import { SignedIn, SignedOut } from 'svelte-firekit';
</script>
<SignedIn>
<p>Only shown when the user is signed in.</p>
</SignedIn>
<SignedOut>
<a href="/login">Sign in</a>
</SignedOut>

Redirects unauthenticated users. Pass requireAuth={true} to protect a route, or requireAuth={false} to redirect already-signed-in users away from login pages.

<script lang="ts">
import { AuthGuard } from 'svelte-firekit';
import { goto } from '$app/navigation';
</script>
<AuthGuard requireAuth={true} onUnauthorized={() => goto('/login')}>
<p>This content is only visible to signed-in users.</p>
</AuthGuard>

For role checks or any async authorization logic. Pass an array of async functions that each return a boolean; all must resolve to true for the content to render.

<script lang="ts">
import { CustomGuard } from 'svelte-firekit';
import { goto } from '$app/navigation';
import { getDoc, doc } from 'firebase/firestore';
import { getFirestoreContext } from 'svelte-firekit';
const db = getFirestoreContext();
const checks = [
async () => {
const snap = await getDoc(doc(db, 'users', userId));
return snap.data()?.role === 'admin';
},
];
</script>
<CustomGuard verificationChecks={checks} onUnauthorized={() => goto('/403')}>
<p>Admin-only content</p>
</CustomGuard>