למה לאגד התחברויות חברתיות?
שילוב התחברות דרך מספר ספקים אינו רק הוספת כפתורים לעמוד. האתגר הטכני האמיתי: משתמש נרשם דרך Google, ואז חודש לאחר מכן מנסה להתחבר דרך GitHub עם אותה כתובת אימייל—אתה צריך לקשר חשבונות מבלי לאבד את הסשן או ליצור כפילויות. טעות מובילה לסכסוכי נתונים או לאיפוסי סיסמה. סטטיסטיקות מראות ש-30% מהמשתמשים החדשים נוטשים את ההרשמה אם התחברות חברתית אינה זמינה, ו-90% מעדיפים התחברות חברתית outright. שילוב ה-OAuth שלנו מיושם באמצעות Auth.js + Prisma + PostgreSQL, עם ניסיון של למעלה מ-10 שנים ו-100+ פרויקטים מוצלחים. אנו מבטיחים קישור חלק ושלמות נתונים מלאה. בניגוד לפתרונות מוכנים כמו Clerk (שעולים מ-$0.25 ל-MAU), הגישה שלנו מעניקה לך שליטה מלאה בנתונים ובתצורה, וחוסכת עד $5,000 בשנה בפרויקטים גדולים. בהשוואה ל-Firebase, Auth.js יכול לחסוך עד $3,000 בשנה ב-100,000 משתמשים פעילים. עבור פרויקט טיפוסי עם 4 ספקים, העלות החד-פעמית שלנו של $2,500 נמוכה מ-6 חודשים של עמלות Clerk של $0.25/MAU עבור 10,000 MAU. הפתרון שלנו ניתן להתאמה אישית פי 2 יותר מ-Clerk ופי 3 מהיר יותר לפריסה מאשר Firebase Auth.
איך עובד קישור חשבונות?
קישור חשבונות הוא אתגר הליבה של אגרגציית OAuth. אנו מיישמים אותו דרך ה-callback signIn ב-Auth.js: אנו בודקים אם קיים משתמש לפי אימייל ומצרפים את הספק החדש לחשבון שלו. אם הספק כבר מקושר, אנו לא עושים דבר. אנו יוצרים טבלת Account מאוחדת עם אילוץ ייחודיות על הצמד [provider, providerAccountId]. הנה היישום:
// auth.ts (Auth.js v5)
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import GitHub from 'next-auth/providers/github';
import Apple from 'next-auth/providers/apple';
import MicrosoftEntraID from 'next-auth/providers/microsoft-entra-id';
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
GitHub({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
Apple({
clientId: process.env.APPLE_ID!,
clientSecret: process.env.APPLE_SECRET!,
// JWT из .p8 ключа
}),
MicrosoftEntraID({
clientId: process.env.AZURE_AD_CLIENT_ID!,
clientSecret: process.env.AZURE_AD_CLIENT_SECRET!,
tenantId: process.env.AZURE_AD_TENANT_ID!,
// или 'common' для всех
}),
],
callbacks: {
async signIn({ user, account, profile }) {
// Автоматическое связывание по email
if (user.email) {
const existingUser = await db.user.findUnique({
where: { email: user.email }
});
if (existingUser) {
const existingAccount = await db.account.findFirst({
where: {
userId: existingUser.id,
provider: account!.provider,
}
});
if (!existingAccount) {
await db.account.create({
data: {
userId: existingUser.id,
provider: account!.provider,
providerAccountId: account!.providerAccountId,
type: account!.type,
access_token: account!.access_token,
refresh_token: account!.refresh_token,
expires_at: account!.expires_at,
}
});
}
return true;
}
}
return true;
},
async session({ session, token }) {
if (token.sub) {
session.user.id = token.sub;
}
return session;
},
},
adapter: PrismaAdapter(db),
});
סכמת ה-Prisma לחשבונות מקושרים נראית כך:
model User {
id String @id @default(cuid())
email String @unique
name String?
image String?
createdAt DateTime @default(now())
accounts Account[]
sessions Session[]
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}עבור ממשק המשתמש, אנו מספקים כפתורי התחברות חברתית שמשתלבים בצורה חלקה עם כל טופס הרשמה או התחברות. דוגמה באמצעות Next-Auth:
// components/SocialLoginButtons.tsx
'use client';
import { signIn } from 'next-auth/react';
const PROVIDERS = [
{
id: 'google',
name: 'Google',
icon: <GoogleIcon />,
className: 'bg-white border border-gray-300 hover:bg-gray-50',
},
{
id: 'github',
name: 'GitHub',
icon: <GitHubIcon />,
className: 'bg-gray-900 text-white hover:bg-gray-800',
},
{
id: 'apple',
name: 'Apple',
icon: <AppleIcon />,
className: 'bg-black text-white hover:bg-gray-900',
},
{
id: 'microsoft-entra-id',
name: 'Microsoft',
icon: <MicrosoftIcon />,
className: 'bg-[#00a4ef] text-white hover:bg-[#0090d4]',
},
] as const;
export function SocialLoginButtons({
callbackUrl = '/',
mode = 'login',
}: {
callbackUrl?: string;
mode?: 'login' | 'register';
}) {
return (
<div className="flex flex-col gap-3">
{PROVIDERS.map((provider) => (
<button
key={provider.id}
type="button"
onClick={() => signIn(provider.id, { callbackUrl })}
className={`flex items-center gap-3 px-4 py-2.5 rounded-lg font-medium ${provider.className}`}
>
{provider.icon}
<span>{mode === 'login' ? 'Войти' : 'Зарегистрироваться'} через {provider.name}</span>
</button>
))}
</div>
);
} מהם היתרונות של אגרגציה?
UX: משתמשים לוחצים פחות, אין צורך לזכור סיסמאות. אבטחה: אסימוני OAuth פגים, אסימוני רענון מתחדשים אוטומטית. המרה: התחברות חברתית מפחיתה נשירה בהרשמה ב-30–50%. לדוגמה, לקוח אחד (בית ספר מקוון) ראה עלייה של 40% בהרשמות לאחר הוספת התחברות Apple ו-Google. עליית המרה ממוצעת של 35% לאחר יישום התחברות חברתית. בהשוואה ל-Clerk, Auth.js מציע גמישות פי 3 יותר בהתאמת ממשק המשתמש ושליטה מלאה בנתונים, אם כי הוא דורש הגדרה ידנית יותר. Firebase Auth תומך בפחות ספקים: 5+ OAuth לעומת 10+ עם Auth.js.
השוואת גישות אגרגציה
| תכונה | Auth.js (NextAuth) | Clerk | Firebase Auth |
|---|---|---|---|
| התקנה | תצורה ידנית | Dashboard + SDK | Firebase Console |
| קישור | signIn callback | אוטומטי עם דיאלוג | יישום מותאם אישית |
| תמיכה בספקים | 10+ OAuth | 10+ + Magic Link | 5+ OAuth |
| מחיר | חינם (self-hosted) | Freemium מ-$0.25/MAU | Freemium עד 50k MAU |
אנו בדרך כלל בוחרים ב-Auth.js בשל הגמישות והשליטה המלאה בנתונים. Clerk מתאים להתחלה מהירה אך יש לו מגבלות בהתאמת ממשק המשתמש.
השוואת תכונות ספקים
| ספק | Refresh Token | התאמת Scope | נדרש אימות אפליקציה |
|---|---|---|---|
| כן | כן | כן (מסך הסכמת OAuth) | |
| GitHub | כן (מוגבל) | לא | לא |
| Apple | כן (JWT) | כן | כן (נדרש Team ID) |
| Microsoft | כן | כן | כן (נדרשת הרשמה) |
איך מובטחת אבטחת אסימוני OAuth?
פרוטוקול OAuth 2.0 משתמש באסימוני גישה ורענון. אסימוני רענון מאפשרים לחדש גישה מבלי להזין מחדש אישורים. אנו מיישמים אחסון מאובטח של אסימונים במסד הנתונים עם הצפנה. RFC 6749 מגדיר את התקן. בערימה שלנו, Auth.js מרענן אסימונים אוטומטית דרך callbacks. אורך חיים ממוצע של אסימון גישה הוא שעה אחת, אסימון רענון 30 יום. אנו מבטיחים סשנים ללא הפרעות. קוד האדפטר הוא כ-50 שורות, וזמן תגובת ה-API הוא מתחת ל-200 אלפיות השנייה.
איך אנו מטפלים בקונפליקטים במהלך קישור?
אם קיים משתמש עם אותה כתובת אימייל אך אין לו סיסמה (נרשם דרך ספק אחר), אנו מציעים לו להתחבר דרך הספק הקיים או להגדיר סיסמה. אם האימייל תפוס אך המשתמש מנסה להתחבר עם ספק חדש, אנו מציגים דיאלוג אישור: "האם זה החשבון שלך? התחבר דרך הספק הישן כדי לקשר." כאשר הגישה לספק נשללת (לדוגמה, המשתמש ביטל הרשאה ב-Google), אנו מטפלים בשגיאה ומציעים אימות מחדש. אנו מבטיחים שאף חשבון לא יאבד. אנו מאחסנים עד 10 ספקים לכל חשבון.
מהו תהליך העבודה שלנו?
- ניתוח — קביעת רשימת ספקים, דרישות קישור, השגת אישורי OAuth מלוחות הבקרה של הספקים.
- עיצוב — סכמת מסד נתונים, טיפול בקונפליקטים, UX לאישור.
- יישום — בניית הגדרת Auth.js, אדפטר Prisma, כפתורי UI, דף ניהול חשבונות.
- בדיקות — אימות קישור, ביטול אסימונים, מקרי קצה (הסרת ספק, שלילת גישה).
- פריסה — הגדרת env, הרצת מיגרציות DB, ניטור.
תוצרים
- הגדרת OAuth לכל ספק (השגת אישורים, הגדרת callback URLs).
- לוגיקת קישור חשבונות דרך signIn callback.
- ממשק משתמש מותאם אישית לכפתורי התחברות חברתית.
- סכמת מסד נתונים (טבלאות User ו-Account עם אילוץ ייחודיות).
- תיעוד פריסה וניהול ספקים.
- אחריות לפעולה תקינה (קישור חלק, רענון אסימונים).
רשימת טעויות נפוצות
- לא להגדיר אסימוני רענון—המשתמש נזרק אחרי שעה.
- לא לטפל במקרה שבו האימייל כבר תפוס אך אין סיסמה—יש להציע התחברות דרך הספק הקיים.
- לשכוח UX בעת ביטול קישור הספק האחרון—אסור להשאיר את המשתמש ללא שיטת התחברות.
- לא לוודא שהאפליקציה מאומתת על ידי הספק (לדוגמה, Google דורש אישור).
הערכות זמנים
שילוב בסיסי (ספק אחד + הגדרה): מיום עסקים אחד. אגרגציה של 4 ספקים עם קישור ו-UI: בין 2 ל-5 ימים. אנו מספקים הערכות מדויקות לאחר ניתוח הפרויקט שלך. התמחור נקבע באופן אישי לפי מורכבות.
צור קשר לייעוץ—המהנדסים שלנו יטפלו בהגדרת OAuth, מסד הנתונים ו-UI. הזמינו שילוב התחברות חברתית turnkey וקבלו גישת הדגמה לאב-טיפוס עובד תוך יומיים.







