Authentication & Authorization - 2/2

From Identity to Access Control

You’ve mastered authentication fundamentals that verify user identity, implemented secure session management and JWT tokens, integrated OAuth 2.0 for third-party authentication, and built multi-factor authentication systems that balance security with user experience. Your applications can authenticate users through multiple methods and maintain secure sessions across devices. But here’s the authorization reality that separates simple login systems from enterprise-grade access control: knowing WHO a user is means nothing if you can’t precisely control WHAT they can access, when they can access it, and under what conditions.

The permission nightmare that creates security chaos:

// Your perfectly authenticated users hitting a wall of confusion
app.get(
  "/api/admin/users",
  requireAuthentication, // User authenticated ✅
  async (req, res) => {
    // But now what? How do we determine if they should see this?

    if (req.user.email === "admin@company.com") {
      // Hard-coded admin check - breaks when admin changes
      const users = await getAllUsers();
      res.json({ users });
    } else {
      res.status(403).json({ error: "Access denied" });
    }
  }
);

app.delete("/api/projects/:id", requireAuthentication, async (req, res) => {
  // More confusion - can this user delete THIS specific project?
  const project = await getProject(req.params.id);

  if (req.user.id === project.ownerId || req.user.role === "admin") {
    // What about project managers? Team leads? Department heads?
    // What if user has admin role but only for their department?
    // What about time-based permissions or IP restrictions?
    await deleteProject(req.params.id);
    res.json({ success: true });
  } else {
    res.status(403).json({ error: "Insufficient permissions" });
  }
});

// The authorization problems that create chaos:
// - Hard-coded permission checks scattered everywhere
// - No centralized way to manage who can do what
// - Impossible to grant temporary or conditional access
// - Can't handle hierarchical roles or inherited permissions
// - No audit trail of who accessed what and when
// - Permission changes require code deployment
// - Can't delegate access or create approval workflows

The uncomfortable authorization truth: Authentication without sophisticated authorization is like having a building with perfect locks but no way to control which rooms each key holder can enter. Modern applications require dynamic permission systems that handle complex organizational hierarchies, conditional access rules, and automated compliance requirements without requiring developers to hard-code business logic.

Real-world authorization failure consequences:

// What happens when authorization systems fail:
const authorizationFailureImpact = {
  dataBreachScenario: {
    problem: "Junior developer granted admin access to fix 'urgent' bug",
    action: "Downloaded entire customer database to debug locally",
    impact: "2.3M customer records exposed on personal laptop",
    cause: "No granular permissions, only 'admin' or 'user' roles",
    compliance: "GDPR violation: $4.1M fine for excessive access privileges",
  },

  businessDisruption: {
    problem:
      "Marketing team couldn't access campaign data during product launch",
    cause: "Permission system hardcoded to only allow 'engineering' role",
    impact: "$800K launch budget wasted, competitor gained market advantage",
    solution: "Required 3 days of emergency code changes and redeployment",
  },

  operationalChaos: {
    problem: "No way to grant temporary contractor access to specific projects",
    workaround: "Created permanent admin accounts for all contractors",
    result: "37 unused admin accounts with full system access",
    discovery: "Security audit found 23 accounts belonging to ex-contractors",
  },

  // Perfect authentication is worthless when authorization
  // can't handle real-world business complexity and change
};

Advanced authorization mastery requires understanding:

  • Role-Based Access Control (RBAC) with hierarchical roles and permission inheritance
  • Permission systems and middleware that scale with organizational complexity
  • Social login integration at scale with account linking and enterprise SSO
  • Single Sign-On (SSO) implementation for seamless multi-application access
  • Authentication best practices that handle security, compliance, and user experience at enterprise scale

This article completes your identity architecture education by building sophisticated authorization systems on your authentication foundation. You’ll create permission frameworks that adapt to organizational changes, SSO systems that scale across applications, and access control patterns that satisfy the most demanding enterprise requirements.


Role-Based Access Control: Hierarchical Permission Systems

Professional RBAC Implementation

The RBAC complexity that simple role checks can’t handle:

// ❌ Naive role system that breaks with real business requirements
const checkAccess = (user, resource) => {
  // Over-simplified role checks
  if (user.role === "admin") return true;
  if (user.role === "manager" && resource.type === "report") return true;
  if (user.role === "user" && resource.ownerId === user.id) return true;

  return false;

  // Real business requirements this can't handle:
  // - Department managers who can only manage their department
  // - Project leads with admin rights to specific projects
  // - Temporary elevated access for incident response
  // - Read-only access during maintenance windows
  // - Geographic restrictions (EU users can only access EU data)
  // - Time-based permissions (access only during business hours)
  // - Inherited permissions from team membership
  // - Conditional access based on security posture
};

Comprehensive RBAC system with hierarchies and conditions:

// ✅ Enterprise-grade RBAC with sophisticated permission modeling
class RoleBasedAccessControl {
  constructor() {
    this.permissionCache = new Map();
    this.roleHierarchy = new Map();
    this.setupSystemRoles();
    this.setupPermissionEngine();
  }

  setupSystemRoles() {
    // Define role hierarchy (roles inherit from parent roles)
    this.roleHierarchy = {
      super_admin: {
        inherits: [],
        permissions: ["*"], // All permissions
        description: "System administrator with unrestricted access",
      },

      organization_admin: {
        inherits: ["department_admin"],
        permissions: ["org:*", "user:manage", "billing:*"],
        description: "Organization-wide administrative access",
      },

      department_admin: {
        inherits: ["team_lead"],
        permissions: ["dept:manage", "user:invite", "report:create"],
        description: "Department-level administrative access",
      },

      team_lead: {
        inherits: ["member"],
        permissions: ["team:manage", "project:create", "user:view"],
        description: "Team leadership with project management rights",
      },

      member: {
        inherits: ["viewer"],
        permissions: ["project:contribute", "comment:create", "file:upload"],
        description: "Active contributor with creation rights",
      },

      viewer: {
        inherits: [],
        permissions: ["project:read", "comment:read", "file:download"],
        description: "Read-only access to assigned resources",
      },

      contractor: {
        inherits: ["member"],
        permissions: ["-user:view", "-report:read"], // Explicit denials
        restrictions: ["temporary", "ip_restricted"],
        description: "Temporary contributor with restricted access",
      },
    };
  }

  async assignRole(userId, roleId, context = {}) {
    try {
      const role = this.roleHierarchy[roleId];
      if (!role) {
        throw new Error(`Role ${roleId} does not exist`);
      }

      // Create role assignment with context
      const assignment = {
        userId,
        roleId,
        assignedBy: context.assignedBy,
        assignedAt: new Date(),
        expiresAt: context.expiresAt,
        conditions: context.conditions || {},
        scope: context.scope || "global", // Can be department-specific, project-specific, etc.
        isActive: true,
        metadata: context.metadata || {},
      };

      // Store role assignment
      await db.roleAssignments.insertOne(assignment);

      // Invalidate permission cache for this user
      this.invalidateUserPermissions(userId);

      // Log role assignment
      this.logRoleEvent({
        type: "role_assigned",
        userId,
        roleId,
        assignedBy: context.assignedBy,
        scope: assignment.scope,
        timestamp: new Date(),
      });

      return assignment;
    } catch (error) {
      console.error("Role assignment failed:", error);
      throw error;
    }
  }

