Guides

Building Auth provider comparison and selection with Cler...

This guide implements a secure authentication and authorization system with multi-tenant support, OAuth integration, and API protection. Focuses on practical implementation patterns for full-stack developers.

2-3 hours5 steps
1

Initialize auth provider integration

Set up your chosen auth provider SDK with environment variables. Configure domain, API keys, and callback URLs. Verify provider-specific setup requirements (e.g., Clerk dashboard, Auth.js middleware).

export AUTH_PROVIDER=authjs
export NEXTAUTH_URL=http://localhost:3000
export AUTH_SECRET=your-32-byte-secret

⚠ Common Pitfalls

  • Exposing API keys in client-side code
  • Using development URLs in production environments
2

Implement multi-tenant schema

Add tenant identifier to database models. Create middleware to extract tenant context from subdomain or request headers. Configure database connection pooling per-tenant if needed.

middleware/tenant.js
app.use((req, res, next) => {
  req.tenantId = req.headers['x-tenant-id'] || 'default';
  next();
});

⚠ Common Pitfalls

  • Forgetting to index tenant identifiers in database queries
  • Sharing session storage across tenants without isolation
3

Configure OAuth provider integration

Register application with identity providers (Google, GitHub, etc.). Implement OAuth callback handlers with state validation. Store access tokens securely in database with scope restrictions.

passport.use(new GoogleStrategy({
  clientID: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
  callbackURL: '/api/auth/google/callback'
}, (token, refreshToken, profile, done) => {
  // Validate and store tenant-specific credentials
}));

⚠ Common Pitfalls

  • Allowing implicit grant flows without PKCE
  • Not validating state parameters in OAuth callbacks
4

Implement token-based session management

Use opaque session tokens with refresh tokens stored in secure HTTP-only cookies. Implement token revocation patterns for logout and password changes.

const session = await getSession({ req });
if (!session) {
  return res.status(401).json({ error: 'Unauthorized' });
}

⚠ Common Pitfalls

  • Using JWTs for session storage without proper signing configurations
  • Failing to invalidate tokens on password reset
5

Secure API endpoints

Add middleware to verify JWT tokens and enforce role-based access control. Implement rate limiting per-user and per-tenant. Validate all request inputs against schema.

function requireAuth(req, res, next) {
  const token = req.headers['authorization']?.split(' ')[1];
  if (!token || !verifyToken(token)) {
    return res.status(401).json({ error: 'Invalid token' });
  }
  next();
}

⚠ Common Pitfalls

  • Missing CORS configuration for API endpoints
  • Not validating content-type headers for JSON payloads

What you built

This implementation provides a secure foundation for authentication and authorization with multi-tenant support. Verify all security configurations through penetration testing and maintain regular audits of access control policies.