Пишете аутентификацию сами?
// auth.ts - DIY Authentication (good luck)
import bcrypt from 'bcrypt'
import jwt from 'jsonwebtoken'
import { randomBytes } from 'crypto'
const SALT_ROUNDS = 12
const JWT_SECRET = process.env.JWT_SECRET!
const CSRF_SECRET = process.env.CSRF_SECRET!
async function hashPassword(password: string) {
return bcrypt.hash(password, SALT_ROUNDS)
}
async function verifyPassword(password: string, hash: string) {
return bcrypt.compare(password, hash)
}
function generateSessionToken() {
return randomBytes(32).toString('hex')
}
function generateCSRFToken(sessionId: string) {
return jwt.sign({ sessionId }, CSRF_SECRET, { expiresIn: '1h' })
}
// Rate limiting - you'll need Redis for this
const rateLimiter = new Map<string, number[]>()
function checkRateLimit(ip: string): boolean {
const now = Date.now()
const windowMs = 15 * 60 * 1000
const maxRequests = 100
// ... this gets complicated fast
const requests = rateLimiter.get(ip) || []
const filtered = requests.filter(t => t > now - windowMs)
if (filtered.length >= maxRequests) return false
filtered.push(now)
rateLimiter.set(ip, filtered)
return true
}
// Don't forget: email verification, password reset,
// MFA, OAuth, session invalidation, account lockout,
// audit logging, webhook events, RBAC...
// Are you sure you want to build all this?// auth.ts - DIY Authentication (good luck)
import bcrypt from 'bcrypt'
import jwt from 'jsonwebtoken'
import { randomBytes } from 'crypto'
const SALT_ROUNDS = 12
const JWT_SECRET = process.env.JWT_SECRET!
const CSRF_SECRET = process.env.CSRF_SECRET!
async function hashPassword(password: string) {
return bcrypt.hash(password, SALT_ROUNDS)
}
async function verifyPassword(password: string, hash: string) {
return bcrypt.compare(password, hash)
}
function generateSessionToken() {
return randomBytes(32).toString('hex')
}
function generateCSRFToken(sessionId: string) {
return jwt.sign({ sessionId }, CSRF_SECRET, { expiresIn: '1h' })
}
// Rate limiting - you'll need Redis for this
const rateLimiter = new Map<string, number[]>()
function checkRateLimit(ip: string): boolean {
const now = Date.now()
const windowMs = 15 * 60 * 1000
const maxRequests = 100
// ... this gets complicated fast
const requests = rateLimiter.get(ip) || []
const filtered = requests.filter(t => t > now - windowMs)
if (filtered.length >= maxRequests) return false
filtered.push(now)
rateLimiter.set(ip, filtered)
return true
}
// Don't forget: email verification, password reset,
// MFA, OAuth, session invalidation, account lockout,
// audit logging, webhook events, RBAC...
// Are you sure you want to build all this?Или просто используйте Blindgate.
import { withAuth } from '@blindgate/next'export default withAuth({ publicRoutes: ['/login', '/signup']})От нуля до продакшена
Общее время: менее 10 минут
Установка
Добавьте SDK в ваш проект
$ bun add @blindgate/nextУстановка
Добавьте SDK в ваш проект
$ bun add @blindgate/nextНастройка
Добавьте middleware аутентификации
import { withAuth } from '@blindgate/next'export default withAuth({ publicRoutes: ['/login', '/signup']})Настройка
Добавьте middleware аутентификации
import { withAuth } from '@blindgate/next'export default withAuth({ publicRoutes: ['/login', '/signup']})Защита
Получите доступ к данным пользователя на страницах
import { currentUser } from '@blindgate/next/server'export default async function Dashboard() { const user = await currentUser() return <h1>Welcome, {user.name}</h1>}Защита
Получите доступ к данным пользователя на страницах
import { currentUser } from '@blindgate/next/server'export default async function Dashboard() { const user = await currentUser() return <h1>Welcome, {user.name}</h1>}Управление
Ваша панель управления готова
Пользователи
Управление пользователями в этом окружении
| Имя |
|---|
AJ Alice Johnson alice@example.com |
BS Bob Smith bob@example.com |
CW Carol White carol@example.com |
DB David Brown david@example.com |
Управление
Ваша панель управления готова
Пользователи
Управление пользователями в этом окружении
| Имя |
|---|
AJ Alice Johnson alice@example.com |
BS Bob Smith bob@example.com |
CW Carol White carol@example.com |
DB David Brown david@example.com |
Деплой
Разверните в продакшен
$ git push origin mainДеплой
Разверните в продакшен
$ git push origin mainСвоими руками vs Blindgate
Зачем тратить месяцы, если можно запустить за минуты?
| Функция | Своими руками | Blindgate |
|---|---|---|
| Аутентификация | ~2 дня | Включено |
| Управление сессиями | ~3 дня | Включено |
| Интеграция OAuth | ~1 неделя | Включено |
| Многофакторная аутентификация | ~1 неделя | Включено |
| Сброс пароля | ~2 дня | Включено |
| Верификация email | ~2 дня | Включено |
| Ограничение частоты запросов | ~3 дня | Включено |
| Роли и разрешения | ~2 недели | Включено |
| Журнал аудита | ~1 неделя | Включено |
| Вебхуки | ~3 дня | Включено |
Панель управления, которую не пришлось создавать
Пользователи
Управление пользователями в этом окружении
| Имя |
|---|
AJ Alice Johnson alice@example.com |
BS Bob Smith bob@example.com |
CW Carol White carol@example.com |
DB David Brown david@example.com |
И это безопасно
Каждый запрос проходит через несколько уровней защиты
Работает с тем, что вы уже используете
Три пакета. Любой фреймворк. Готово к продакшену.
import { BlindgateProvider, useAuth, SignIn } from '@blindgate/react'function App() { return ( <BlindgateProvider publishableKey="pk_live_..."> <Dashboard /> </BlindgateProvider> )}function Dashboard() { const { user, signOut } = useAuth() if (!user) return <SignIn /> return ( <div> <h1>Welcome, {user.name}</h1> <button type="button" onClick={signOut}>Sign Out</button> </div> )}API на хуках с BlindgateProvider контекстом для React-приложений
И это не ударит по бюджету
Двигайте ползунок, чтобы увидеть цены для вашего масштаба
Бесплатно
Рекомендуемый- До 1 000 MAU
- Аутентификация по email и паролю
- Поддержка сообщества
- 1 проект
Pro
- До 10 000 MAU
- Все методы аутентификации
- Приоритетная поддержка
- Неограниченно проектов
- Пользовательские домены
Enterprise
- Неограниченно MAU
- SSO и SAML
- Выделенная поддержка
- Гарантия SLA
- Пользовательские интеграции
- On-premise размещение
Хватит писать аутентификацию. Пора создавать продукт.
Каждый час на аутентификацию — это час, не потраченный на ваш продукт.