  async getUserPermissions(userId, context = {}) {
    try {
      // Check cache first
      const cacheKey = `permissions:${userId}:${JSON.stringify(context)}`;
      if (this.permissionCache.has(cacheKey)) {
        return this.permissionCache.get(cacheKey);
      }

      // Get active role assignments
      const assignments = await db.roleAssignments
        .find({
          userId,
          isActive: true,
          $or: [{ expiresAt: null }, { expiresAt: { $gt: new Date() } }],
        })
        .toArray();

      // Calculate effective permissions
      const effectivePermissions = await this.calculateEffectivePermissions(
        assignments,
        context
      );

      // Cache result
      this.permissionCache.set(cacheKey, effectivePermissions);

      // Set cache expiration
      setTimeout(() => {
        this.permissionCache.delete(cacheKey);
      }, 5 * 60 * 1000); // 5 minutes

      return effectivePermissions;
    } catch (error) {
      console.error("Permission calculation failed:", error);
      throw error;
    }
  }

  async calculateEffectivePermissions(assignments, context) {
    const permissions = new Set();
    const deniedPermissions = new Set();
    const conditions = [];

    for (const assignment of assignments) {
      // Check if assignment applies to current context
      if (!this.assignmentApplies(assignment, context)) {
        continue;
      }

      // Get role definition
      const role = this.roleHierarchy[assignment.roleId];
      if (!role) continue;

      // Collect permissions from role hierarchy
      const rolePermissions = await this.expandRolePermissions(
        assignment.roleId
      );

      rolePermissions.forEach((permission) => {
        if (permission.startsWith("-")) {
          // Explicit denial
          deniedPermissions.add(permission.slice(1));
        } else {
          permissions.add(permission);
        }
      });

      // Collect conditions
      if (assignment.conditions) {
        conditions.push({
          type: "assignment_conditions",
          conditions: assignment.conditions,
          source: assignment.roleId,
        });
      }
    }

    // Remove denied permissions
    deniedPermissions.forEach((denied) => {
      permissions.delete(denied);
    });

    return {
      permissions: Array.from(permissions),
      deniedPermissions: Array.from(deniedPermissions),
      conditions,
      calculatedAt: new Date(),
      userId: assignments[0]?.userId,
      context,
    };
  }

  async expandRolePermissions(roleId) {
    const permissions = new Set();
    const visited = new Set();

    const expandRole = (currentRoleId) => {
      if (visited.has(currentRoleId)) return; // Prevent circular inheritance
      visited.add(currentRoleId);

      const role = this.roleHierarchy[currentRoleId];
      if (!role) return;

      // Add direct permissions
      role.permissions.forEach((permission) => {
        permissions.add(permission);
      });

      // Recursively add inherited permissions
      role.inherits.forEach((parentRoleId) => {
        expandRole(parentRoleId);
      });
    };

    expandRole(roleId);
    return Array.from(permissions);
  }

  async checkPermission(userId, permission, resource = null, context = {}) {
    try {
      // Get user's effective permissions
      const userPermissions = await this.getUserPermissions(userId, context);

      // Check for wildcard permissions
      if (userPermissions.permissions.includes("*")) {
        return { granted: true, reason: "super_admin_wildcard" };
      }

      // Check for explicit denial
      if (userPermissions.deniedPermissions.includes(permission)) {
        return { granted: false, reason: "explicitly_denied" };
      }

      // Check direct permission match
      if (userPermissions.permissions.includes(permission)) {
        return await this.evaluateConditions(
          userPermissions,
          permission,
          resource,
          context
        );
      }

      // Check wildcard patterns
      const hasWildcardPermission = userPermissions.permissions.some((perm) => {
        if (!perm.includes(":*")) return false;

        const [namespace] = perm.split(":");
        const [reqNamespace] = permission.split(":");

        return namespace === reqNamespace;
      });

      if (hasWildcardPermission) {
        return await this.evaluateConditions(
          userPermissions,
          permission,
          resource,
          context
        );
      }

      return { granted: false, reason: "permission_not_found" };
    } catch (error) {
      console.error("Permission check failed:", error);
      return { granted: false, reason: "permission_check_error" };
    }
  }

  async evaluateConditions(userPermissions, permission, resource, context) {
    try {
      // If no conditions, grant access
      if (
        !userPermissions.conditions ||
        userPermissions.conditions.length === 0
      ) {
        return { granted: true, reason: "no_conditions" };
      }

      // Evaluate all conditions
      for (const conditionGroup of userPermissions.conditions) {
        const conditionResult = await this.evaluateConditionGroup(
          conditionGroup,
          permission,
          resource,
          context
        );

        if (!conditionResult.satisfied) {
          return {
            granted: false,
            reason: "condition_not_met",
            failedCondition: conditionResult.failedCondition,
          };
        }
      }

      return { granted: true, reason: "all_conditions_met" };
    } catch (error) {
      console.error("Condition evaluation failed:", error);
      return { granted: false, reason: "condition_evaluation_error" };
    }
  }

  async evaluateConditionGroup(conditionGroup, permission, resource, context) {
    const { conditions } = conditionGroup;

    // Time-based conditions
    if (conditions.timeRestriction) {
      const now = new Date();
      const currentHour = now.getHours();
      const currentDay = now.getDay(); // 0 = Sunday

      if (conditions.timeRestriction.businessHoursOnly) {
        if (
          currentHour < 9 ||
          currentHour > 17 ||
          currentDay === 0 ||
          currentDay === 6
        ) {
          return {
            satisfied: false,
            failedCondition: "outside_business_hours",
          };
        }
      }

      if (conditions.timeRestriction.allowedHours) {
        if (!conditions.timeRestriction.allowedHours.includes(currentHour)) {
          return {
            satisfied: false,
            failedCondition: "outside_allowed_hours",
          };
        }
      }
    }

    // IP-based conditions
    if (conditions.ipRestriction && context.ipAddress) {
      const allowedNetworks = conditions.ipRestriction.allowedNetworks || [];
      const isAllowedIP = allowedNetworks.some((network) =>
        this.isIPInNetwork(context.ipAddress, network)
      );

      if (!isAllowedIP) {
        return {
          satisfied: false,
          failedCondition: "ip_not_allowed",
        };
      }
    }

    // Resource-based conditions
    if (conditions.resourceRestriction && resource) {
      // Department-specific access
      if (conditions.resourceRestriction.departmentOnly) {
        const userDepartment = await this.getUserDepartment(context.userId);
        if (resource.department !== userDepartment) {
          return {
            satisfied: false,
            failedCondition: "wrong_department",
          };
        }
      }

      // Owner-only access
      if (conditions.resourceRestriction.ownerOnly) {
        if (resource.ownerId !== context.userId) {
          return {
            satisfied: false,
            failedCondition: "not_resource_owner",
          };
        }
      }
    }

    // MFA conditions
    if (conditions.requireMFA) {
      if (!context.mfaVerified) {
        return {
          satisfied: false,
          failedCondition: "mfa_required",
        };
      }
    }

    return { satisfied: true };
  }

