Building auth yourself?
// 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?Password hashing & salting
Session token management
CSRF protection
Rate limiting
OAuth flow handling
Email verification
Password reset flow
MFA implementation
Account lockout logic
Session invalidation
Or just use Blindgate.
middleware.ts
import { withAuth } from '@blindgate/next'export default withAuth({ publicRoutes: ['/login', '/signup']})All of the above, handled.
From zero to production
Total time: less than 10 minutes
Install
Add the SDK to your project
$ bun add @blindgate/next0 min
0 min
Install
Add the SDK to your project
$ bun add @blindgate/nextConfigure
Add authentication middleware
middleware.ts
import { withAuth } from '@blindgate/next'export default withAuth({ publicRoutes: ['/login', '/signup']})2 min
2 min
Configure
Add authentication middleware
middleware.ts
import { withAuth } from '@blindgate/next'export default withAuth({ publicRoutes: ['/login', '/signup']})Protect
Access user data in your pages
app/dashboard/page.tsx
import { currentUser } from '@blindgate/next/server'export default async function Dashboard() { const user = await currentUser() return <h1>Welcome, {user.name}</h1>}5 min
5 min
Protect
Access user data in your pages
app/dashboard/page.tsx
import { currentUser } from '@blindgate/next/server'export default async function Dashboard() { const user = await currentUser() return <h1>Welcome, {user.name}</h1>}Manage
Your dashboard is ready
blindgate.dev/dashboard
Blindgate
VP
Users
Manage users in this environment
| Name |
|---|
AJ Alice Johnson alice@example.com |
BS Bob Smith bob@example.com |
CW Carol White carol@example.com |
DB David Brown david@example.com |
Showing 1 to 4 of 4
Rows per page 10Page 1 of 1
5 min
5 min
Manage
Your dashboard is ready
blindgate.dev/dashboard
Blindgate
VP
Users
Manage users in this environment
| Name |
|---|
AJ Alice Johnson alice@example.com |
BS Bob Smith bob@example.com |
CW Carol White carol@example.com |
DB David Brown david@example.com |
Showing 1 to 4 of 4
Rows per page 10Page 1 of 1
Ship It
Deploy to production
$ git push origin mainProduction: Live
10 min
10 min
Ship It
Deploy to production
$ git push origin mainProduction: Live
DIY vs Blindgate
Why spend months when you can ship in minutes?
| Feature | DIY | Blindgate |
|---|---|---|
| Authentication | ~2 days | Included |
| Session Management | ~3 days | Included |
| OAuth Integration | ~1 week | Included |
| Multi-Factor Auth | ~1 week | Included |
| Password Reset | ~2 days | Included |
| Email Verification | ~2 days | Included |
| Rate Limiting | ~3 days | Included |
| Roles & Permissions | ~2 weeks | Included |
| Audit Logging | ~1 week | Included |
| Webhooks | ~3 days | Included |
~3 months
DIY estimate
~10 minutes
With Blindgate
A dashboard you didn't have to build
blindgate.dev/dashboard
Blindgate
VP
Users
Manage users in this environment
| Name |
|---|
AJ Alice Johnson alice@example.com |
BS Bob Smith bob@example.com |
CW Carol White carol@example.com |
DB David Brown david@example.com |
Showing 1 to 4 of 4
Rows per page 10Page 1 of 1
And it's secure, too
Every request passes through multiple layers of security
Request
Incoming authentication request
Rate Limiting
Intelligent rate limiting and IP filtering
Authentication
Secure credential validation
Authorization
Role and permission verification
Response
Secure session token issued
Works with whatever you're already using
Three packages. Every framework. Production-ready.
app.tsx
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> )}Hooks-based API with BlindgateProvider context for React applications
And it won't break the bank
Slide to see pricing for your scale
Monthly Active Users1K
1K2K5K10K25K50K100K
Free
Recommended$0/mo
- Up to 1,000 MAU
- Email & password auth
- Community support
- 1 project
Pro
$49/mo
- Up to 10,000 MAU
- All auth methods
- Priority support
- Unlimited projects
- Custom domains
Enterprise
Custom
- Unlimited MAU
- SSO & SAML
- Dedicated support
- SLA guarantee
- Custom integrations
- On-premise option
Stop Building Auth. Start Building Product.
Every hour on auth is an hour not spent on your product.