  // Permission middleware for Express routes
  requirePermission(permission, options = {}) {
    return async (req, res, next) => {
      try {
        if (!req.user) {
          return res.status(401).json({
            error: "Authentication required",
          });
        }

        // Build context for permission check
        const context = {
          userId: req.user.id,
          ipAddress: req.ip,
          userAgent: req.get("User-Agent"),
          mfaVerified: req.mfaChallenge?.verified || false,
          requestPath: req.path,
          requestMethod: req.method,
          ...options.additionalContext,
        };

        // Get resource if applicable
        let resource = null;
        if (options.resourceLoader) {
          resource = await options.resourceLoader(req);
        }

        // Check permission
        const permissionResult = await this.checkPermission(
          req.user.id,
          permission,
          resource,
          context
        );

        if (!permissionResult.granted) {
          // Log access denial
          this.logAccessDenial({
            userId: req.user.id,
            permission,
            resource: resource?.id,
            reason: permissionResult.reason,
            context,
            timestamp: new Date(),
          });

          return res.status(403).json({
            error: "Access denied",
            message: this.getAccessDenialMessage(permissionResult.reason),
            requiredPermission: permission,
            failedCondition: permissionResult.failedCondition,
          });
        }

        // Log successful access
        this.logAccessGrant({
          userId: req.user.id,
          permission,
          resource: resource?.id,
          context,
          timestamp: new Date(),
        });

        // Attach permission info to request
        req.permission = {
          granted: permission,
          resource,
          context,
        };

        next();
      } catch (error) {
        console.error("Permission middleware failed:", error);
        res.status(500).json({
          error: "Permission check failed",
          message: "Unable to verify your permissions",
        });
      }
    };
  }
}

// Usage examples
const rbac = new RoleBasedAccessControl();

// Assign roles with context
await rbac.assignRole("user123", "team_lead", {
  assignedBy: "admin456",
  scope: "project:abc-123",
  expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days
  conditions: {
    timeRestriction: { businessHoursOnly: true },
    ipRestriction: { allowedNetworks: ["192.168.1.0/24"] },
  },
});

// Protected routes with RBAC
app.get(
  "/api/admin/users",
  authenticateUser,
  rbac.requirePermission("user:list"),
  async (req, res) => {
    const users = await getUsersList();
    res.json({ users });
  }
);

app.delete(
  "/api/projects/:projectId",
  authenticateUser,
  rbac.requirePermission("project:delete", {
    resourceLoader: async (req) => {
      return await getProject(req.params.projectId);
    },
  }),
  async (req, res) => {
    await deleteProject(req.params.projectId);
    res.json({ success: true });
  }
);

app.post(
  "/api/sensitive-operation",
  authenticateUser,
  rbac.requirePermission("admin:sensitive", {
    additionalContext: { requireMFA: true },
  }),
  async (req, res) => {
    await performSensitiveOperation();
    res.json({ success: true });
  }
);

Social Login at Scale: Enterprise Integration Patterns

Multi-Provider Social Authentication System

Scalable social login with account linking:

// ✅ Enterprise social login system with sophisticated account management
class EnterpriseSocialAuth extends OAuthManager {
  constructor() {
    super();
    this.setupEnterpriseProviders();
    this.accountLinker = new AccountLinker();
    this.provisioningEngine = new UserProvisioningEngine();
  }

  setupEnterpriseProviders() {
    // Add enterprise providers to existing OAuth providers
    this.providers = {
      ...this.providers,

      // Microsoft Azure AD / Office 365
      azure_ad: {
        clientId: process.env.AZURE_AD_CLIENT_ID,
        clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
        redirectUri: process.env.AZURE_AD_REDIRECT_URI,
        authority:
          process.env.AZURE_AD_AUTHORITY ||
          "https://login.microsoftonline.com/common",
        authUrl:
          "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
        tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
        userInfoUrl: "https://graph.microsoft.com/v1.0/me",
        scopes: ["openid", "profile", "email", "User.Read"],
      },

      // Okta
      okta: {
        clientId: process.env.OKTA_CLIENT_ID,
        clientSecret: process.env.OKTA_CLIENT_SECRET,
        redirectUri: process.env.OKTA_REDIRECT_URI,
        domain: process.env.OKTA_DOMAIN,
        authUrl: `${process.env.OKTA_DOMAIN}/oauth2/v1/authorize`,
        tokenUrl: `${process.env.OKTA_DOMAIN}/oauth2/v1/token`,
        userInfoUrl: `${process.env.OKTA_DOMAIN}/oauth2/v1/userinfo`,
        scopes: ["openid", "profile", "email"],
      },

      // SAML (via OneLogin)
      saml_onelogin: {
        issuer: process.env.SAML_ISSUER,
        entryPoint: process.env.SAML_ENTRY_POINT,
        cert: process.env.SAML_CERT,
        privateCert: process.env.SAML_PRIVATE_CERT,
      },

      // Custom LDAP/Active Directory
      ldap: {
        url: process.env.LDAP_URL,
        bindDN: process.env.LDAP_BIND_DN,
        bindCredentials: process.env.LDAP_BIND_PASSWORD,
        searchBase: process.env.LDAP_SEARCH_BASE,
        searchFilter:
          process.env.LDAP_SEARCH_FILTER || "(sAMAccountName={{username}})",
      },
    };
  }

  async handleEnterpriseLogin(provider, credentials, context = {}) {
    try {
      let authResult = null;

      switch (provider) {
        case "azure_ad":
          authResult = await this.handleAzureADLogin(credentials, context);
          break;

        case "okta":
          authResult = await this.handleOktaLogin(credentials, context);
          break;

        case "saml_onelogin":
          authResult = await this.handleSAMLLogin(credentials, context);
          break;

        case "ldap":
          authResult = await this.handleLDAPLogin(credentials, context);
          break;

        default:
          // Fallback to standard OAuth
          authResult = await this.handleCallback(
            provider,
            credentials.code,
            credentials.state
          );
      }

      if (!authResult.success) {
        throw new Error(authResult.error);
      }

      // Process enterprise user with provisioning rules
      const processedUser = await this.provisioningEngine.processEnterpriseUser(
        provider,
        authResult.user,
        context
      );

      return processedUser;
    } catch (error) {
      console.error("Enterprise login failed:", error);
      throw error;
    }
  }

  async handleAzureADLogin(credentials, context) {
    try {
      // Exchange code for tokens
      const tokenResponse = await this.exchangeCodeForTokens(
        "azure_ad",
        credentials.code
      );

      // Get user info from Microsoft Graph
      const userInfo = await this.getUserInfo(
        "azure_ad",
        tokenResponse.access_token
      );

      // Get additional Azure AD information
      const additionalInfo = await this.getAzureADUserDetails(
        tokenResponse.access_token
      );

      const normalizedUser = {
        providerId: userInfo.id,
        email: userInfo.mail || userInfo.userPrincipalName,
        firstName: userInfo.givenName,
        lastName: userInfo.surname,
        fullName: userInfo.displayName,
        jobTitle: userInfo.jobTitle,
        department: userInfo.department,
        officeLocation: userInfo.officeLocation,
        manager: additionalInfo.manager,
        directReports: additionalInfo.directReports,
        groups: additionalInfo.groups,
        roles: additionalInfo.roles,
      };

      return {
        success: true,
        user: normalizedUser,
        tokens: tokenResponse,
        provider: "azure_ad",
      };
    } catch (error) {
      console.error("Azure AD login failed:", error);
      return { success: false, error: error.message };
    }
  }

  async getAzureADUserDetails(accessToken) {
    try {
      const [managerResponse, directReportsResponse, groupsResponse] =
        await Promise.all([
          // Get manager
          axios
            .get("https://graph.microsoft.com/v1.0/me/manager", {
              headers: { Authorization: `Bearer ${accessToken}` },
            })
            .catch(() => ({ data: null })),

          // Get direct reports
          axios
            .get("https://graph.microsoft.com/v1.0/me/directReports", {
              headers: { Authorization: `Bearer ${accessToken}` },
            })
            .catch(() => ({ data: { value: [] } })),

          // Get groups
          axios
            .get("https://graph.microsoft.com/v1.0/me/memberOf", {
              headers: { Authorization: `Bearer ${accessToken}` },
            })
            .catch(() => ({ data: { value: [] } })),
        ]);

      return {
        manager: managerResponse.data,
        directReports: directReportsResponse.data.value || [],
        groups: groupsResponse.data.value || [],
        roles: [], // Could be extracted from groups or separate call
      };
    } catch (error) {
      console.error("Failed to get Azure AD user details:", error);
      return {
        manager: null,
        directReports: [],
        groups: [],
        roles: [],
      };
    }
  }
}

// User provisioning engine for enterprise rules
class UserProvisioningEngine {
  constructor() {
    this.provisioningRules = new Map();
    this.setupProvisioningRules();
  }

  setupProvisioningRules() {
    // Define how users from different providers should be provisioned
    this.provisioningRules.set("azure_ad", {
      autoProvision: true,
      defaultRole: "member",
      roleMapping: {
        Admin: "organization_admin",
        Manager: "department_admin",
        TeamLead: "team_lead",
        Developer: "member",
        Contractor: "contractor",
      },
      departmentMapping: {
        Engineering: "engineering",
        Sales: "sales",
        Marketing: "marketing",
        HR: "human_resources",
      },
      requireApproval: false,
      syncAttributes: ["jobTitle", "department", "manager"],
    });

    this.provisioningRules.set("okta", {
      autoProvision: true,
      defaultRole: "member",
      extractRolesFromGroups: true,
      groupRoleMapping: {
        "app-admins": "organization_admin",
        "app-managers": "department_admin",
        "app-users": "member",
      },
      requireApproval: false,
    });

    this.provisioningRules.set("ldap", {
      autoProvision: false, // Require manual approval
      defaultRole: "viewer",
      syncFromLDAP: true,
      ldapAttributeMapping: {
        title: "jobTitle",
        department: "department",
        manager: "manager",
        memberOf: "groups",
      },
      requireApproval: true,
    });
  }

  async processEnterpriseUser(provider, userData, context) {
    try {
      const rules = this.provisioningRules.get(provider);
      if (!rules) {
        throw new Error(`No provisioning rules for provider: ${provider}`);
      }

      // Check if user already exists
      const existingUser = await this.findExistingUser(userData.email);

      if (existingUser) {
        return await this.updateExistingUser(
          existingUser,
          userData,
          provider,
          rules
        );
      } else {
        return await this.createNewUser(userData, provider, rules, context);
      }
    } catch (error) {
      console.error("Enterprise user provisioning failed:", error);
      throw error;
    }
  }

  async createNewUser(userData, provider, rules, context) {
    try {
      if (!rules.autoProvision) {
        // Create provisional user pending approval
        return await this.createProvisionalUser(userData, provider, rules);
      }

      // Determine user role from provider data
      const assignedRole = this.determineUserRole(userData, rules);

      // Create user account
      const newUser = {
        id: crypto.randomUUID(),
        email: userData.email,
        username: userData.email.split("@")[0],
        firstName: userData.firstName,
        lastName: userData.lastName,
        fullName: userData.fullName,
        jobTitle: userData.jobTitle,
        department: this.mapDepartment(userData.department, rules),
        profilePicture: userData.profilePicture,
        isActive: true,
        emailVerified: true, // Trust enterprise providers
        createdAt: new Date(),
        updatedAt: new Date(),
        authMethod: "enterprise",
        primaryProvider: provider,
        provisionedBy: "auto",
        provisioningSource: provider,
      };

      await db.users.insertOne(newUser);

      // Assign role
      await rbac.assignRole(newUser.id, assignedRole, {
        assignedBy: "system",
        source: "auto_provisioning",
        metadata: {
          provider,
          originalRole: userData.roles,
          department: userData.department,
        },
      });

      // Link enterprise account
      await this.linkEnterpriseAccount(newUser.id, provider, userData);

      // Sync additional attributes
      if (rules.syncAttributes) {
        await this.syncUserAttributes(
          newUser.id,
          userData,
          rules.syncAttributes
        );
      }

      this.logProvisioningEvent({
        type: "user_auto_provisioned",
        userId: newUser.id,
        provider,
        role: assignedRole,
        timestamp: new Date(),
      });

      return {
        ...newUser,
        isNewUser: true,
        provisioned: true,
        assignedRole,
      };
    } catch (error) {
      console.error("New user creation failed:", error);
      throw error;
    }
  }

  determineUserRole(userData, rules) {
    // Try role mapping first
    if (rules.roleMapping && userData.roles) {
      for (const role of userData.roles) {
        if (rules.roleMapping[role]) {
          return rules.roleMapping[role];
        }
      }
    }

    // Try group-based role mapping
    if (rules.groupRoleMapping && userData.groups) {
      for (const group of userData.groups) {
        const groupName = group.displayName || group.name;
        if (rules.groupRoleMapping[groupName]) {
          return rules.groupRoleMapping[groupName];
        }
      }
    }

    // Try job title-based mapping
    if (userData.jobTitle) {
      const title = userData.jobTitle.toLowerCase();
      if (title.includes("admin")) return "organization_admin";
      if (title.includes("manager") || title.includes("director"))
        return "department_admin";
      if (title.includes("lead") || title.includes("senior"))
        return "team_lead";
    }

    // Default role
    return rules.defaultRole;
  }
}

// Advanced account linking system
class AccountLinker {
  constructor() {
    this.linkingStrategies = new Map();
    this.setupLinkingStrategies();
  }

  setupLinkingStrategies() {
    this.linkingStrategies.set("email_match", {
      priority: 1,
      matcher: (existingUser, newUserData) => {
        return (
          existingUser.email.toLowerCase() === newUserData.email.toLowerCase()
        );
      },
      confidence: "high",
    });

    this.linkingStrategies.set("username_match", {
      priority: 2,
      matcher: (existingUser, newUserData) => {
        return existingUser.username === newUserData.username;
      },
      confidence: "medium",
    });

    this.linkingStrategies.set("name_email_match", {
      priority: 3,
      matcher: (existingUser, newUserData) => {
        const nameMatch = existingUser.fullName === newUserData.fullName;
        const emailDomainMatch =
          existingUser.email.split("@")[1] === newUserData.email.split("@")[1];
        return nameMatch && emailDomainMatch;
      },
      confidence: "medium",
    });
  }

  async findLinkablAccounts(newUserData) {
    try {
      const potentialMatches = [];

      // Try each linking strategy
      for (const [strategyName, strategy] of this.linkingStrategies) {
        const matches = await db.users.find({}).toArray();

        for (const existingUser of matches) {
          if (strategy.matcher(existingUser, newUserData)) {
            potentialMatches.push({
              user: existingUser,
              strategy: strategyName,
              confidence: strategy.confidence,
              priority: strategy.priority,
            });
          }
        }
      }

      // Sort by priority and confidence
      return potentialMatches.sort((a, b) => {
        if (a.priority !== b.priority) return a.priority - b.priority;
        if (a.confidence === "high" && b.confidence !== "high") return -1;
        if (b.confidence === "high" && a.confidence !== "high") return 1;
        return 0;
      });
    } catch (error) {
      console.error("Account linking search failed:", error);
      return [];
    }
  }

  async linkAccounts(primaryUserId, secondaryUserId, linkingReason) {
    try {
      // Create account link record
      const link = {
        primaryUserId,
        secondaryUserId,
        linkingReason,
        linkedAt: new Date(),
        linkedBy: "system", // Could be 'user' for manual linking
        isActive: true,
      };

      await db.accountLinks.insertOne(link);

      // Merge account data
      await this.mergeAccountData(primaryUserId, secondaryUserId);

      // Deactivate secondary account
      await db.users.updateOne(
        { id: secondaryUserId },
        {
          $set: {
            isActive: false,
            linkedToPrimary: primaryUserId,
            linkedAt: new Date(),
          },
        }
      );

      this.logLinkingEvent({
        type: "accounts_linked",
        primaryUserId,
        secondaryUserId,
        reason: linkingReason,
        timestamp: new Date(),
      });

      return { success: true, link };
    } catch (error) {
      console.error("Account linking failed:", error);
      throw error;
    }
  }
}

Single Sign-On (SSO): Seamless Multi-Application Access

Enterprise SSO Implementation

Production-ready SSO system for multi-application environments:

// ✅ Comprehensive SSO system with SAML and OIDC support
const saml = require("passport-saml");
const jwt = require("jsonwebtoken");

class EnterpriseSSOManager {
  constructor() {
    this.applications = new Map();
    this.ssoSessions = new Map();
    this.setupApplicationRegistry();
    this.setupSAMLConfiguration();
  }

  setupApplicationRegistry() {
    // Register all applications that participate in SSO
    this.applications = new Map([
      [
        "main-app",
        {
          id: "main-app",
          name: "Main Application",
          url: "https://app.company.com",
          logoutUrl: "https://app.company.com/logout",
          trustedDomains: ["app.company.com"],
          sharedSecret: process.env.APP_MAIN_SECRET,
          requiresMFA: false,
        },
      ],

      [
        "admin-portal",
        {
          id: "admin-portal",
          name: "Admin Portal",
          url: "https://admin.company.com",
          logoutUrl: "https://admin.company.com/logout",
          trustedDomains: ["admin.company.com"],
          sharedSecret: process.env.APP_ADMIN_SECRET,
          requiresMFA: true,
        },
      ],

      [
        "analytics-dashboard",
        {
          id: "analytics-dashboard",
          name: "Analytics Dashboard",
          url: "https://analytics.company.com",
          logoutUrl: "https://analytics.company.com/logout",
          trustedDomains: ["analytics.company.com"],
          sharedSecret: process.env.APP_ANALYTICS_SECRET,
          requiresMFA: false,
        },
      ],
    ]);
  }

  setupSAMLConfiguration() {
    this.samlConfig = {
      issuer: "https://sso.company.com",
      callbackUrl: "https://sso.company.com/saml/callback",
      entryPoint: process.env.SAML_IDP_ENTRY_POINT,
      cert: process.env.SAML_IDP_CERT,
      privateCert: process.env.SAML_SP_PRIVATE_CERT,
      decryptionPvk: process.env.SAML_SP_PRIVATE_KEY,
      signatureAlgorithm: "sha256",
      digestAlgorithm: "sha256",
    };
  }

  async initiateSSO(targetApplication, user, context = {}) {
    try {
      const app = this.applications.get(targetApplication);
      if (!app) {
        throw new Error(`Unknown application: ${targetApplication}`);
      }

      // Check if user has access to this application
      const hasAccess = await this.checkApplicationAccess(
        user.id,
        targetApplication
      );
      if (!hasAccess) {
        throw new Error(`User does not have access to ${targetApplication}`);
      }

      // Check MFA requirements
      if (app.requiresMFA && !context.mfaVerified) {
        return {
          requiresMFA: true,
          mfaChallenge: await this.createMFAChallenge(
            user.id,
            targetApplication
          ),
        };
      }

      // Create SSO session
      const ssoSession = await this.createSSOSession(
        user,
        targetApplication,
        context
      );

      // Generate SSO token for target application
      const ssoToken = await this.generateSSOToken(user, app, ssoSession);

      return {
        success: true,
        ssoToken,
        redirectUrl: `${app.url}/sso/callback?token=${ssoToken}`,
        sessionId: ssoSession.id,
      };
    } catch (error) {
      console.error("SSO initiation failed:", error);
      throw error;
    }
  }

  async createSSOSession(user, targetApplication, context) {
    try {
      const sessionId = crypto.randomUUID();
      const expiresAt = new Date(Date.now() + 8 * 60 * 60 * 1000); // 8 hours

      const ssoSession = {
        id: sessionId,
        userId: user.id,
        targetApplication,
        createdAt: new Date(),
        expiresAt,
        lastAccessedAt: new Date(),
        ipAddress: context.ipAddress,
        userAgent: context.userAgent,
        mfaVerified: context.mfaVerified || false,
        isActive: true,
        accessedApplications: [targetApplication],
      };

      // Store session
      this.ssoSessions.set(sessionId, ssoSession);

      // Persist to database
      await db.ssoSessions.insertOne(ssoSession);

      this.logSSOEvent({
        type: "sso_session_created",
        sessionId,
        userId: user.id,
        targetApplication,
        timestamp: new Date(),
      });

      return ssoSession;
    } catch (error) {
      console.error("SSO session creation failed:", error);
      throw error;
    }
  }

  async generateSSOToken(user, application, ssoSession) {
    try {
      const tokenPayload = {
        sub: user.id,
        email: user.email,
        name: user.fullName,
        roles: user.roles || [],
        permissions: await this.getUserApplicationPermissions(
          user.id,
          application.id
        ),
        iat: Math.floor(Date.now() / 1000),
        exp: Math.floor(Date.now() / 1000) + 15 * 60, // 15 minutes
        aud: application.id,
        iss: "sso.company.com",
        jti: crypto.randomUUID(),
        session_id: ssoSession.id,
        mfa_verified: ssoSession.mfaVerified,
      };

      // Sign token with application-specific secret
      const token = jwt.sign(tokenPayload, application.sharedSecret, {
        algorithm: "HS256",
      });

      // Store token for validation
      await db.ssoTokens.insertOne({
        tokenId: tokenPayload.jti,
        userId: user.id,
        applicationId: application.id,
        sessionId: ssoSession.id,
        createdAt: new Date(),
        expiresAt: new Date(tokenPayload.exp * 1000),
        isUsed: false,
      });

      return token;
    } catch (error) {
      console.error("SSO token generation failed:", error);
      throw error;
    }
  }

  async validateSSOToken(token, applicationId) {
    try {
      const application = this.applications.get(applicationId);
      if (!application) {
        throw new Error("Invalid application");
      }

      // Verify token signature
      const decoded = jwt.verify(token, application.sharedSecret);

      // Check token hasn't been used
      const tokenRecord = await db.ssoTokens.findOne({
        tokenId: decoded.jti,
        applicationId,
        isUsed: false,
      });

      if (!tokenRecord) {
        throw new Error("Token not found or already used");
      }

      // Mark token as used (one-time use)
      await db.ssoTokens.updateOne(
        { tokenId: decoded.jti },
        {
          $set: {
            isUsed: true,
            usedAt: new Date(),
          },
        }
      );

      // Validate SSO session
      const ssoSession = this.ssoSessions.get(decoded.session_id);
      if (
        !ssoSession ||
        !ssoSession.isActive ||
        new Date() > ssoSession.expiresAt
      ) {
        throw new Error("Invalid or expired SSO session");
      }

      // Update session with application access
      if (!ssoSession.accessedApplications.includes(applicationId)) {
        ssoSession.accessedApplications.push(applicationId);
        ssoSession.lastAccessedAt = new Date();

        await db.ssoSessions.updateOne(
          { id: ssoSession.id },
          {
            $set: {
              accessedApplications: ssoSession.accessedApplications,
              lastAccessedAt: ssoSession.lastAccessedAt,
            },
          }
        );
      }

      this.logSSOEvent({
        type: "sso_token_validated",
        tokenId: decoded.jti,
        userId: decoded.sub,
        applicationId,
        sessionId: decoded.session_id,
        timestamp: new Date(),
      });

      return {
        valid: true,
        user: {
          id: decoded.sub,
          email: decoded.email,
          name: decoded.name,
          roles: decoded.roles,
          permissions: decoded.permissions,
        },
        session: ssoSession,
        mfaVerified: decoded.mfa_verified,
      };
    } catch (error) {
      console.error("SSO token validation failed:", error);
      return {
        valid: false,
        error: error.message,
      };
    }
  }

  async initiateGlobalLogout(sessionId, initiatingApplication) {
    try {
      const ssoSession = this.ssoSessions.get(sessionId);
      if (!ssoSession) {
        throw new Error("SSO session not found");
      }

      // Mark session as inactive
      ssoSession.isActive = false;
      await db.ssoSessions.updateOne(
        { id: sessionId },
        { $set: { isActive: false, loggedOutAt: new Date() } }
      );

      // Notify all accessed applications
      const logoutPromises = ssoSession.accessedApplications
        .filter((appId) => appId !== initiatingApplication)
        .map((appId) =>
          this.notifyApplicationLogout(appId, sessionId, ssoSession.userId)
        );

      await Promise.all(logoutPromises);

      // Remove from memory cache
      this.ssoSessions.delete(sessionId);

      this.logSSOEvent({
        type: "global_logout_initiated",
        sessionId,
        userId: ssoSession.userId,
        initiatingApplication,
        affectedApplications: ssoSession.accessedApplications,
        timestamp: new Date(),
      });

      return {
        success: true,
        affectedApplications: ssoSession.accessedApplications.length,
      };
    } catch (error) {
      console.error("Global logout failed:", error);
      throw error;
    }
  }

  async notifyApplicationLogout(applicationId, sessionId, userId) {
    try {
      const application = this.applications.get(applicationId);
      if (!application) {
        console.warn(
          `Unknown application for logout notification: ${applicationId}`
        );
        return;
      }

      // Send logout notification to application
      await axios.post(
        `${application.logoutUrl}/sso/logout`,
        {
          sessionId,
          userId,
          timestamp: new Date(),
        },
        {
          headers: {
            Authorization: `Bearer ${this.generateNotificationToken(
              application
            )}`,
            "Content-Type": "application/json",
          },
          timeout: 5000,
        }
      );

      console.log(`Logout notification sent to ${application.name}`);
    } catch (error) {
      console.error(
        `Failed to notify ${applicationId} of logout:`,
        error.message
      );
      // Don't throw - continue with other notifications
    }
  }

  // SAML Integration for external identity providers
  async handleSAMLResponse(samlResponse) {
    try {
      // Parse SAML response
      const profile = await this.parseSAMLResponse(samlResponse);

      // Create or update user from SAML attributes
      const user = await this.provisioningEngine.processEnterpriseUser("saml", {
        providerId: profile.nameID,
        email: profile.email,
        firstName: profile.firstName,
        lastName: profile.lastName,
        fullName: profile.displayName,
        groups: profile.groups,
        roles: profile.roles,
        department: profile.department,
      });

      return user;
    } catch (error) {
      console.error("SAML response handling failed:", error);
      throw error;
    }
  }

  // SSO middleware for applications
  requireSSO() {
    return async (req, res, next) => {
      try {
        const ssoToken = req.query.token || req.headers["x-sso-token"];
        const applicationId = req.headers["x-application-id"] || "main-app";

        if (!ssoToken) {
          return res.redirect(
            `https://sso.company.com/login?app=${applicationId}&returnUrl=${encodeURIComponent(
              req.originalUrl
            )}`
          );
        }

        const validation = await this.validateSSOToken(ssoToken, applicationId);

        if (!validation.valid) {
          return res.redirect(
            `https://sso.company.com/login?app=${applicationId}&error=${encodeURIComponent(
              validation.error
            )}`
          );
        }

        // Attach SSO user to request
        req.user = validation.user;
        req.ssoSession = validation.session;
        req.mfaVerified = validation.mfaVerified;

        next();
      } catch (error) {
        console.error("SSO middleware failed:", error);
        res.redirect(
          `https://sso.company.com/error?message=${encodeURIComponent(
            "SSO validation failed"
          )}`
        );
      }
    };
  }
}

// SSO routes
const ssoManager = new EnterpriseSSOManager();

app.get("/sso/login/:application", async (req, res) => {
  try {
    const { application } = req.params;
    const user = req.user; // From session authentication

    if (!user) {
      return res.redirect(
        `/login?returnUrl=${encodeURIComponent(req.originalUrl)}`
      );
    }

    const ssoResult = await ssoManager.initiateSSO(application, user, {
      ipAddress: req.ip,
      userAgent: req.get("User-Agent"),
      mfaVerified: req.mfaVerified,
    });

    if (ssoResult.requiresMFA) {
      return res.redirect(
        `/mfa/challenge?challengeId=${ssoResult.mfaChallenge.challengeId}&app=${application}`
      );
    }

    res.redirect(ssoResult.redirectUrl);
  } catch (error) {
    console.error("SSO login failed:", error);
    res.redirect(`/error?message=${encodeURIComponent(error.message)}`);
  }
});

app.post("/sso/validate", async (req, res) => {
  try {
    const { token, applicationId } = req.body;

    const validation = await ssoManager.validateSSOToken(token, applicationId);

    res.json(validation);
  } catch (error) {
    console.error("SSO validation failed:", error);
    res.status(500).json({
      valid: false,
      error: "Token validation failed",
    });
  }
});

app.post("/sso/logout", async (req, res) => {
  try {
    const { sessionId, applicationId } = req.body;

    const result = await ssoManager.initiateGlobalLogout(
      sessionId,
      applicationId
    );

    res.json(result);
  } catch (error) {
    console.error("SSO logout failed:", error);
    res.status(500).json({
      success: false,
      error: error.message,
    });
  }
});

Authentication Best Practices: Enterprise Security Standards

Comprehensive Security Framework

Production-ready authentication security checklist:

// ✅ Complete authentication security best practices implementation
class AuthenticationSecurityManager {
  constructor() {
    this.securityPolicies = new Map();
    this.threatDetection = new ThreatDetectionEngine();
    this.complianceManager = new AuthComplianceManager();
    this.setupSecurityPolicies();
    this.setupThreatDetection();
  }

  setupSecurityPolicies() {
    this.securityPolicies.set("password_policy", {
      minLength: 12,
      maxLength: 128,
      requireUppercase: true,
      requireLowercase: true,
      requireNumbers: true,
      requireSpecialChars: true,
      preventCommonPasswords: true,
      preventUserInfoInPassword: true,
      passwordHistory: 12, // Remember last 12 passwords
      maxAge: 90, // Force change every 90 days
      lockoutThreshold: 5,
      lockoutDuration: 30 * 60 * 1000, // 30 minutes
    });

    this.securityPolicies.set("session_policy", {
      maxDuration: 8 * 60 * 60 * 1000, // 8 hours
      slidingWindow: 2 * 60 * 60 * 1000, // 2 hours
      maxConcurrentSessions: 5,
      requireReauthForSensitive: true,
      logoutOnSuspiciousActivity: true,
      secureTransportOnly: true,
    });

    this.securityPolicies.set("mfa_policy", {
      requiredForAdmins: true,
      requiredForSensitiveOps: true,
      allowedMethods: ["totp", "sms", "email", "hardware_key"],
      backupCodeCount: 10,
      graceWindow: 7 * 24 * 60 * 60 * 1000, // 7 days to setup MFA
      bypassCodes: 5, // Emergency bypass codes for admins
    });
  }

  setupThreatDetection() {
    this.threatPatterns = [
      {
        name: "credential_stuffing",
        pattern:
          "Multiple failed logins across different accounts from same IP",
        threshold: { failedLogins: 20, timeWindow: 300000, uniqueAccounts: 10 },
        response: "ip_block",
      },
      {
        name: "account_takeover",
        pattern: "Login from unusual location after password change",
        threshold: { distanceKm: 500, timeWindow: 3600000 },
        response: "require_mfa",
      },
      {
        name: "session_hijacking",
        pattern: "Multiple concurrent sessions from different locations",
        threshold: { concurrentSessions: 3, distanceKm: 100 },
        response: "terminate_sessions",
      },
    ];
  }

  async enforcePasswordPolicy(password, userId = null) {
    try {
      const policy = this.securityPolicies.get("password_policy");
      const violations = [];

      // Length checks
      if (password.length < policy.minLength) {
        violations.push(
          `Password must be at least ${policy.minLength} characters`
        );
      }

      if (password.length > policy.maxLength) {
        violations.push(
          `Password must be no more than ${policy.maxLength} characters`
        );
      }

      // Character requirements
      if (policy.requireUppercase && !/[A-Z]/.test(password)) {
        violations.push("Password must contain at least one uppercase letter");
      }

      if (policy.requireLowercase && !/[a-z]/.test(password)) {
        violations.push("Password must contain at least one lowercase letter");
      }

      if (policy.requireNumbers && !/\d/.test(password)) {
        violations.push("Password must contain at least one number");
      }

      if (
        policy.requireSpecialChars &&
        !/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)
      ) {
        violations.push("Password must contain at least one special character");
      }

      // Common password check
      if (policy.preventCommonPasswords) {
        const isCommon = await this.checkCommonPassword(password);
        if (isCommon) {
          violations.push(
            "This password is too common. Please choose a more unique password."
          );
        }
      }

      // User info check
      if (policy.preventUserInfoInPassword && userId) {
        const containsUserInfo = await this.checkPasswordContainsUserInfo(
          password,
          userId
        );
        if (containsUserInfo) {
          violations.push(
            "Password must not contain your personal information"
          );
        }
      }

      // Password history check
      if (policy.passwordHistory && userId) {
        const isReused = await this.checkPasswordHistory(
          password,
          userId,
          policy.passwordHistory
        );
        if (isReused) {
          violations.push(
            `Password must not be one of your last ${policy.passwordHistory} passwords`
          );
        }
      }

      return {
        valid: violations.length === 0,
        violations,
        strength: this.calculatePasswordStrength(password),
      };
    } catch (error) {
      console.error("Password policy enforcement failed:", error);
      throw error;
    }
  }

  async detectAuthenticationThreats(event) {
    try {
      for (const pattern of this.threatPatterns) {
        const threat = await this.evaluateThreatPattern(pattern, event);

        if (threat.detected) {
          await this.respondToThreat(threat, event);
        }
      }
    } catch (error) {
      console.error("Threat detection failed:", error);
    }
  }

  async evaluateThreatPattern(pattern, event) {
    try {
      switch (pattern.name) {
        case "credential_stuffing":
          return await this.detectCredentialStuffing(pattern, event);

        case "account_takeover":
          return await this.detectAccountTakeover(pattern, event);

        case "session_hijacking":
          return await this.detectSessionHijacking(pattern, event);

        default:
          return { detected: false };
      }
    } catch (error) {
      console.error(
        `Threat pattern evaluation failed for ${pattern.name}:`,
        error
      );
      return { detected: false };
    }
  }

  async detectCredentialStuffing(pattern, event) {
    if (event.type !== "login_failed") return { detected: false };

    const timeWindow = pattern.threshold.timeWindow;
    const since = new Date(Date.now() - timeWindow);

    // Count failed logins from same IP
    const failedLogins = await db.authEvents.countDocuments({
      type: "login_failed",
      ipAddress: event.ipAddress,
      timestamp: { $gte: since },
    });

    // Count unique accounts targeted
    const uniqueAccounts = await db.authEvents.distinct("userId", {
      type: "login_failed",
      ipAddress: event.ipAddress,
      timestamp: { $gte: since },
    });

    const detected =
      failedLogins >= pattern.threshold.failedLogins &&
      uniqueAccounts.length >= pattern.threshold.uniqueAccounts;

    return {
      detected,
      pattern: pattern.name,
      severity: "high",
      details: {
        ipAddress: event.ipAddress,
        failedLogins,
        uniqueAccounts: uniqueAccounts.length,
        timeWindow,
      },
    };
  }

  async respondToThreat(threat, event) {
    try {
      this.logSecurityThreat(threat, event);

      switch (threat.pattern) {
        case "credential_stuffing":
          if (threat.details.failedLogins >= 50) {
            await this.blockIPAddress(threat.details.ipAddress, "24h");
          } else {
            await this.rateLimitIPAddress(threat.details.ipAddress, "1h");
          }
          break;

        case "account_takeover":
          await this.requireAdditionalVerification(event.userId);
          break;

        case "session_hijacking":
          await this.terminateAllUserSessions(event.userId);
          break;
      }

      // Alert security team
      await this.alertSecurityTeam(threat, event);
    } catch (error) {
      console.error("Threat response failed:", error);
    }
  }

  async generateSecurityReport(timeRange) {
    try {
      const startDate = new Date(timeRange.start);
      const endDate = new Date(timeRange.end);

      const [
        loginAttempts,
        successfulLogins,
        failedLogins,
        mfaChallenges,
        threatEvents,
        suspiciousIPs,
        passwordChanges,
      ] = await Promise.all([
        db.authEvents.countDocuments({
          type: "login_attempt",
          timestamp: { $gte: startDate, $lte: endDate },
        }),

        db.authEvents.countDocuments({
          type: "login_success",
          timestamp: { $gte: startDate, $lte: endDate },
        }),

        db.authEvents.countDocuments({
          type: "login_failed",
          timestamp: { $gte: startDate, $lte: endDate },
        }),

        db.authEvents.countDocuments({
          type: "mfa_challenge",
          timestamp: { $gte: startDate, $lte: endDate },
        }),

        db.threatEvents.countDocuments({
          timestamp: { $gte: startDate, $lte: endDate },
        }),

        db.threatEvents
          .aggregate([
            {
              $match: {
                timestamp: { $gte: startDate, $lte: endDate },
              },
            },
            {
              $group: {
                _id: "$ipAddress",
                count: { $sum: 1 },
              },
            },
            {
              $sort: { count: -1 },
            },
            {
              $limit: 10,
            },
          ])
          .toArray(),

        db.authEvents.countDocuments({
          type: "password_changed",
          timestamp: { $gte: startDate, $lte: endDate },
        }),
      ]);

      const report = {
        timeRange: { start: startDate, end: endDate },
        summary: {
          totalLoginAttempts: loginAttempts,
          successfulLogins,
          failedLogins,
          successRate: ((successfulLogins / loginAttempts) * 100).toFixed(2),
          mfaChallenges,
          threatEvents,
          passwordChanges,
        },
        threats: {
          topSuspiciousIPs: suspiciousIPs,
          threatsByType: await this.getThreatsByType(startDate, endDate),
        },
        recommendations: await this.generateSecurityRecommendations(
          startDate,
          endDate
        ),
        generatedAt: new Date(),
      };

      return report;
    } catch (error) {
      console.error("Security report generation failed:", error);
      throw error;
    }
  }
}

// Complete authentication middleware with all security features
class SecureAuthMiddleware {
  constructor() {
    this.securityManager = new AuthenticationSecurityManager();
    this.rbac = new RoleBasedAccessControl();
    this.jwtManager = new SecureJWTManager();
    this.mfaManager = new MultiFactorAuthManager();
  }

  // Comprehensive authentication middleware
  requireAuth(options = {}) {
    return async (req, res, next) => {
      try {
        // Step 1: Extract and validate credentials
        const authResult = await this.extractAndValidateAuth(req);
        if (!authResult.success) {
          return res.status(401).json({
            error: "Authentication required",
            message: authResult.message,
          });
        }

        // Step 2: Security threat detection
        await this.securityManager.detectAuthenticationThreats({
          type: "api_access",
          userId: authResult.user.id,
          ipAddress: req.ip,
          userAgent: req.get("User-Agent"),
          timestamp: new Date(),
        });

        // Step 3: Check permissions if required
        if (options.permission) {
          const permissionResult = await this.rbac.checkPermission(
            authResult.user.id,
            options.permission,
            options.resource,
            {
              ipAddress: req.ip,
              userAgent: req.get("User-Agent"),
              mfaVerified: authResult.mfaVerified,
            }
          );

          if (!permissionResult.granted) {
            return res.status(403).json({
              error: "Access denied",
              message: "Insufficient permissions",
              requiredPermission: options.permission,
            });
          }
        }

        // Step 4: MFA check if required
        if (options.requireMFA && !authResult.mfaVerified) {
          const mfaChallenge = await this.mfaManager.requireMFA(
            authResult.user.id,
            options.mfaReason || "api_access"
          );

          if (mfaChallenge.required) {
            return res.status(403).json({
              error: "MFA required",
              mfaChallenge,
            });
          }
        }

        // Attach user and auth info to request
        req.user = authResult.user;
        req.authMethod = authResult.method;
        req.mfaVerified = authResult.mfaVerified;

        next();
      } catch (error) {
        console.error("Authentication middleware failed:", error);
        res.status(500).json({
          error: "Authentication error",
          message: "Unable to verify your identity",
        });
      }
    };
  }
}

// Usage
const authMiddleware = new SecureAuthMiddleware();

// Public endpoint
app.get("/api/public/status", (req, res) => {
  res.json({ status: "operational" });
});

// Basic authenticated endpoint
app.get("/api/user/profile", authMiddleware.requireAuth(), (req, res) => {
  res.json({ user: req.user });
});

// Permission-required endpoint
app.delete(
  "/api/admin/users/:id",
  authMiddleware.requireAuth({
    permission: "user:delete",
    requireMFA: true,
    mfaReason: "user_deletion",
  }),
  (req, res) => {
    res.json({ success: true });
  }
);

Key Takeaways

Advanced authorization completes the identity picture by transforming authentication into sophisticated access control. RBAC systems handle complex organizational hierarchies, social login scales across enterprises, SSO enables seamless multi-application access, and comprehensive security practices protect against modern threats.

The complete identity architecture mindset:

  • Authorization scales with complexity: Role hierarchies and conditional permissions adapt to real organizational structures
  • Social login requires enterprise thinking: Account linking, provisioning rules, and compliance considerations matter at scale
  • SSO is infrastructure: Multi-application environments need centralized identity with distributed access control
  • Security never stops: Threat detection, compliance monitoring, and proactive defense are continuous processes

What distinguishes enterprise identity systems:

  • RBAC implementations that handle role inheritance, conditional access, and dynamic permission calculation
  • Social login systems with sophisticated account linking, provisioning automation, and enterprise provider integration
  • SSO architectures that seamlessly connect multiple applications with centralized session management
  • Security frameworks that detect threats, enforce policies, and maintain compliance automatically

Series Conclusion

We’ve completed comprehensive authentication and authorization covering identity verification, session management, token systems, enterprise integration, and advanced security practices. You now possess the complete identity toolkit for building systems that scale from startups to enterprise environments.

The complete identity architect’s mastery:

  • Authentication fundamentals with session and token-based approaches that scale across devices and applications
  • Authorization systems that handle complex permissions, roles, and conditional access at enterprise scale
  • Enterprise integration through OAuth, SAML, SSO, and sophisticated account linking strategies
  • Security operations with threat detection, policy enforcement, and automated compliance management
  • Best practices that balance security requirements with user experience across diverse organizational needs

What’s Next

With identity and security foundations complete, we move into the testing and quality assurance phase of backend development. You’ll learn to build comprehensive test suites that validate both functionality and security, implement quality gates that prevent regressions, and create CI/CD pipelines that maintain code quality as applications scale.

Identity provides the foundation. Security protects what you’ve built. Testing ensures it all works correctly under real-world conditions while maintaining the security and performance standards users expect.

You’re no longer just building authentication systems—you’re architecting identity infrastructures that adapt to organizational growth, integrate with enterprise systems, and maintain security through automated threat detection and response. The identity architecture is complete. Now we ensure quality matches the sophistication through comprehensive testing strategies.