diff --git a/content/7-common-iam-risks-and-how-to-avoid-them/iam-consequences.png b/content/7-common-iam-risks-and-how-to-avoid-them/iam-consequences.png new file mode 100644 index 00000000..4cc5d642 Binary files /dev/null and b/content/7-common-iam-risks-and-how-to-avoid-them/iam-consequences.png differ diff --git a/content/7-common-iam-risks-and-how-to-avoid-them/iam-life-cycle-diagram.png b/content/7-common-iam-risks-and-how-to-avoid-them/iam-life-cycle-diagram.png new file mode 100644 index 00000000..77957e2f Binary files /dev/null and b/content/7-common-iam-risks-and-how-to-avoid-them/iam-life-cycle-diagram.png differ diff --git a/content/7-common-iam-risks-and-how-to-avoid-them/iam-risk-matrix.png b/content/7-common-iam-risks-and-how-to-avoid-them/iam-risk-matrix.png new file mode 100644 index 00000000..e36776c7 Binary files /dev/null and b/content/7-common-iam-risks-and-how-to-avoid-them/iam-risk-matrix.png differ diff --git a/content/7-common-iam-risks-and-how-to-avoid-them/index.md b/content/7-common-iam-risks-and-how-to-avoid-them/index.md new file mode 100644 index 00000000..3200740d --- /dev/null +++ b/content/7-common-iam-risks-and-how-to-avoid-them/index.md @@ -0,0 +1,217 @@ +--- +title: 7 Common IAM Risks and How to Avoid Them +date: "2024-11-04" +description: " Reveal the 7 critical IAM risks that pose a threat to your business. Discover actionable advice to reduce these risks and strengthen your security measures." +cover: "7-common-iam-risks-and-how-to-avoid-them.png" +category: "programming" +author: "Mostafa Ibrahim" +--- + +## Table of Contents + +- [Introduction](#introduction) +- [The Importance of Mitigating Risks in Identity and Access Management](#the-importance-of-mitigating-risks-in-identity-and-access-management) +- [Common IAM Risks and Strategies to Avoid Them](#common-iam-risks-and-strategies-to-avoid-them) + - [1. Excessive User Privileges](#1-excessive-user-privileges) + - [2. Weak Password Policies](#2-weak-password-policies) + - [3. Lack of Visibility and Monitoring](#3-lack-of-visibility-and-monitoring) + - [4. Inadequate Offboarding Processes](#4-inadequate-offboarding-processes) + - [5. Misconfigured IAM Policies](#5-misconfigured-iam-policies) + - [6. Shadow IT Risks](#6-shadow-it-risks) + - [7. IAM System Outages](#7-iam-system-outages) +- [The Need for a Comprehensive IAM Strategy](#the-need-for-a-comprehensive-iam-strategy) +- [SuperTokens: The Solution to Key IAM Challenges](#supertokens-the-solution-to-key-iam-challenges) +- [Frequently Asked Questions About IAM Risks](#frequently-asked-questions-about-iam-risks) + - [What is IAM safety?](#what-is-iam-safety) + - [What is the risk matrix in IAM?](#what-is-the-risk-matrix-in-iam) + - [What are IAM conditions?](#what-are-iam-conditions) + - [How to calculate the risk?](#how-to-calculate-the-risk) +- [Conclusion](#conclusion) + +## Introduction + +Managing user identities and access rights is becoming quite a challenge. With more people working remotely and organizations using cloud services, it's more important than ever to keep track of who has access to what. This is where Identity and Access Management (IAM) comes in. + +IAM is all about making sure that the right people have access to the right resources at the right times. Think of it like a digital gatekeeper—it helps protect sensitive information by controlling who can enter and access what. However, with this responsibility comes some big risks that organizations need to be aware of and tackle head-on. + +This guide will break down some of the most common IAM risks and their possible effects. Plus, it will offer practical strategies to mitigate those risks, helping organizations strengthen their security measures and keep their data safe. + +## The Importance of Mitigating Risks in Identity and Access Management + +![IAM consequences](/iam-consequences.png) + +The consequences of poorly managed IAM systems can be severe and far-reaching. According to a recent [IBM Security report](https://www.ibm.com/reports/data-breach), the average cost of a data breach reached $4.88 million in 2024, with compromised credentials being a leading cause. For security-conscious organizations, the impact of unmanaged IAM risks can manifest in several critical ways: + +* **Financial Impact:** Beyond immediate data breach costs, organizations face potential regulatory fines, legal expenses, and lost business opportunities. +* **Reputational Damage:** Trust is paramount; once broken due to a security incident, rebuilding customer confidence can take years. +* **Operational Disruption:** Inadequate access controls can lead to workflow bottlenecks and reduced productivity. +* **Compliance Violations:** With regulations like GDPR and CCPA enforcing strict data protection requirements, IAM failures can result in significant penalties. + +![Man unlocking digital shield](/man-unlocking-digital-shield.png) + +## Common IAM Risks and Strategies to Avoid Them + +Here are seven prevalent IAM risks along with actionable strategies to mitigate them: + +### 1\. Excessive User Privileges + +Excessive user privileges occur when employees or systems are granted more access than they require to perform their job functions. This issue is a frequent oversight, often stemming from "permission creep," where users accumulate access rights over time without review or revocation. While this may seem harmless initially, it creates vulnerabilities that attackers or malicious insiders can exploit. + +**Impact:** Increased potential damage from compromised accounts and insider threats. + +**How to Avoid:** + +* Implement Role-Based Access Control (RBAC) to align permissions with job functions. +* Conduct quarterly access reviews to identify and revoke unnecessary privileges. +* Use automated tools to detect and alert privilege escalations. +* Document and justify all privilege assignments. + +### 2\. Weak Password Policies + +![Strong password rules](/strong-password-rules.png) + +Weak password policies are a major issue in cybersecurity. Even though there are better ways to authenticate users now, many companies still depend on passwords and don’t have strong enough security measures in place. Some common problems are allowing short passwords, not requiring regular updates, and not blocking common phrases or patterns. + +When passwords are weak, it’s not just bad news for the company; it can also hurt customer trust, especially if their data gets leaked. Improving password policies is one of the easiest and most effective ways to strengthen identity and access management systems. + +**Impact:** Weak passwords provide attackers with an easy entry point into organizational systems. + +**How to Avoid:** + +* Enforce strong password requirements (length, complexity, history). +* Implement Multi-Factor Authentication (MFA) across all systems. +* Use password managers to encourage unique passwords. +* Provide regular password security training for employees. + +### 3\. Lack of Visibility and Monitoring + +IAM visibility refers to an organization’s ability to monitor access patterns, detect anomalies, and audit changes across its user base. Without adequate visibility, it becomes nearly impossible to identify unauthorized access attempts or trace the origins of suspicious activity. This blind spot is a critical vulnerability, especially in environments with complex infrastructures or frequent system integrations. + +[On average, companies take 197 days to identify and 69 days to contain a breach](https://www.varonis.com/blog/data-breach-response-times#:~:text=The%20cost%20of%20a%20breach%20goes%20beyond,of%20time%20costs%20businesses%20millions%20of%20dollars.), according to IBM. Proper IAM monitoring can help reduce this time, potentially saving millions of dollars. + +**Impact:** Without proper visibility, organizations can't detect unauthorized access attempts or suspicious behavior patterns until it's too late. + +**How to Avoid:** + +* Deploy Security Information and Event Management (SIEM) solutions. +* Implement User and Entity Behavior Analytics (UEBA). +* Create automated alerts for suspicious activities. +* Maintain detailed access logs and conduct regular reviews. + +### 4\. Inadequate Offboarding Processes + +Employee transitions are a normal part of business, but offboarding is often neglected when it comes to security. If organizations don’t quickly revoke access after an employee leaves, their systems can be at risk of unauthorized use. + +In many cases, ex-employees unintentionally retain access due to outdated directories or inefficient HR-IAM integration. However, this oversight creates significant risks, including potential sabotage, data theft, or compliance breaches, particularly in industries handling sensitive information. + +**Impact:** Former employees retaining access creates significant security risks and potential compliance violations. + +**How to Avoid**: + +* Create automated offboarding workflows. +* Implement Just-in-Time access provisioning. +* Regularly audit dormant accounts. +* Maintain up-to-date user directories integrated with HR systems. + +### 5\. Misconfigured IAM Policies + +IAM misconfigurations often happen because digital transformation is happening so fast. As we adopt more cloud services and integrate different systems, managing policies becomes more complicated. Sometimes, these misconfigurations can accidentally give too much access to sensitive information or limit access for legitimate users, which can mess up workflows and cause compliance problems. + +[Gartner predicts that through 2025, 99% of cloud security failures will be the customer's fault](https://www.gartner.com/smarterwithgartner/is-the-cloud-secure#:~:text=Through%202025%2C%2099%25%20of%20cloud%20security%20failures%20will%20be%20the%20customer%E2%80%99s%20fault.). Misconfigurations, including those in IAM, are significant contributors to these failures. + +**Impact:** Misconfigured policies can inadvertently expose sensitive resources or prevent legitimate access to critical systems. + +**How to Avoid:** + +* Use policy validation tools. +* Implement configuration management best practices. +* Conduct regular security assessments. +* Maintain detailed documentation of IAM policies. + +### 6\. Shadow IT Risks + +Shadow IT refers to the use of unauthorized applications or systems by employees, bypassing approved IAM frameworks. This practice has surged in the era of remote work, with employees turning to third-party tools to boost productivity without considering security implications. + +When organizations don’t know about these applications, it's harder to keep track of data and enforce security rules. This can lead to data leaks, security breaches, or problems with compliance. To handle shadow IT effectively, companies need to find a way to allow employees to use useful tools while still keeping their data safe. + +**Impact:** Unauthorized applications create security blind spots and increase the risk of data leakage. + +**How to Avoid:** + +* Implement Cloud Access Security Broker (CASB) solutions. +* Create clear policies for application usage. +* Provide approved alternatives to common shadow IT applications. +* Conduct regular employee training on security risks. + +### 7\. IAM System Outages + +![IAM life cycle](/iam-life-cycle-diagram.png) + +IAM outages are more than an inconvenience—they can bring entire operations to a standstill. As IAM systems handle authentication for critical applications, any downtime disrupts workflows and leaves organizations scrambling for alternatives. + +The risks extend beyond operational delays. In many cases, outages force employees to use unsecured workarounds, such as shared credentials or local copies of sensitive files, further compromising security. Preventing outages involves not only robust infrastructure but also ongoing testing and monitoring to ensure resilience. + +**Impact**: System downtime can paralyze operations and force unsafe workarounds. + +**How to Avoid:** + +* Implement high-availability architectures. +* Regularly test backup and disaster recovery plans. +* Monitor system health proactively. +* Maintain documented incident response procedures. + +## The Need for a Comprehensive IAM Strategy + +A robust IAM strategy requires more than just implementing technical controls. Organizations need to adopt a holistic approach that combines technology, processes, and people. This includes regular training, clear policies, and the right tools to manage and monitor access effectively. + +Modern IAM solutions like [SuperTokens](https://supertokens.com/product) provide the foundation for implementing these strategies effectively. With features designed to address common IAM challenges, organizations can significantly reduce their risk exposure while improving operational efficiency. + +**_Remember: Security is not a destination but a journey. Stay vigilant, stay updated, and keep your IAM infrastructure robust and resilient._** + +## SuperTokens: The Solution to Key IAM Challenges + + ![Supertokens homepage](/supertokens-homepage.png) + +SuperTokens offers a comprehensive approach to addressing IAM risk. The platform provides: + +* **Granular Access Control**: Define precise roles and permissions to ensure users access only the resources they need, reducing the risk of unauthorized access or data exposure. +* **Security Best Practices Built-In**: Leverages industry-standard protocols to defend against common vulnerabilities like SQL injection and cross-site scripting. +* **Detailed Audit Logging**: Monitor user activities and system changes to support compliance and streamline security investigations. +* **Reliable Scalability and Availability**: Maintain seamless operations during high traffic, with the flexibility to scale as user demand grows. +* **Administrator-Friendly Interface**: Simplify user and security management with an intuitive and easy-to-navigate dashboard. +* **Seamless System Integration**: Effortlessly connect with existing workflows and infrastructure for streamlined implementation. +* **Customizable Authentication UI**: Personalize authentication workflows to reflect brand identity, enhancing user confidence. +* **Multi-Factor Authentication (MFA) Support**: Strengthen security by adding extra identity verification steps, reducing risks of unauthorized access. + +## Frequently Asked Questions About IAM Risks + +### What is IAM safety? + +IAM safety refers to the security measures and controls implemented to protect digital identities and manage access to resources. It encompasses authentication, authorization, and accounting (AAA) to ensure only legitimate users can access appropriate resources. + +### What is the risk matrix in IAM? + +![IAM risk matrix](/iam-risk-matrix.png) + +A risk matrix in IAM helps organizations evaluate and prioritize potential security threats based on their likelihood and potential impact. This tool aids in resource allocation and risk mitigation planning. + +### What are IAM conditions? + +IAM conditions are specific criteria that must be met before access is granted. These can include time-based restrictions, IP address limitations, device requirements, or multi-factor authentication completion. + +### How to calculate the risk? + +IAM risk calculation involves assessing both the probability of a security incident and its potential impact. Organizations typically use metrics such as: + +* Number of privileged accounts +* Failed login attempts +* Time to revoke access +* Policy violation incidents + +## Conclusion + +As organizations continue to digitally transform, the importance of robust IAM practices cannot be overstated. By understanding and addressing common IAM risks, organizations can better protect their assets while ensuring efficient operations. + +The key to success lies in adopting a proactive approach to IAM risk management, implementing appropriate tools and controls, and maintaining vigilance through regular assessments and updates. Modern solutions like SuperTokens offer comprehensive authentication and identity management capabilities through their [self-hosted authentication solution](https://supertokens.com/blog/self-hosted-authentication/) that can help organizations build a strong foundation for their IAM strategy. With the right combination of tools, processes, and ongoing oversight, organizations can effectively mitigate common IAM risks and maintain a strong security posture. + +**Secure your organization with SuperTokens and follow best practices for risk management.** [**Signup today**](https://supertokens.com/product)**!** \ No newline at end of file diff --git a/content/7-common-iam-risks-and-how-to-avoid-them/man-unlocking-digital-shield.png b/content/7-common-iam-risks-and-how-to-avoid-them/man-unlocking-digital-shield.png new file mode 100644 index 00000000..762e78ee Binary files /dev/null and b/content/7-common-iam-risks-and-how-to-avoid-them/man-unlocking-digital-shield.png differ diff --git a/content/7-common-iam-risks-and-how-to-avoid-them/strong-password-rules.png b/content/7-common-iam-risks-and-how-to-avoid-them/strong-password-rules.png new file mode 100644 index 00000000..7c044937 Binary files /dev/null and b/content/7-common-iam-risks-and-how-to-avoid-them/strong-password-rules.png differ diff --git a/content/7-common-iam-risks-and-how-to-avoid-them/supertokens-homepage.png b/content/7-common-iam-risks-and-how-to-avoid-them/supertokens-homepage.png new file mode 100644 index 00000000..84e19a7c Binary files /dev/null and b/content/7-common-iam-risks-and-how-to-avoid-them/supertokens-homepage.png differ diff --git a/content/authelia-alternatives/auth0.png b/content/authelia-alternatives/auth0.png new file mode 100644 index 00000000..ed89e23f Binary files /dev/null and b/content/authelia-alternatives/auth0.png differ diff --git a/content/authelia-alternatives/authentik.png b/content/authelia-alternatives/authentik.png new file mode 100644 index 00000000..5b0536c5 Binary files /dev/null and b/content/authelia-alternatives/authentik.png differ diff --git a/content/authelia-alternatives/aws-cognito.png b/content/authelia-alternatives/aws-cognito.png new file mode 100644 index 00000000..c54bbb59 Binary files /dev/null and b/content/authelia-alternatives/aws-cognito.png differ diff --git a/content/authelia-alternatives/fusion-auth.png b/content/authelia-alternatives/fusion-auth.png new file mode 100644 index 00000000..a4ecb4c4 Binary files /dev/null and b/content/authelia-alternatives/fusion-auth.png differ diff --git a/content/authelia-alternatives/index.md b/content/authelia-alternatives/index.md new file mode 100644 index 00000000..b452562d --- /dev/null +++ b/content/authelia-alternatives/index.md @@ -0,0 +1,341 @@ +--- +title: "7 Top Authelia Alternatives for Enhanced Authentication in 2025?" +date: "2024-09-10" +description: "In this blog, we're going to look at the top 7 alternatives to Authelia. We’ll go over the main features, pricing, pros and cons of each option to help you decide what’s best for your authentication strategy." +cover: "authelia-alternatives.png" +category: "programming" +author: "Mostafa Ibrahim" +--- + +## Table of Contents + +- [Introduction](#introduction) +- [**1. SuperTokens**](#1-supertokens) + * [**Key Features:**](#key-features) + * [**Pricing:**](#pricing) + * [**Limitations:**](#limitations) +- [**2. Keycloak**](#2-keycloak) + * [**Key Features:**](#key-features-1) + * [**Pricing:**](#pricing-1) + * [**Limitations:**](#limitations-1) +- [**3. Authentik**](#3-authentik) + * [**Key Features:**](#key-features-2) + * [**Pricing:**](#pricing-2) + * [**Limitations:**](#limitations-2) +- [**4. FusionAuth**](#4-fusionauth) + * [**Key Features:**](#key-features-3) + * [**Pricing:**](#pricing-3) + * [**Limitations:**](#limitations-3) +- [**5. Okta**](#5-okta) + * [**Key Features:**](#key-features-4) + * [**Pricing:**](#pricing-4) + * [**Limitations:**](#limitations-4) +- [**6. Auth0**](#6-auth0) + * [**Pricing:**](#pricing-5) + * [**Limitations:**](#limitations-5) +- [**7. Amazon Cognito**](#7-amazon-cognito) + * [**Pricing:**](#pricing-6) + * [**Limitations:**](#limitations-6) +- [**Making the Right Choice**](#making-the-right-choice) + +## Introduction + +Authentication servers form the backbone of modern application security and developers are looking for strong and flexible options that offer more than just simple password protection. Authelia is a good choice, but many organizations are checking out other options that might fit their needs better, whether that means having more features, different pricing plans, or easier integrations. + +According to recent[ security statistics from IBM](https://www.ibm.com/security/data-breach), compromised credentials remain the most common attack vector for data breaches, accounting for nearly [16% of all incidents](https://www.zscaler.com/blogs/product-insights/7-key-takeaways-ibm-s-cost-data-breach-report-2024#:~:text=Notable%20stats%3A%C2%A0Credential%2Dbased%20attacks%20were%20the%20most%20common%20attack%20vector%2C%20accounting%20for%C2%A016%25%20of%20all%20breaches.). This underscores the critical importance of choosing the right authentication solution for your organization. + +In this blog, we're going to look at the top 7 alternatives to Authelia. Each one has its own strengths and is designed to meet different needs for security, scalability, and ease of use. Whether you're a startup looking for a simple solution that works well for developers or a large company with complex identity and access management needs, you'll find plenty of choices for secure authentication. We’ll go over the main features, pricing, pros and cons of each option to help you decide what’s best for your authentication strategy. + + +## **1. SuperTokens** + +![supertokens homepage](./supertokens-homepage.png) + +SuperTokens has emerged as a powerful contender in the authentication space, particularly for organizations prioritizing secure session management and user data protection. Unlike traditional solutions, SuperTokens offers a unique approach to handling user sessions through rotating refresh tokens, making it significantly harder for attackers to exploit stolen credentials. + + +### **Key Features:** + +- **Advanced Session Management**: SuperTokens offers rotating refresh tokens for heightened security. If a token is compromised, it’s immediately invalidated, preventing potential session hijacking. + +- **Comprehensive MFA Support**: Supports various[ multi-factor authentication methods](https://supertokens.com/blog/benefits-of-multi-factor-authentication), including Time-based One-Time Passwords (TOTP). This MFA can adapt based on factors like login location and device. + +- **Developer-First Approach**: Provides extensive documentation and SDKs for popular frameworks + +- **Customizable User Flows**: Offers flexibility in implementing[ various authentication types](https://supertokens.com/blog/types-of-authentication) + +- **Self-Hosting Option**: Gives complete control over data and infrastructure + +- **Passwordless Authentication**: Supports modern[ email magic links](https://supertokens.com/features/email-magic-links) for seamless login experiences + + +### **Pricing:** + +- The [self-hosted](https://supertokens.com/blog/self-hosted-authentication) version is free and open-source + +- Managed service available with tiered pricing based on usage + +- Enterprise features available for larger implementations + + +### **Limitations:** + +- Some enterprise-level features might require additional configuration + +- Community is growing but smaller compared to more established alternatives + +## **2. Keycloak** + +![keycloak homepage ](./keycloak.png) + +Keycloak is a proven and reliable tool for managing identity and access, perfect for businesses of all sizes. It's open-source, which means it's flexible and can fit various needs, whether for a small app or a big system. With strong support for different protocols and lots of customization options, it gives organizations the control they need over their authentication processes. + +### **Key Features:** + +- **Comprehensive Protocol Support**: Delivers enterprise-grade implementation of OAuth2, OpenID Connect, and SAML protocols. Organizations can use multiple protocols simultaneously, making it easier to support legacy systems while adopting modern authentication standards. + +- **User Federation**: Seamless integration with LDAP and Active Directory + +- **Social Login**: Built-in support for major social identity providers like Google, Facebook, and GitHub. + +- **Custom Authentication Flows**: It allows the creation of complex authentication flows configured in the Keycloak Admin Console by adding authenticators, sub-flows, and custom rules directly, with custom Java code options for advanced requirements. This supports multi-step and conditional authentication setups too. + +- **Admin Console**: Intuitive interface for managing users and configurations + +- **Clustering Support**: Implements true high availability through active-active clustering, supporting large-scale deployments. The system handles session replication and failover automatically, ensuring continuous service availability. + + +### **Pricing:** + +- Free and open-source + +- Commercial support is available through Red Hat + +- Optional enterprise consulting services + + +### **Limitations:** + +- The initial setup can be complex + +- Requires significant resources for optimal performance + +- Developers may face a steep learning curve when working with advanced features + + +## **3. Authentik** + +![authentik alternatives](./authentik.png) + +Authentik offers a new way to handle identity management that’s both modern and easy to use. It’s built for self-hosted setups and has strong access control features along with a user-friendly interface. What really makes Authentik stand out is how it simplifies complicated authentication processes while still providing all the features you'd expect from a top-tier solution. Plus, its focus on Docker makes it a great choice for teams that are into modern deployment methods. + + +### **Key Features:** + +- **Flexible Policy Engine:** Create advanced access control rules based on user details, time, location, and more with an easy-to-use builder.  + +- **Built-in Application Catalog:** Access ready-to-use integration templates for popular apps, complete with setup guides and automated technical management. + +- **Automated User Provisioning:** Simplify user account management with automated creation, updates, and disabling across apps based on your rules.  + +- **Custom Branding:** Personalize the login experience with customizable layouts, colors, and the option to add custom CSS or JavaScript. + +- **Docker-First Deployment:** Enjoy consistent setup across environments with included Docker and Kubernetes deployment files. + +- **Event Export:** Track activities with detailed logs and export events for monitoring along with real-time notification webhooks. + + +### **Pricing:** + +- The core version is free and open-source + +- Enterprise and Enterprise Plus tiers are available with additional features + +- Support packages are offered separately + + +### **Limitations:** + +- Primarily focused on self-hosted deployments + +- Some enterprise features are only available in paid tiers + +- Smaller ecosystem compared to major competitors + + +## **4. FusionAuth** + +![fusionauth](./fusion-auth.png) + +FusionAuth delivers a compelling blend of powerful features and developer-friendly implementation. This authentication solution stands out for its attention to unique use cases, such as family accounts and complex user relationships. Built to handle sophisticated authentication scenarios while maintaining ease of use, FusionAuth particularly excels in situations requiring deep customization of the authentication experience. + + +### **Key Features:** + +- **Advanced Password Security**: Offers breach detection, password strength checks, and customizable password rules, enforcing security policies and automatically checking passwords against known breaches. + +- **Comprehensive API**: Provides a robust RESTful API covering all UI functionalities, with extensive documentation, client libraries, and integration examples. + +- **Theme Management**: Allows for flexible theming with support for multiple themes, enabling customized branding for various applications and user groups. + +- **Family Support**: Supports family relationships and parental controls, handling consent, access restrictions, and family account linking in line with COPPA compliance. + +- **Advanced Analytics**: Provides in-depth insights into user behavior and login patterns through interactive dashboards, tracking failed attempts and engagement metrics. + +- **Webhook System**: Integrates with external systems in real-time via a flexible webhook system, allowing custom notifications and complex automation. + + +### **Pricing:** + +- Free tier available for basic usage + +- Usage-based pricing for additional features + +- Enterprise plans for larger implementations + + +### **Limitations:** + +- Limited field-specific filtering in user searches + +- Some advanced features require paid tiers + +- Setup complexity can increase with custom requirements + + +## **5. Okta** + +![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXeluJxWfwj4ozU8ZVWWOSvILsGGs36LBBgB-V_raVXO0c0yMSmuZUN1PlbrEVH0Ni13fdSRk5tiMr36BeOC2gqsd6V7jEn9bbWDLJ02EJ-0FLXX6s1hI7Z0bwiYMFEuXwFXOT4yQnoLMPCvNqWvA8NBTJQe?key=jF7q6wIiWjwYrFQQ_CalAA) + +Okta has become a popular choice for companies when it comes to managing identity and access. It offers a wide range of services for authentication and authorization. What sets Okta apart is its ability to provide a strong and flexible solution that meets the needs of larger organizations without being too complicated to use. It combines top-notch security with the ability to work well with various tech systems, making it a great fit for many businesses. + + +### **Key Features:** + +- **Universal Directory**: Centralized user management with custom schemas, rich profiles, and automatic profile enrichment. Supports custom attributes, group hierarchies, and advanced segmentation, with real-time sync across connected applications. + +- **Adaptive MFA**: Context-aware, risk-adaptive authentication using device, location, and behavior data. Supports custom risk profiles and automated step-up authentication. + +- **Lifecycle Management**: Automates user journeys with workflow automation, role-based access control, and audit trails. Updates access across integrated applications in real-time. + +- **API Access Management**: Secures APIs via OAuth 2.0 and OpenID Connect, with token management, rate limiting, and API analytics. + +- **Advanced Reporting**: Provides custom dashboards and scheduled reports for insights on user activity, authentication patterns, and security events. + +- **Okta Integration Network**: Connects with thousands of apps, providing easy access management and integration for secure, unified application access across the organization. + + +### **Pricing:** + +- Premium pricing structure + +- Custom enterprise pricing based on requirements + +- Volume discounts available + + +### **Limitations:** + +- Higher cost compared to other solutions + +- May be overly complex for smaller implementations + +- Limited self-hosting options + + +## **6. Auth0** + +![auth0](./auth0.png) + +Auth0 has carved out its niche by focusing on developer experience without compromising on security features. This authentication platform simplifies the implementation of complex authentication flows while providing the flexibility needed for custom solutions. Plus, with its detailed documentation and ready-made components, it’s super appealing for teams that want to set up authentication quickly without stressing over the technical stuff. + +**Key Features:** + +- **Rules Engine**: Customizable JavaScript-based rules engine for tailored authentication flows and real-time user profile modifications, with pre-built templates. + +- **Lock Widget**: Customizable, mobile-friendly authentication interface that accelerates deployment and maintains consistent branding. + +- **Extensive SDKs**: Development kits for multiple languages with authentication flows, token handling, and debugging tools. + +- **Social Connections**: Easy integration with 30+ social identity providers, supporting OAuth and profile linking. + +- **Anomaly Detection**: Detects suspicious activity with brute force protection, IP blacklisting, and real-time security alerts. + +- **Breached Password Detection**: Monitors passwords against breaches and enforces custom security policies for compromised accounts. + + +### **Pricing:** + +- A free tier with basic features + +- Pay-as-you-go pricing based on active users + +- Enterprise plans available + + +### **Limitations:** + +- Costs can increase significantly with user growth + +- Limited control over infrastructure + +- Some features are restricted to higher tiers + + +## **7. Amazon Cognito** + +![aws cognito](./aws-cognito.png) + + +Amazon Cognito is a user-friendly authentication service that works well for organizations using AWS. It helps manage user identities and connects easily with other AWS services. Cognito is great for cloud-based applications, offering a mix of simplicity and advanced features. It provides user authentication for both web and mobile applications, making it a solid choice for teams that already know their way around AWS and want a straightforward login solution. + +**Key Features:** + +- **User Pools**: Comprehensive user directory with registration, authentication, and Lambda-based security customization. + +- **Identity Pools**: Secure management of temporary AWS credentials with fine-grained IAM roles for user access. + +- **AWS Integration**: Deep integration with AWS services, supporting Lambda customization and serverless workflows. + +- **Scalable Infrastructure**: Automatically scales for millions of users, ensuring high availability and easy backup. + +- **Security Features**: Adaptive authentication with account lockouts and event logging. + +- **Advanced Security**: Risk-based authentication that detects suspicious behavior with step-up authentication and real-time alerts. + + +### **Pricing:** + +- Free tier available (up to 50,000 MAUs) + +- Pay-as-you-go pricing model + +- Volume-based discounts + + +### **Limitations:** + +- Complex setup for non-standard use cases + +- Limited customization options + +- Primarily designed for the AWS ecosystem + + +## **Making the Right Choice** + +When selecting an Authelia alternative, consider these key factors: + +1. **Deployment Requirements**: Whether you need self-hosted or managed solutions + +2. **Scalability Needs**: Current and projected user base + +3. **Integration Requirements**: Compatibility with existing systems + +4. **Budget Constraints**: Total cost of ownership + +5. **Technical Expertise**: Available resources for implementation and maintenance + +The world of authentication is changing all the time, and each option has its own perks. Big companies usually lean towards all-in-one solutions like Okta or Auth0. On the other hand, organizations that want more control and flexibility often prefer options like SuperTokens or Keycloak. + +Ready to upgrade your authentication system? Explore [SuperTokens](https://supertokens.com/product) today for a secure, scalable, and developer-friendly alternative to Authelia. With its robust session management capabilities and flexible deployment options, SuperTokens offers a modern solution for today's authentication challenges. Sign up today! diff --git a/content/authelia-alternatives/keycloak.png b/content/authelia-alternatives/keycloak.png new file mode 100644 index 00000000..2cd7fc67 Binary files /dev/null and b/content/authelia-alternatives/keycloak.png differ diff --git a/content/authelia-alternatives/supertokens-homepage.png b/content/authelia-alternatives/supertokens-homepage.png new file mode 100644 index 00000000..124a787e Binary files /dev/null and b/content/authelia-alternatives/supertokens-homepage.png differ diff --git a/content/enterprise-sso/index.md b/content/enterprise-sso/index.md new file mode 100644 index 00000000..523f4ec3 --- /dev/null +++ b/content/enterprise-sso/index.md @@ -0,0 +1,125 @@ +--- +title: "Best Practices for Enterprise SSO" +date: "2024-09-28" +description: "This guide will dive into what enterprise SSO is and why it’s necessary for modern organizations. It will also provide actionable tips for implementing it effectively" +cover: "enterprise-sso.png" +category: "programming" +author: "Darko Bozhinovski" +--- + +## Table of Content + +- [Introduction](#introduction) +- [What is Enterprise SSO?](#what-is-enterprise-sso) +- [Why Enterprise SSO Matters in Large Organizations](#why-enterprise-sso-matters-in-large-organizations) +- [How Enterprise SSO Works](#how-enterprise-sso-works) +- [Key Features of Enterprise SSO](#key-features-of-enterprise-sso) +- [Common Challenges in Implementing Enterprise SSO (and How to Overcome Them)](#common-challenges-in-implementing-enterprise-sso-and-how-to-overcome-them) +- [Implementing Enterprise SSO with SuperTokens](#implementing-enterprise-sso-with-supertokens) + - [How SuperTokens Fits into Enterprise SSO:](#how-supertokens-fits-into-enterprise-sso) +- [Conclusion](#conclusion) + +## Introduction + +As organizations expand, so does the challenge of managing access across an increasing number of applications and platforms. This is where Single Sign-On (SSO) becomes essential, allowing employees to use one login for multiple systems without sacrificing security. For large enterprises, SSO is more than a convenience; it's a critical tool that minimizes password fatigue, boosts productivity, and reduces IT requests tied to access issues. + +This guide will dive into what enterprise SSO is and why it's necessary for modern organizations. It will also provide actionable tips for implementing it effectively. Focusing on enterprise security and user experience, we'll explore how SuperTokens offers a developer-friendly approach to simplify SSO in a safer and more scalable way. + +## What is Enterprise SSO? + +Enterprise SSO is a user authentication approach that lets employees access multiple applications and services with just one set of credentials. Unlike generic SSO solutions, enterprise SSO is tailor-made for the needs of large organizations with complex IT environments. By serving as a centralized authentication hub, it connects both cloud-based and on-premise applications, helping organizations streamline access control across departments and resources. + +Beyond just solving login headaches, enterprise SSO strengthens security, reduces the risk of password-related breaches, and enhances the overall user experience by unifying security standards across all systems. + +## Why Enterprise SSO Matters in Large Organizations + +Managing authentication and authorization processes can be a burden in organizations with countless employees and platforms. Here's how enterprise SSO handles the core challenges: + +- Simplified Access Control: Employees need access to various applications based on their roles. Without SSO, each application requires credentials, leading to password fatigue and more frequent forgotten passwords---a common source of IT support tickets. + +- Improved Security Consistency: Security policies vary from one application to another, creating gaps in protection. By consolidating authentication through SSO, organizations enforce consistent security standards across all platforms. + +- Enhanced Productivity: Constantly logging into different systems disrupts workflow. SSO allows end users to stay focused, accessing everything they need through one secure login. + +Enterprise SSO does more than streamline access---it also reduces security risks, improves user satisfaction, and saves employees time by eliminating repetitive logins. + +## How Enterprise SSO Works + +To understand SSO's mechanics, let's break down its two main components: the Identity Provider (IdP) and the Service Provider (SP). + +- **User Authentication** + + - Users log into the IdP, which verifies their identity using credentials stored in a central directory like Active Directory or LDAP. Often, this login includes multifactor authentication (MFA) for added security. + +- **Token Generation and Validation** + + - nce authenticated, the IdP issues a token that confirms the user's identity and permissions. This token is securely passed to other applications and validated by the SPs. + +- **Session Management** + + - SSO systems control session lengths and enforce timeouts. This means end users aren't prompted to log in repeatedly, and administrators maintain control over session activity. + +- **Trust Relationships** + + - SSO relies on a trust-based connection between the IdP and SPs, established through protocols like SAML, OAuth, or OpenID Connect. The IdP's tokens verify user identities with SPs without transferring sensitive credentials multiple times. + +## Key Features of Enterprise SSO + +Enterprise SSO is more than just convenient; it can reshape how organizations operate: + +- **Enhanced Security** + + - Centralizing authentication reduces password-related vulnerabilities, shrinking the attack surface and making it easier to enforce security protocols. SuperTokens enhances security further by offering built-in support for MFA, protecting against unauthorized access. + +- **Improved User Experience** + + - With enterprise SSO, users can seamlessly move across applications without needing to re-authenticate every time. This reduces login friction, enabling employees to focus on core tasks without the hassle of remembering passwords. + +- **Cost Efficiency for IT** + + - Password resets are one of the top reasons for IT calls. SSO slashes these requests, freeing up IT teams to focus on strategic tasks. Centralized access management also allows better software license control, reducing costs by efficiently managing user accounts. + +- **Enhanced Compliance and Audit Capabilities** + + - Enterprise SSO solutions often include logging and monitoring features to track user activity, making meeting compliance standards like GDPR, HIPAA, and SOC2 easier. + +## Common Challenges in Implementing Enterprise SSO (and How to Overcome Them) + +Implementing SSO in an enterprise environment has its complexities, but they're manageable. Here's how to tackle them: + +- **Integration Complexity** + + - Enterprises use diverse applications, which can complicate SSO integration. SuperTokens helps here by supporting multiple protocols, including SAML and OpenID Connect, ensuring compatibility with various systems. + +- **Single Point of Failure Risks** + + - If the IdP is compromised, it can affect all connected systems. To counter this, enterprises can implement MFA and strong security policies. SuperTokens, for instance, include built-in MFA to reduce unauthorized access risks significantly. + +- **Balancing Security with Ease of Use** + + - Striking a balance between security and usability is critical. Adaptable session settings and MFA allow organizations to deliver a smooth user experience without sacrificing security. SuperTokens supports customizable session management and MFA options, offering a tailored solution. + +- **Ensuring Compliance** + + - Organizations need SSO that meets data protection standards and supports audit logging. SuperTokens provides session tracking and detailed logs, making complying with standards like GDPR, SOC2, and HIPAA easier. + +## Implementing Enterprise SSO with SuperTokens + +SuperTokens is a flexible, developer-friendly option for enterprises considering SSO that integrates easily into existing systems while supporting enterprise-level security requirements. + +### How SuperTokens Fits into Enterprise SSO: + +- Protocol Compatibility +- SuperTokens supports SAML, OAuth, and OpenID Connect, making it compatible with various new and legacy applications. +- Built-in Multifactor Authentication +- SuperTokens includes MFA with SSO, adding a layer of security to keep unauthorized access at bay. +- Compliance-Ready Logging +- SuperTokens offers audit trails for access events, which is essential for regulatory compliance. This transparency helps organizations meet standards like GDPR, SOC2, and HIPAA. + +With SuperTokens, enterprises can streamline authentication management, boost security, and maintain regulatory compliance. For organizations looking for a reliable and adaptable SSO solution, [SuperTokens](https://supertokens.com/features/single-sign-on) provides the flexibility and protection needed for enterprise operations. + +## Conclusion + +Implementing enterprise SSO can transform access management, making it easier and safer to access essential resources. Though setup can be challenging, a flexible solution like SuperTokens can make all the difference. SuperTokens offers a secure, user-friendly SSO experience that reduces risk, enhances productivity, and scales for future growth. + +Ready to streamline access for your organization? [Sign up with SuperTokens](https://supertokens.com/product) today for an enterprise SSO solution that balances security with ease of use. \ No newline at end of file diff --git a/content/flask-user-authentication/index.md b/content/flask-user-authentication/index.md index 61f2c288..e40071f5 100644 --- a/content/flask-user-authentication/index.md +++ b/content/flask-user-authentication/index.md @@ -1,8 +1,8 @@ --- title: "Adding Authentication to Your Flask Backend with SuperTokens" description: "Learn how to seamlessly add authentication to your Flask backend using SuperTokens. This guide covers setting up authentication with the SuperTokens CLI or manual configuration, enabling you to focus on building application logic instead of authentication infrastructure." -date: "2024-11-29" -cover: "cover-image-for-my-blog-post.png" +date: "2024-11-04" +cover: "flask-user-authentication.png" category: "programming, featured" author: "Nemi Shah" --- diff --git a/content/how-to-secure-a-nestjs-app/index.md b/content/how-to-secure-a-nestjs-app/index.md new file mode 100644 index 00000000..c4e1003a --- /dev/null +++ b/content/how-to-secure-a-nestjs-app/index.md @@ -0,0 +1,1444 @@ +--- +title: How to secure a NestJs Application +date: "2024-09-25" +description: "In this post, we will be using NestJS, a Node.js framework that excels at making backend development efficient and scalable. Inspired by mature frameworks like Spring and ASP.NET, NestJS brings the best practices from these proven systems into the JavaScript/TypeScript world." +cover: "how-to-secure-a-nestjs-app.png" +category: "programming" +author: "Dejan Lukic" +--- + +## Introduction + +In this blog post, we'll explore how to secure a NestJS API using SuperTokens, an open-source user authentication solution. The purpose of this article is to give a comprehensive introduction to SuperTokens, explain how it is structured, and touch briefly on the fundamentals of authentication. Additionally, I will walk through the NestJS constructs used, making this post valuable not only to backend developers but also to those who are interested in learning more about authentication and API security. + +Implementing a secure authentication layer in an application is known to be one of the most challenging and time-consuming tasks, both on the backend and frontend. It’s not just about complexity; authentication requires constant testing, development iterations, and attention to security, which can take weeks or even months of a developer's valuable time. This is where SuperTokens comes in, providing a simple yet flexible solution that streamlines the process of adding secure authentication to your application. + +In this post, we will be using NestJS, a Node.js framework that excels at making backend development efficient and scalable. Inspired by mature frameworks like Spring and ASP.NET, NestJS brings the best practices from these proven systems into the JavaScript/TypeScript world. + +Let’s dive into the key concepts and technologies before moving into the implementation. + + +## Understanding Authentication + +Authentication is the cornerstone of securing modern applications. It ensures that only legitimate users or systems can access protected resources. Whether you're building a web application, mobile app, or API, implementing a robust authentication mechanism is crucial for ensuring data integrity and security. + +There are several widely used authentication methods, each with its own strengths, weaknesses, and appropriate use cases. Let’s take a closer look at the most common types of authentication. + + + +1. **Password-based Authentication**: Password-based authentication is one of the oldest and most widely used authentication mechanisms. Users provide a username and password to prove their identity. + * Pros: + * **Familiar and simple**: Users are accustomed to using passwords; + * Easy to implement with minimal setup. + * Cons: + * **Security risks**: Passwords are vulnerable to attacks such as brute force, phishing, and credential stuffing. + * **Poor user experience**: Users often forget passwords or create weak ones, leading to the need for password reset flows, which can be frustrating. + * **Password management burden**: Users must manage and remember multiple passwords, often leading to reuse across services. +2. **Token-based Authentication (JWT)**: Token-based authentication relies on issuing a token, such as a JSON Web Token (JWT), after a user successfully logs in. The token is then sent with each subsequent request to authenticate the user. + * Pros: + * **Stateless**: Token-based authentication doesn’t require server-side session storage, making it highly scalable in distributed systems. + * **Versatile**: Tokens can carry additional information (claims) about the user or session, which can be used by the backend for authorization decisions. + * Cons: + * **Token expiration:**: Access tokens have limited lifetimes and require refresh tokens to maintain sessions, adding complexity. + * **Security concerns**: Storing tokens insecurely on the client side (e.g., in localStorage) can make them susceptible to theft or misuse. + * **Token revocation**: Unlike session-based authentication, invalidating tokens across distributed services [can be challenging](https://supertokens.com/blog/revoking-access-with-a-jwt-blacklist), requiring additional infrastructure. +3. **OAuth and Social Authentication**: OAuth is a widely used standard for authorizing third-party applications to access user data without exposing the user’s credentials. Social authentication leverages OAuth to let users sign in using their existing accounts on services like Google, Facebook, or GitHub. + * Pros: + * **Easy for users**: Users can sign in with a single click without needing to remember another password; + * **Quick onboarding**: Reduces friction during sign-up and login, as users are already familiar with their social accounts; + * Cons: + * **Reliance on third-party services**: If the third-party provider is down or blocked in certain regions, users won’t be able to authenticate; + * **Data sharing concerns**: Some users may not want to link their social media accounts with your service or share personal data from those accounts; + * **Privacy regulation**: Social logins often come with considerations around privacy and data sharing, which may introduce compliance complexities; +4. **Passwordless Authentication**: Passwordless authentication allows users to log in without a password, typically using a magic link sent via email or a One-Time Password (OTP) sent via SMS or email. The user clicks the link or enters the code to authenticate. + * Pros: + * **No passwords to manage**: It eliminates the risks and frustration associated with password management; + * **Enhanced security**: Without passwords, there’s no risk of password theft, reuse, or brute force attacks; + * Cons: + * **Email/SMS delivery issues**: If email services or phone networks are unreliable, users may not receive the magic link or OTP. For example, in rural areas or places with poor phone signal, SMS OTPs can be delayed or fail to arrive, causing frustration; + * **Dependence on third-party services**: Passwordless authentication depends on reliable email or SMS services, which might introduce challenges in specific regions; + * **Less familiar**: Some users may not be accustomed to passwordless login methods and may prefer the simplicity of password-based login; + + +## Choosing the Right Authentication Method + +The choice of authentication method depends on several factors: + + + +1. **User Experience**: Simple methods like social login or passwordless authentication reduce friction but might not be suitable for high-security applications. +2. **Security**: For sensitive applications, methods like MFA or hardware tokens are recommended. Password-based authentication is typically the least secure option due to its vulnerability to attacks. +3. **Scalability**: Token-based authentication is scalable, especially in microservices and stateless applications, whereas session-based authentication may introduce scalability challenges; +4. **Privacy and Compliance**: When using third-party services (e.g., social login or OAuth), be mindful of data-sharing concerns and compliance with regulations like *GDPR*. + +By carefully weighing these factors, you can choose an authentication method that provides the right balance of security, convenience, and scalability for your application. + +![too many variables](./too-many-variables.gif) + +## What is SuperTokens? + +SuperTokens is an open-source, developer-friendly authentication solution designed to simplify the implementation of secure, scalable user authentication systems. It provides a plug-and-play model for common authentication flows like sign-up, sign-in, passwordless login, social logins, and session management—while also being customizable for more advanced use cases. + +SuperTokens is built to handle the complexities of user authentication in modern applications, such as token management, session handling, and security best practices, so that developers can focus on building core functionality without worrying about intricate security details. + + +## SuperTokens' Architecture & SDKs + +Let’s quickly explain how SuperTokens works behind the scenes and how its architecture is structured. + +SuperTokens can be run both as a: + + + +* **Self-hosted instance** +* **Managed service** + +These flows are quite similar in terms of functionality, with some key differences in where the components are hosted. + +### Managed Service Architecture Diagram + +![managed-service-architecture](./managed-service-architecture.png) + +### Self-hosted Architecture Diagram + + +![self hosted authentication](./self-hosted-architechture.png) + + +The primary difference between these two flows is that in the self-hosted flow, you use your own database, while in the managed service, SuperTokens automatically manages the database for you. Since the concepts are almost identical, we’ll discuss the general architecture below without focusing on whether the flow is self-hosted or managed + +**Architecture Breakdown** + + +1. **Your Website/App**: This is the frontend of your application. While it doesn't need to be autogenerated or managed by the SuperTokens SDK, it should adhere to the Frontend Driver Interface (FDI), which I’ll explain shortly. SuperTokens offers frontend SDKs in various frameworks (React, Vue, Vanilla JS, React Native, Flutter, etc.) to handle common authentication-related challenges, such as securely storing and sending access tokens, handling refresh tokens, and more. This significantly enhances developer experience by abstracting away the complexities of token management. + + One important note: The frontend should never communicate directly with SuperTokens Core. Instead, the communication should happen via your backend API, which acts as the intermediary. + +2. **Your Backend API**: This is the backend part of your application. Similar to the frontend, this part doesn’t need to be autogenerated or fully managed by the SuperTokens SDK, as long as it adheres to the Core Driver Interface (CDI), which I’ll explain below. SuperTokens provides backend SDKs for various languages and frameworks, and these SDKs handle important authentication logic, such as session management, token expiration, and more. By using the backend SDK, additional /auth routes are provided out-of-the-box, reducing the manual effort required for implementing secure authentication. + + The backend is the only part of your system that communicates directly with SuperTokens Core. It serves as the bridge between the frontend and the core authentication service. + +3. **SuperTokens Core**: This is the central component of the SuperTokens architecture. It’s an HTTP service that encapsulates all the core authentication logic. SuperTokens Core handles tasks like creating and verifying tokens, session management, user state management, and more. It also interfaces with the database (either your self-hosted database or the managed service) to store and retrieve authentication-related data. + + SuperTokens Core is designed to be lightweight and highly performant, allowing it to scale easily across different environments. Your backend SDK interacts with the core to perform operations that require database access. + +4. **Your database** (Self-hosted only): In the self-hosted flow, this is the database where all authentication-related data is stored. It includes user sessions, tokens, and other necessary information. You are responsible for managing this database. SuperTokens supports various database engines such as PostgreSQL and MySQL for self-hosted deployments. + + In the managed service flow, SuperTokens manages this database for you, which simplifies operations and removes the need for database management on your end. + + +*Even though it’s technically possible to skip using the frontend and backend SDKs and work directly with SuperTokens Core, this approach is not recommended. Doing so significantly increases the complexity of the project and undermines the main purpose of SuperTokens, which is to simplify secure authentication.* + + +--- + + +## Key Note on SuperTokens APIs + +When working with SuperTokens APIs, it’s crucial to follow the correct interface patterns: + + + +* **Frontend-to-Backend Communication**: The communication between your frontend and backend should use the Frontend Driver Interface (FDI). This interface defines the API calls your frontend can make to the backend to handle authentication-related actions (like login, session validation, etc.). The FDI ensures that the frontend is abstracted from the backend’s internal logic. You can view the full [FDI API specification here](https://app.swaggerhub.com/apis/supertokens/FDI). The APIs are categorized by recipe, depending on the specific authentication method you are implementing. +* **Backend-to-Core Communication**: The communication between your backend and SuperTokens Core is defined by the Core Driver Interface (CDI). This API governs how your backend interacts with SuperTokens Core to perform operations like creating and verifying tokens, managing sessions, and querying the database for authentication data. You can view the full [CDI API specification here]((https://app.swaggerhub.com/apis/supertokens/CDI)). + + +### Frontend Driver Interface (FDI) and Core Driver Interface (CDI) + +* **Frontend Driver Interface (FDI)**: This interface is designed to allow the frontend to communicate with the backend for all authentication-related operations (such as login, signup, session management, etc.). It is the layer that abstracts how authentication is handled in the backend. This way, the frontend does not need to worry about the complexities of session management or token handling. +* **Core Driver Interface (CDI)**: This is the interface that defines how the backend SDK communicates with SuperTokens Core. The backend SDK uses this interface to send authentication requests, manage tokens, handle user sessions, and retrieve or store data in the database. The CDI ensures that the backend and core are decoupled, which allows you to replace or extend components without affecting the core functionality. + + +--- + +By adhering to these interfaces, you can ensure that your application architecture remains modular, scalable, and easy to maintain. + + +### What is NestJS? + +NestJS is a progressive Node.js framework built for developing efficient, scalable, and maintainable server-side applications. It embraces TypeScript by default but also supports JavaScript, offering developers the best of both worlds. Inspired by enterprise frameworks like Spring (Java) and ASP.NET (C#), NestJS incorporates design principles like modular architecture, dependency injection, and middleware support. + +Key NestJS features: + + + +* **Modularity**: Organizes the application into feature modules, making it easier to maintain. +* **Dependency Injection (DI)**: Built-in DI simplifies managing class dependencies and makes testing more efficient. +* **Built-in Middleware and Guards**: Supports adding custom middleware (like authentication checks) and Guards to protect routes. +* **Extensibility**: Works well with many other libraries (ORMs, WebSockets, etc.), and integrates with Express or Fastify under the hood. + +Now, let's see how we can combine these two powerful tools to build a secure and scalable API. + + +## Integrating SuperTokens with NestJS + +Before I continue, I must mention the fantastic [integration guide](https://supertokens.com/docs/passwordless/nestjs/guide) written by the SuperTokens team. It’s a great read and hard to beat in terms of clarity and completeness. My goal here is to provide a bit more in-depth explanation and additional context. + +Depending on the state of your current project—whether you already have everything except the authentication layer or you're just getting started—there are two approaches you can take. You can either: + + +* Follow this guide and add the necessary parts to your existing project, or +* Generate a scaffolded version of both the frontend and backend using the SuperTokens setup command. + +Which path you take depends on your knowledge of NestJS and SuperTokens. If you just want to quickly get started, run the following command: + +```bash +$ npx create-supertokens-app@latest +``` + +By running this command, you will be prompted to select your frontend and backend frameworks, as well as the authentication methods you want to support. The setup process is intuitive, and once completed, you’ll have two generated projects. + + +Since this guide is focused on integrating SuperTokens with the backend (specifically NestJS), I won’t be covering the frontend part in much detail. + +You can easily continue building on top of this autogenerated project without worrying about the authentication layer, as everything is already set up for you. + + +--- + +**Note:** + +In the autogenerated project, the managed service flow is selected by default. If you need a self-hosted solution, you’ll need to modify the connection URI in the `config.ts` file: + +```ts +export const connectionUri = 'https://try.supertokens.com'; +``` + +Change it to this for local development using Docker (this will be explained in the next section) or the connection URI specific to your environment: + +export const connectionUri = 'http://localhost:3567'; + +One great thing about this setup is that all configuration tweaks are centralized in the `config.ts` file. You can adjust it to fit your needs and project specifications. + + +--- + +Let’s now go step by step. Before proceeding, you'll need to decide whether you want to use the managed service or self-hosted flow. In this guide, I’ll focus on the self-hosted flow because it involves more moving parts, which allows me to explain the entire setup in greater detail. + + +### Docker Setup + +At the start of any project, I prefer to identify the different services and databases I need and organize them in a `docker-compose.yml` file. For this guide, I’m following another great [SuperTokens guide](https://supertokens.com/docs/passwordless/pre-built-ui/setup/core/with-docker), which outlines the setup. + +I chose to use PostgreSQL as the database for this example, but the choice of database doesn’t significantly impact the setup (except for the database tool used to inspect it). Here's my `docker-compose.yml` file, which is very similar to the one in the guide: + +```docker +services: + + db: + + image: "postgres:latest" + + environment: + + POSTGRES_USER: user + + POSTGRES_PASSWORD: password + + POSTGRES_DB: supertokens + + ports: + + - 5432:5432 + + networks: + + - app_network + + restart: unless-stopped + + healthcheck: + + test: ["CMD", "pg_isready", "-U", "user", "-d", "supertokens"] + + interval: 5s + + timeout: 5s + + retries: 5 + + supertokens: + + image: registry.supertokens.io/supertokens/supertokens-postgresql:9.2.3 + + depends_on: + + db: + + condition: service_healthy + + ports: + + - 3567:3567 + + environment: + + POSTGRESQL_CONNECTION_URI: "postgresql://user:password@db:5432/supertokens" + + networks: + + - app_network + + restart: unless-stopped + + healthcheck: + + test: > + + bash -c 'exec 3<>/dev/tcp/127.0.0.1/3567 && echo -e "GET /hello HTTP/1.1\r\nhost: 127.0.0.1:3567\r\nConnection: close\r\n\r\n" >&3 && cat <&3 | grep "Hello"' + + interval: 10s + + timeout: 5s + + retries: 5 + +networks: + + app_network: + + driver: bridge + +``` + +**Important note from docs**: If you are running the backend process that integrates with our backend SDK as part of the docker compose file as well, make sure to use [http://supertokens:3567](http://supertokens:3567) as the connection uri instead of [http://localhost:3567](http://localhost:3567) + +This docker-compose.yml file defines two services: *db* (PostgreSQL) and *supertokens* (SuperTokens core). They are connected to a shared network and have health checks to ensure both services are functioning properly. + +To start the services, run this command: + +```bash +$ docker compose up -d --force-recreate +``` + +After the services start, test if SuperTokens is working correctly by sending a request to the `/hello` endpoint: + +```bash +$ curl http://localhost:3567/hello +``` + +If everything is working, you should see a response with "Hello". + +Next, list the running containers using: + +```bash +$ docker ps +``` + +To inspect the database, connect to the PostgreSQL container (**db**) using its name or container ID: + +```bash +$ docker exec -it <container_name_or_id> bash +``` + +Once inside the container, connect to the PostgreSQL database: + +```bash +$ psql -U user supertokens +``` + +This command is going to run `psql` interface which serves as an interface to connect to your PostgreSQL database. + +To list all databases in the container: + +```bash +$ \list +``` + +To connect to the `supertokens` database: + +```bash +$ \c supertokens +``` + +To list all tables within the `supertokens` database: + +```bash +$ \dt +``` + +One thing worth mentioning is the User Management Dashboard provided by SuperTokens. This dashboard allows you to easily manage users, sessions, and user-related operations such as viewing user details, revoking sessions, and even deleting users from the system. It's a handy tool for administrators to perform user management tasks without needing to build custom interfaces. + +Since that goes beyond the scope of this article, I recommend checking out another fantastic [guide](https://supertokens.com/docs/userdashboard/about) from the SuperTokens team to explore its full capabilities. + +### NestJS Integration + +While the setup above provides a working example out of the box, let’s take a step back and imagine adding these NestJS constructs to an existing project. Copying from the autogenerated project into your custom one would work, but understanding how everything fits together is key. + + +#### Step 0: Install SuperTokens + +First, install the `supertokens-node` package using your preferred package manager: + +```bash +$ npm install supertokens-node +``` + +#### Step 1: Add an Authentication Module + +We need to create a new **static** module dedicated to handling authentication. It’s a good practice to name it `auth`. You can manually add a new module, or use the NestJS CLI for convenience: + +```bash +$ nest g module auth +``` + +As a quick reminder, in NestJS, modules organize your application into logical units, grouping related components such as controllers and services. The root module (AppModule) serves as the entry point, while feature modules like AuthModule help break down functionality into manageable parts. Modules make your application modular, scalable, and easy to maintain. + +After running the command, the `auth` folder should be generated with `auth.module.ts`, and this module will be automatically registered in the root module of your application. + +*auth.module.ts* +```ts +import { Module } from '@nestjs/common'; + +@Module({ + + providers: [], + + exports: [], + + controllers: [], + +}) + +export class AuthModule {} + +*app.module.ts* + +import { Module } from '@nestjs/common'; + +@Module({ + + imports: [AuthModule], + + controllers: [], + + providers: [], + +}) + +export class AppModule {} +``` + + +#### Step 2: Connect with the Init Method from the Core Library + +Because `supertokens-node` is a generic library designed to support multiple Node.js frameworks, we need to consider how to initialize SuperTokens Core within a NestJS project. **supertokens-node** provides an `init` method for this purpose, but the question arises: where exactly should we call it in a NestJS context? + +In NestJS, the ideal place to handle this is through **Providers**. Providers are a key concept in NestJS, allowing various classes—such as services, repositories, factories, or helpers—to be injected as dependencies. This means that the initialization of SuperTokens can be done via a provider, keeping the setup modular and flexible. + +Now that we've settled on using providers for this task, the next challenge is managing the configuration. The init method requires a configuration object. Initially, it might seem straightforward to solve this using environment variables. But what if you’re working in a microservice architecture where each service has different configurations? Handling multiple environment variables can quickly become overwhelming and lead to what’s commonly referred to as "config hell." + +A better approach is to allow the AuthModule to be configurable by the host module. This way, each host module can pass the necessary configuration dynamically, depending on the environment or service. This is where dynamic modules in NestJS become invaluable—they allow us to pass configuration parameters during module initialization, providing flexibility and ensuring that the setup remains clean and adaptable. + + + In NestJS, dynamic modules allow runtime configuration. These are typically set up using methods like forRoot() for global configuration or forRootAsync() for asynchronous configuration. This approach enables different parts of the app to pass different configurations to the module. + +```ts +@Module({}) + +export class ConfigModule { + + static forRoot(options: ConfigOptions): DynamicModule { + + return { + + module: ConfigModule, + + providers: [ + + { provide: 'CONFIG_OPTIONS', useValue: options }, + + ], + + }; + + } + +} +``` + +While the idea of using **dynamic modules** solves some of our challenges, another issue comes up. We've already decided to use providers to handle the SDK initialization, but now the question is: how do we pass the configuration from the dynamic module to the provider? + +In NestJS, everything is handled through Inversion of Control (IoC) and Dependency Injection (DI), meaning that the framework manages the creation and lifecycle of all constructs, including providers. So, to pass the configuration from the dynamic module to the provider, we need to leverage DI. + +This is where custom providers come into play. Custom providers give us control over how dependencies are injected. By using useClass, useValue, or useFactory, we can define how configuration objects (or other data) are injected into providers. This approach ensures that the configuration passed to the dynamic module can be cleanly injected into the provider, allowing the SDK to be initialized with the correct settings. + + + In NestJS, custom providers give you control over dependency injection. You can use useClass to provide an alternate class, useValue to supply a static value, useFactory to create a provider dynamically, or useExisting to reuse an existing provider. + + + When working with custom providers, you can also define injection tokens, which allow you to reference values or classes by a token rather than directly by the class. This is particularly useful for injecting non-class values, like configuration objects. +```ts +const CONFIG_TOKEN = 'CONFIG_TOKEN'; + +@Module({ + +providers: [ + + { provide: CONFIG_TOKEN, useValue: { apiKey: '12345' } } + + ], + +}) + +export class ConfigModule {} + +@Injectable() + +export class ConfigService { + + constructor(@Inject(CONFIG_TOKEN) config: DynamicConfig) + +} +``` + +Here, CONFIG_TOKEN acts as an injection token, and the value associated with it can be injected into any class that needs it. This approach is flexible and allows decoupling dependencies from their implementations. + +Now, let’s implement the necessary configuration for SuperTokens in a new file config.interface.ts in the auth module. This will define the types and *injection tokens*. + +```ts +import { AppInfo } from 'supertokens-node/types'; + +export const ConfigInjectionToken = 'ConfigInjectionToken'; + +export type AuthModuleConfig = { + + appInfo: AppInfo; + + connectionURI: string; + + apiKey?: string; + +} +``` + +`AppInfo` is a required object that helps SuperTokens configure essential details such as your app’s name and domain settings. Here’s what the AppInfo structure looks like: + +```ts +import { AppInfo } from 'supertokens-node/types'; + +type AppInfo = { + + appName: string, + + websiteDomain: string, + + apiDomain: string, + + websiteBasePath?: string, // optional + + apiBasePath?: string, // optional + + apiGatewayPath?: string // optional + +} +``` +Let’s break down the `AuthModuleConfig` object: + + + +* **connectionURI**: address of your core instance. Possible options would be: + * in autogenerated project, this value defaults to **[https://try.supertokens.com](https://try.supertokens.com)**, + * in local self-hosted instance (like in this example), this has to be address of **supertokens** service, **[http://localhost:3567](http://localhost:3567)** + * in managed service flow, sign up on **supertokens.com** +* **apiKey**(optional): if using managed service flow, this is api key for your account +* **appInfo**: this object is to be specified on the frontend as well as on the backend. This is a complex object consisted from these values: + * **appName** (mandatory): this is the name of your application. It is used when sending password reset or email verification emails (in the default email design) + * **websiteDomain** (mandatory): this is a required configuration that defines the domain where your login UI is hosted. For local development, this might be something like [http://localhost:8080](http://localhost:8080), while for production, it would reflect your actual domain, such as [https://www.example.com](https://www.example.com). If you use a subdomain for login (e.g., [https://auth.example.com](https://auth.example.com)), that should be specified as the websiteDomain. The login UI by default appears at {websiteDomain}/auth/*, but this can be customized. This domain is needed both on the frontend for routing and on the backend for generating correct email verification and password reset links. + * **apiDomain** (mandatory): this is a required configuration that specifies the domain of your API endpoint that the frontend communicates with. For local development, this could be something like [http://localhost:9000](http://localhost:9000), while in production, it might be [https://api.example.com](https://api.example.com). If your API is accessed via /api/_ under the same domain as the frontend, the apiDomain would match your websiteDomain. By default, the login widgets will query {apiDomain}/auth/_, though this path can be customized using the apiBasePath configuration. + * **websiteBasePath** (optional): this is an optional configuration that allows you to change the default URL path where the login UI and other authentication-related UIs are displayed. By default, the UI is shown at {websiteDomain}/auth. If you want to use a different path, such as {websiteDomain}/user/*, you would set this value to "/user". If you're using a dedicated subdomain for authentication (e.g., [https://auth.example.com](https://auth.example.com)), set this value to "/" so the UI appears at the root of the subdomain. Remember to set the same value for this param on the backend and the frontend. + * **apiBasePath** (optional): this is an optional configuration that allows you to customize the default /auth path where the frontend SDK queries your API. For example, if you want to version your API, you can set it to /v0/auth, or if you prefer to scope the APIs under a different path like /supertokens, you can configure it accordingly. If you don't want any scoping, set it to /, which will expose the APIs at {apiDomain}/*. Be sure to set the same value on both the backend and frontend to ensure consistency. Be cautious when changing the apiBasePath, as it will also update the refresh token API path, potentially causing previously issued refresh tokens to fail, which could log users out. + +Let's create a new `config.ts` file in the root of the project. This file will serve as the unified place where all configurations for this project reside. + +First, let's fill in the `appInfo` object and `connectionURI`: + +```ts +export const appInfo = { + + appName: 'Demo app for NestJS', + + apiDomain: 'http://localhost:3001', + + websiteDomain: 'http://localhost:3000', + + apiBasePath: '/auth', + + websiteBasePath: '/auth', + +}; +``` + +Next, we'll modify the AuthModule to be **dynamic**. A dynamic module allows us to pass in configurations when initializing the module, making it flexible for different environments. + +Here’s how the updated `auth.module.ts` will look: + +```ts +import { + + Module, + + DynamicModule, + +} from '@nestjs/common'; + +import { ConfigInjectionToken, AuthModuleConfig } from './config.interface'; + +@Module({ + + providers: [], + + exports: [], + + controllers: [], + +}) + +export class AuthModule { + + static forRoot({ + + connectionURI, + + apiKey, + + appInfo, + + }: AuthModuleConfig): DynamicModule { + + return { + + providers: [ + + { + + useValue: { + + appInfo, + + connectionURI, + + apiKey, + + }, + + provide: ConfigInjectionToken, + + }, + + ], + + exports: [], + + imports: [], + + module: AuthModule, + + }; + + } + +} +``` + +Here, we're using the **forRoot** method to accept a configuration object, which allows us to pass in the necessary settings. We're also registering a custom provider to supply the configuration throughout the module. When returning a **DynamicModule** object, the only required property is the **module** itself, which should match the class name of the module. All other properties like providers, exports, and imports are optional. + +In this case, the **appInfo** and **connectionURI** are already populated, and we're omitting the **apiKey** for this demo. With these configurations in place, our dynamic module is fully prepared. Now, all that's left is to connect it to the root (host) module, allowing it to function across the app. + +Next, connect this module to the root (host) module, AppModule: + +```ts +import { Module } from '@nestjs/common'; + +import { AppController } from './app.controller'; + +import { AppService } from './app.service'; + +import { AuthModule } from './auth/auth.module'; + +import * as SuperTokensConfig from './config'; + +@Module({ + + imports: [ + + AuthModule.forRoot({ + + connectionURI: SuperTokensConfig.connectionUri, + + appInfo: SuperTokensConfig.appInfo, + + }), + + ], + + controllers: [AppController], + + providers: [AppService], + +}) + +export class AppModule {} +``` + +Since the init method in its configuration object expects a **recipeList**, the next step is to decide which authentication methods (or recipes) we want to support. The choice of recipes depends on the specific requirements of your business logic. + +For this article, we'll support the following recipes: + + + +* **Email** + **Password** authentication +* **Passwordless** login (via email and phone) +* **Social Logins** (Google, GitHub, Apple, Twitter) + +In addition to these, we’ll enable the User Management Dashboard for easy user handling, and implement session management, token handling, and user roles. + +Now, let’s add all this configuration to our `config.ts` file: + +```ts +export const recipeList = [ + + EmailPassword.init(), + + Passwordless.init({ + + contactMethod: 'EMAIL_OR_PHONE', + + flowType: 'USER_INPUT_CODE_AND_MAGIC_LINK', + + }), + + ThirdParty.init({ + + signInAndUpFeature: { + + providers: [ + + { + + config: { + + thirdPartyId: 'google', + + clients: [ + + { + + clientId: '<YOUR_GOOGLE_CLIENT_ID>', + + clientSecret: '<YOUR_GOOGLE_CLIENT_SECRET>', + + }, + + ], + + }, + + }, + + { + + config: { + + thirdPartyId: 'github', + + clients: [ + + { + + clientId: '<YOUR_GITHUB_CLIENT_ID>', + + clientSecret: '<YOUR_GITHUB_CLIENT_SECRET>', + + }, + + ], + + }, + + }, + + { + + config: { + + thirdPartyId: 'apple', + + clients: [ + + { + + clientId: '<YOUR_APPLE_CLIENT_ID>', + + additionalConfig: {...}, + + }, + + ], + + }, + + }, + + { + + config: { + + thirdPartyId: 'twitter', + + clients: [ + + { + + clientId: '<YOUR_TWITTER_CLIENT_ID>', + + clientSecret: '<YOUR_TWITTER_CLIENT_SECRET>', + + }, + + ], + + }, + + }, + + ], + + }, + + }), + + Session.init(), + + Dashboard.init(), + + UserRoles.init(), + +]; +``` + +The recipeList configuration is fairly straightforward, as it defines which authentication methods and features you're enabling in your app. For more specific configurations regarding social login providers, you can refer to this [guide](https://supertokens.com/docs/thirdpartypasswordless/common-customizations/sign-in-and-up/provider-config), which offers detailed instructions for each provider. + +Now that we have the full configuration set up, the next step is to create the provider responsible for calling the init method from the SuperTokens SDK. + +We can use the NestJS CLI to generate this service. Run the following command from the root of your project: + +$ nest g service supertokens auth + +This command will create a `supertokens` folder within the auth module. We’ve placed it in a separate folder to keep things organized, as this service will specifically manage interactions with the SuperTokens library. Inside this folder, you’ll find a file named `supertokens.service.ts`. + +Now, let's add the following code to the `supertokens.service.ts` file: +```ts +import { Inject, Injectable } from '@nestjs/common'; + +import supertokens from 'supertokens-node'; + +import { ConfigInjectionToken, AuthModuleConfig } from '../config.interface'; + +import * as SuperTokensConfig from '../../config'; + +@Injectable() + +export class SupertokensService { + + constructor(@Inject(ConfigInjectionToken) private config: AuthModuleConfig) { + + supertokens.init({ + + appInfo: config.appInfo, + + supertokens: { + + connectionURI: config.connectionURI, + + apiKey: config.apiKey, + + }, + + recipeList: SuperTokensConfig.recipeList, + + }); + + } + +} +``` + +If the NestJS CLI didn't automatically register this service in the dynamic AuthModule, ensure that it is manually added to the providers array in the module definition: + +```ts +import { + + Module, + + DynamicModule, + +} from '@nestjs/common'; + +import { ConfigInjectionToken, AuthModuleConfig } from './config.interface'; + +import { SupertokensService } from './supertokens/supertokens.service'; + +@Module({ + + providers: [SupertokensService], + + exports: [], + + controllers: [], + +}) + +export class AuthModule { + + static forRoot({ + + connectionURI, + + apiKey, + + appInfo, + + }: AuthModuleConfig): DynamicModule { + + return { + + providers: [ + + { + + useValue: { + + appInfo, + + connectionURI, + + apiKey, + + }, + + provide: ConfigInjectionToken, + + }, + + SupertokensService, + + ], + + exports: [], + + imports: [], + + module: AuthModule, + + }; + + } + +} +``` + +#### Step 3: Connect with the Middleware from the SDK + +To handle session management, token validation, and authentication flows, we need custom middleware that intercepts HTTP requests and examines authentication data before the request reaches the route handler. Middleware is perfect for this because it operates early in the request lifecycle, making it ideal for processing session validation and managing tokens. + +Middleware allows us to efficiently validate tokens and handle authentication across all incoming requests, ensuring the flow is secure and streamlined. It has access to low-level request and response objects, which is necessary for setting cookies, reading headers, and managing tokens. Interceptors, although useful, are better suited for tasks like post-processing rather than managing session lifecycles. + +To create middleware in NestJS, use the following command: + +$ nest g middleware auth + +This will generate an `auth.middleware.ts` file in the auth module. Add the following code to incorporate SuperTokens: + +```ts +import { Injectable, NestMiddleware } from '@nestjs/common'; + +import { middleware } from 'supertokens-node/framework/express'; + +@Injectable() + +export class AuthMiddleware implements NestMiddleware { + + supertokensMiddleware: any; + + constructor() { + + this.supertokensMiddleware = middleware(); + + } + + use(req: Request, res: any, next: () => void) { + + return this.supertokensMiddleware(req, res, next); + + } + +} + +The middleware from the express framework within SuperTokens is now integrated, but we still need to apply it globally. Let’s modify the `auth.module.ts` file to register this middleware: + +import { + + MiddlewareConsumer, + + Module, + + NestModule, + + DynamicModule, + +} from '@nestjs/common'; + +import { AuthMiddleware } from './auth.middleware'; + +import { ConfigInjectionToken, AuthModuleConfig } from './config.interface'; + +import { SupertokensService } from './supertokens/supertokens.service'; + +@Module({ + + providers: [SupertokensService], + + exports: [], + + controllers: [], + +}) + +export class AuthModule implements NestModule { + + configure(consumer: MiddlewareConsumer) { + + consumer.apply(AuthMiddleware).forRoutes('*'); + + } + + static forRoot({ + + connectionURI, + + apiKey, + + appInfo, + + }: AuthModuleConfig): DynamicModule { + + return {...} + + } + +} +``` + +In NestJS, this is how we configure middleware. By implementing the **NestModule** interface from **@nestjs/common**, we can define a **configure** method that applies middleware to specific routes. In the line `consumer.apply(AuthMiddleware).forRoutes('*')`, we ensure that the AuthMiddleware is applied globally across all routes in the application. This middleware intercepts every incoming request to manage session validation, token verification, and other authentication tasks before the request reaches the route handler. Since we've already covered why middleware is the ideal choice for handling such tasks, this configuration simply ensures that the middleware is active for all incoming HTTP traffic. + + +#### Step 4: Update CORS Settings (Optional) + +If your frontend is running on a different domain or port from your backend, you'll likely encounter issues with cross-origin requests being blocked by the browser. + +CORS (Cross-Origin Resource Sharing) is a security feature in browsers that restricts web pages from making requests to a different domain than the one that served the page. It's designed to prevent unauthorized access to resources on different domains. + +To fix this, you need to enable and configure CORS in your NestJS application. Modify `main.ts` as follows: + +```ts +import { NestFactory } from '@nestjs/core'; + +import { AppModule } from './app.module'; + +import supertokens from 'supertokens-node'; + +import * as SuperTokensConfig from './config'; + +async function bootstrap() { + + const app = await NestFactory.create(AppModule); + + app.enableCors({ + + origin: [SuperTokensConfig.appInfo.websiteDomain], + + allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()], + + credentials: true, + + }); + + await app.listen(3001); + +} + +bootstrap(); +``` + +Make sure to restart your server after these changes to ensure they are applied. + + +#### Step 5: Add SuperTokens Error Handling + +We’ve successfully integrated all the components, and the logic for communicating with the SuperTokens core is in place, but something crucial is still missing: error handling. For instance, what happens when an access token expires, or a session becomes invalid? Who manages these scenarios, and how are error responses formatted? Currently, we don’t have a unified way of handling such issues—but that’s where exception filters come in. + +In NestJS, an exception filter is a powerful feature that captures exceptions thrown during the request lifecycle. It intercepts errors and allows us to return customized, consistent HTTP responses rather than letting those errors propagate and potentially crash the application. By using exception filters, we can centralize error handling, making our application more robust and ensuring that user-facing error messages are clear and controlled. Exception filters can be applied globally or scoped to specific parts of the application, giving us flexible control over error management. + +Run the following command to generate an exception filter: + +```bash +$ nest g filter auth +``` + +This will create an `auth.filter.ts` file in the auth module. Add the following code: + +```ts +import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common'; + +import { Request, Response, NextFunction, ErrorRequestHandler } from 'express'; + +import { errorHandler } from 'supertokens-node/framework/express'; + +import { Error as STError } from 'supertokens-node'; + +@Catch(STError) + +export class SupertokensExceptionFilter implements ExceptionFilter { + + handler: ErrorRequestHandler; + + constructor() { + + this.handler = errorHandler(); + + } + + catch(exception: Error, host: ArgumentsHost) { + + const ctx = host.switchToHttp(); + + const resp = ctx.getResponse<Response>(); + + this.handler( + + exception, + + ctx.getRequest<Request>(), + + resp, + + ctx.getNext<NextFunction>(), + + ); + + } + +} +``` + +Let’s break down what’s happening here. This code defines a custom exception filter in NestJS to handle SuperTokens-specific errors. The `@Catch` decorator is used to capture exceptions of the type `STError`, which come from the SuperTokens SDK. The SupertokensExceptionFilter class utilizes the `errorHandler()` function from SuperTokens to manage these errors. The two key elements here are the `STError` (a custom error type from the SDK) and the `errorHandler()`, both of which allow us to process SuperTokens-related errors effectively. + +Inside the `catch()` method, the filter switches the context to HTTP using `ArgumentsHost`, which gives access to the request and response objects. It retrieves the request, response, and the next middleware function in the chain. The SuperTokens `errorHandler` is then invoked to process the caught exception and respond with an appropriate message. + +Now, you might wonder why nothing changes if you run your app with an expired token. This could make you think the exception filter isn't needed—but that's not the case. You need to ensure the filter is applied to the correct part of your application. For example, you can use it on a specific controller like this: + +```ts +@UseFilters(new HttpExceptionFilter()) + +export class CatsController {} + +However, applying it to each controller individually can be tedious and lead to boilerplate code. Instead, we can register the exception filter globally, so it handles all relevant errors throughout the application. To do this, modify your `main.ts` file to include the global filter registration. Here's how: + +import { NestFactory } from '@nestjs/core'; + +import { AppModule } from './app.module'; + +import { SupertokensExceptionFilter } from './auth/auth.filter'; + +async function bootstrap() { + + const app = await NestFactory.create(AppModule); + + /* OMITTED FOR BREVITY */ + + app.useGlobalFilters(new SupertokensExceptionFilter()); + + await app.listen(3001); + +} + +bootstrap(); +``` + +This global setup ensures that the exception filter is automatically applied to all relevant routes, simplifying your error management. + + +#### Step 6: Fine-Grained Route Protection with Guards + +At this point, you might be wondering if all routes in our application are protected or none of them are. Both extremes are undesirable—what we really need is fine-grained control over which routes require protection. That’s where **guards** come in. + +While middleware excels at handling global tasks like validating tokens and managing sessions for every incoming request, it lacks the specificity required for controlling access to individual routes or methods. This is where guards in NestJS shine. + +A guard in NestJS allows you to define conditions for accessing specific routes. For example, while middleware might ensure a user’s session is valid, a guard can enforce more nuanced logic, such as ensuring the user is authenticated before accessing a certain route or verifying that the user has a particular role or permission. + +Guards provide the flexibility to secure sensitive parts of the application based on your exact needs, working in tandem with middleware for session management. By using guards, you can prevent unauthorized users from reaching certain routes even if their requests have passed through middleware checks. + +When you run the NestJS CLI command: + +```bash +$ nest g guard auth +``` + +it will generate a new file, `auth.guard.ts`, which contains the basic structure for the guard. Now we need to add logic to this guard to handle session-based authentication. + +Here’s the logic we’ll add to the `auth.guard.ts` file: + +```ts +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; + +import { + + getSession, + + VerifySessionOptions, + +} from 'supertokens-node/recipe/session'; + +@Injectable() + +export class AuthGuard implements CanActivate { + + constructor(private readonly getSessionOptions?: VerifySessionOptions) {} + + public async canActivate(context: ExecutionContext): Promise<boolean> { + + const ctx = context.switchToHttp(); + + const req = ctx.getRequest(); + + const resp = ctx.getResponse(); + + // If the session doesn't exist and {sessionRequired: true} is passed to the AuthGuard constructor (default is true), + + // getSession will throw an error that will be handled by the exception filter, returning a 401 response. + + // To avoid an error when the session doesn't exist, pass {sessionRequired: false} to the AuthGuard constructor. + + // In this case, req.session will be undefined if the session doesn't exist. + + const session = await getSession(req, resp, this.getSessionOptions); + + req.session = session; + + return true; + + } + +} +``` + +Let’s break down what’s happening in the **AuthGuard**. + +The **@Injectable()** decorator makes the **AuthGuard** class available for dependency injection in NestJS. This class implements the **CanActivate** interface, which defines the **canActivate** method responsible for determining whether a request should proceed to the route handler. + +The guard's constructor accepts an optional **VerifySessionOptions** argument, which allows customization of the session verification behavior. For example, you can specify whether a session is required for the route or if it’s optional. + +In the **canActivate method**, the HTTP request (**req**) and response (**resp**) are extracted from the **ExecutionContext**. The key logic lies in the call to **getSession(req, resp, this.getSessionOptions)** — this method checks for an active session on the request. + +* If a session exists, it’s attached to **req.session**, making session details accessible in the request. +* If no session exists and **{sessionRequired: true}** is passed (the default behavior), **getSession** will throw an error, which triggers the exception filter to return a 401 Unauthorized response. +* If **{sessionRequired: false}** is passed, the request will proceed even without a session, but **req.session** will be **undefined**. + +In the end, the guard returns **true**, meaning the request can continue as long as session validation passes. + +Now, when you run your application and try to access any protected route, nothing will happen — why? This is because we haven't yet told the app where to use the guard. + +In NestJS, guards are flexible and can be applied at different levels: + +* **Global level**: Protects every route in the app. +* **Controller level**: Protects all routes within a specific controller. +* **Route level**: Protects individual routes. + +Let’s attach our newly created guard at the controller level. You likely have an **AppController** already generated when you scaffolded the project. Here’s how to apply the guard: + +```ts +import { Controller, Get, UseGuards } from '@nestjs/common'; + +import { AuthGuard } from './auth/auth.guard'; + +@UseGuards(AuthGuard) + +@Controller() + +export class AppController { + + constructor(private readonly appService: AppService) {} + + @Get('/protected-route') + + getProtectedRouteInfo() {...} + +} +``` + +Alternatively, in some examples, you might see the guard applied like this: + +```ts +import { Controller, Get, UseGuards } from '@nestjs/common'; + +import { AuthGuard } from './auth/auth.guard'; + +@UseGuards(new AuthGuard()) + +@Controller() + +export class AppController { + + constructor(private readonly appService: AppService) {} + + @Get('/protected-route') + + getProtectedRouteInfo() {...} + +} +``` + +In the first example, we pass the **AuthGuard** class itself, allowing NestJS to manage its instantiation, which also enables dependency injection. In the second example, we manually instantiate the guard, which can be useful in certain scenarios. + +The guard now protects the entire controller, but if we wanted to protect only a specific route, we could do it like this: + +```ts +import { Controller, Get, UseGuards } from '@nestjs/common'; + +import { AuthGuard } from './auth/auth.guard'; + +@Controller() + +export class AppController { + + constructor(private readonly appService: AppService) {} + + @UseGuards(AuthGuard) + + @Get('/protected-route') + + getProtectedRouteInfo() {...} + +} +``` + +This approach allows you to selectively protect routes without applying the guard globally across the entire controller. + + +#### Step 7: Accessing Session Data with Decorators + +To effectively manage user authentication and session handling, it is often necessary to retrieve session data (like user ID or session-specific metadata) from incoming requests. Instead of manually extracting session information from each request, NestJS provides a more elegant solution through parameter decorators. + +Decorators simplify how we access session data by allowing us to inject session details directly into controller methods. This approach ensures clean, reusable code while keeping authentication-related logic separate from business logic. + +To create a custom decorator for session data: + + + +1. Run the following command from the root of the project: + +```bash +$ nest g decorator session auth +``` + +This command will generate a `session.decorator.ts` file inside the `auth/session` folder. + +2. Now, add the following code to the session.decorator.ts file: + +```ts + import { createParamDecorator, ExecutionContext } from '@nestjs/common'; + + + export const Session = createParamDecorator( + + + (data: unknown, ctx: ExecutionContext) => { + + + const request = ctx.switchToHttp().getRequest(); + + + return request.session; + + + }, + + + ); +``` + +The Session decorator uses the createParamDecorator function to extract the session data from the request. By tapping into the ExecutionContext, it switches to the HTTP layer, retrieves the request object, and returns the session attached to it. This session contains essential information such as the user ID, session handle, and access token payload. + +Use Cases for Session Decorators + +1. **User Identification**: You might want to retrieve the authenticated user’s ID for various actions such as updating profiles, managing orders, or handling permissions. + + const userId = session.getUserId(); + +2. **Access Control**: You can access roles or permissions stored in the session's token payload to implement role-based access control (RBAC). This can determine whether the user has the right to perform specific actions. + + const userRole = session.getAccessTokenPayload().role; + +3. **Session Metadata**: You can also track session-specific metadata, such as when the session was created, or apply additional logic like refreshing session tokens. + +To utilize the custom Session decorator in a protected controller, we inject it as a parameter: + +```ts +import { Controller, Get, UseGuards } from '@nestjs/common'; + +import { SessionContainer } from 'supertokens-node/recipe/session'; + +import { Session } from './auth/session/session.decorator'; + +import { AuthGuard } from './auth/auth.guard'; + +@UseGuards(AuthGuard) + +@Controller() + +export class AppController { + + constructor(private readonly appService: AppService) {} + + @Get('/protected-route') + + getProtectedRouteInfo(@Session() session: SessionContainer) { + + // you can inspect session object + + /** + + * console.log(session.getHandle()); + + * console.log(session.getUserId()); + + * console.log(session.getAccessTokenPayload()); + + */ + + } + +} +``` + +### Why Use Decorators for Session Data? + +* **Consistency**: Decorators standardize how session information is accessed across the application, ensuring consistent session handling. +* **Code Reusability**: Once the decorator is implemented, it can be reused across multiple controllers without repeating session extraction logic. +* **Separation of Concerns**: By isolating session handling in decorators, we keep the core business logic focused and avoid cluttering controllers with authentication details. + +By using this setup, you can streamline how session data is handled in your NestJS application and ensure efficient authentication management. + +For more advanced use cases and customizations, you can explore the [SuperTokens documentation](https://supertokens.com/docs/thirdpartypasswordless/common-customizations/sessions/about). This setup gives you the foundation for a robust authentication layer and user management. + + +## Conclusion + +In conclusion, integrating SuperTokens with NestJS provides a seamless and robust solution for managing authentication in modern applications. Throughout this article, we explored the fundamental concepts of authentication, the benefits of using NestJS as a backend framework, and how SuperTokens simplifies session management and token-based authentication. + +By leveraging middleware, exception filters, and guards, we demonstrated how to effectively handle authentication flows within a NestJS application. Whether you're working on user sessions, role-based access control, or token validation, SuperTokens offers a flexible and scalable approach to securing your app without the complexity typically associated with building authentication from scratch. + +With the knowledge of how to configure both self-hosted and managed SuperTokens setups, you're now equipped to implement secure, user-friendly authentication in your own NestJS projects. As your application scales, SuperTokens will continue to offer both simplicity and customization to meet your evolving security needs. + +Feel free to explore further customization and deepen your understanding of SuperTokens by exploring their detailed documentation and integrating additional features into your application. \ No newline at end of file diff --git a/content/how-to-secure-a-nestjs-app/managed-service-architecture.png b/content/how-to-secure-a-nestjs-app/managed-service-architecture.png new file mode 100644 index 00000000..b62fa88c Binary files /dev/null and b/content/how-to-secure-a-nestjs-app/managed-service-architecture.png differ diff --git a/content/how-to-secure-a-nestjs-app/self-hosted-architechture.png b/content/how-to-secure-a-nestjs-app/self-hosted-architechture.png new file mode 100644 index 00000000..d15e4f91 Binary files /dev/null and b/content/how-to-secure-a-nestjs-app/self-hosted-architechture.png differ diff --git a/content/how-to-secure-a-nestjs-app/too-many-variables.gif b/content/how-to-secure-a-nestjs-app/too-many-variables.gif new file mode 100644 index 00000000..f6c58c71 Binary files /dev/null and b/content/how-to-secure-a-nestjs-app/too-many-variables.gif differ diff --git a/content/unified-login/example-flow-2.png b/content/unified-login/example-flow-2.png new file mode 100644 index 00000000..3810090d Binary files /dev/null and b/content/unified-login/example-flow-2.png differ diff --git a/content/unified-login/example-flow-3.png b/content/unified-login/example-flow-3.png new file mode 100644 index 00000000..5a98fc2c Binary files /dev/null and b/content/unified-login/example-flow-3.png differ diff --git a/content/unified-login/example-flow.png b/content/unified-login/example-flow.png new file mode 100644 index 00000000..3f607ada Binary files /dev/null and b/content/unified-login/example-flow.png differ diff --git a/content/unified-login/glg_cal.mp4 b/content/unified-login/glg_cal.mp4 new file mode 100644 index 00000000..07732026 Binary files /dev/null and b/content/unified-login/glg_cal.mp4 differ diff --git a/content/unified-login/glg_docs.mp4 b/content/unified-login/glg_docs.mp4 new file mode 100644 index 00000000..15fcb14a Binary files /dev/null and b/content/unified-login/glg_docs.mp4 differ diff --git a/content/unified-login/glg_mail.mp4 b/content/unified-login/glg_mail.mp4 new file mode 100644 index 00000000..463f57a5 Binary files /dev/null and b/content/unified-login/glg_mail.mp4 differ diff --git a/content/unified-login/gloogle_full.mp4 b/content/unified-login/gloogle_full.mp4 new file mode 100644 index 00000000..f3092b07 Binary files /dev/null and b/content/unified-login/gloogle_full.mp4 differ diff --git a/content/unified-login/index.md b/content/unified-login/index.md new file mode 100644 index 00000000..6f320fbf --- /dev/null +++ b/content/unified-login/index.md @@ -0,0 +1,199 @@ +--- +title: "Unified Login: Because Who Doesn't Love a Good OAuth2 Adventure?" +date: "2024-12-09" +description: "Ah, authentication. The bane of every developer's existence. Or is it? 🤔 Today, we're diving into the wonderful world of a new feature called Unified Login. Buckle up, folks—it's gonna be a wild ride!" +cover: unified-login.png +category: "programming" +author: "Darko Bozhinovski" +--- + +## Table of Contents + + +- [Introduction](#introduction) +- [**What's the Deal with Unified Login?**](#whats-the-deal-with-unified-login) +- [**Aside: Why Would You Even Need This? When Should You Use Unified Login?**](#aside-why-would-you-even-need-this-when-should-you-use-unified-login) +- [**The OAuth2 Cast of Characters**](#the-oauth2-cast-of-characters) +- [**Tokens, Tokens Everywhere!**](#tokens-tokens-everywhere) +- [**Setting Up Your Gloogle Empire**](#setting-up-your-gloogle-empire) +- [**An Overview of Our All Things Gloogle**](#an-overview-of-our-all-things-gloogle) + * [**Our Backend**](#our-backend) + * [**Gloogle Auth**](#gloogle-auth) + * [**GloogleDocs - A VanillaJS App**](#gloogledocs-a-vanillajs-app) + * [**GloogleMail - A React App**](#glooglemail-a-react-app) + * [**GloogleCalendar - A SolidJS App**](#glooglecalendar-a-solidjs-app) + * [**Putting it all together**](#putting-it-all-together) +- [**The Good, The Bad, and The OAuth2**](#the-good-the-bad-and-the-oauth2) +- [**Wrapping Up**](#wrapping-up) +- [**Key Takeaways**](#key-takeaways) + +## Introduction + +Ah, authentication. The bane of every developer's existence. Or is it? 🤔 Today, we're diving into the wonderful world of a new feature called Unified Login. Buckle up, folks—it's gonna be a wild ride! + + +## **What's the Deal with Unified Login?** + +Picture this: you're building the next big thing. It's like Google, but cooler (obviously). You've got your GloogleDocs, GloogleMail, and GloogleCalendar all set up. But wait—how do you handle authentication across all these amazing services? Enter Unified Login. 🦸‍♀️ + +Unified Login is like that one friend who's great at introducing people at parties. It's a way to authenticate different types of applications using a common Authorization Server. In our case, that server is powered by SuperTokens. + + +## **Aside: Why Would You Even Need This? When Should You Use Unified Login?** + +Great question! I'm glad you asked. Here are a few scenarios where Unified Login might be your new best friend: + + + +1. You've got multiple frontend clients connecting to different backends + +![example flow](./example-flow.png) + +2. You're juggling multiple frontend clients that all connect to the same backend + +![example flow 2](./example-flow-2.png) + +(Hint: Gloogle, our demo below, uses this one) + +3. You want to use your website login for desktop and mobile apps too + + ![example flow 3](./example-flow-3.png) + + +Basically, if you're building the next Google (or Gloogle), Unified Login is your jam. Or, if you've already grown to the size where you need a single source of truth for all your authentication and authorization needs. + + +## **The OAuth2 Cast of Characters** + +Before we dive into the nitty-gritty, let's meet our OAuth2 stars: + + + +* 👤 **Resource Owner**: The user (that's you!) +* 💻 **Client**: The application that wants to access protected resources +* 🗺️ **Resource Server**: The server hosting the protected resources (often, an API of some kind) +* 🔒 **Authorization Server**: The server issuing OAuth2 Access Tokens + +Think of it like a fancy restaurant. You're the Resource Owner (the VIP), the Client is your personal assistant trying to get you a table, the Resource Server is the exclusive dining room, and the Authorization Server is the bouncer deciding who gets in (and get seated where, to stretch the analogy even further). + + +## **Tokens, Tokens Everywhere!** + +In the world of OAuth2, tokens are like golden tickets. Here are the ones you need to know: + + + +* **OAuth2 Access Token**: The VIP pass to access protected resources +* **OAuth2 Refresh Token**: The "I know a guy" token that gets you a new Access Token +* **ID Token**: The name tag that tells the Client who you are + + +## **Setting Up Your Gloogle Empire** + +Now, let's get down to business. Here's how you can set up Unified Login for your Gloogle services: + + + +1. Enable OAuth2 features in the SuperTokens Dashboard +2. Create OAuth2 Clients for each of your applications +3. Set up your Authorization Service +4. Configure session handling in each application +5. Update the login flow in your frontend apps +6. Test, test, and test again! + +...But, the neat part is that you can just ignore all of the steps above if you're out to test drive this. In fact, if you're the hands-on type, here's a handy link for you - [Gloogle Repo](https://github.com/supertokens/Gloogle). + + +## **An Overview of Our All Things Gloogle** + +As with most other tech empires, our Gloogle empire has multiple apps to offer. Otherwise, there's not much point in calling it an empire, right? Plus, the the apps were built in different time periods, using different frameworks. Common problem for a growing tech empire, wouldn't you agree? Luckily, we've moved away from using jQuery last year, so we're not *that* legacy. + +Let's take a closer look at each component: + + +### **Our Backend** + +The backbone of our Gloogle empire is, well, a backend. It's a server, handling request. Revolutionary, right? Under the hood, it's an express application relying on the SuperTokens [EmailPassword](https://supertokens.com/docs/emailpassword/quickstart/introduction), [Session](https://supertokens.com/docs/emailpassword/common-customizations/sessions/about) and [Unified Login](https://supertokens.com/docs/unified-login/introduction) recipes. + +For a server that does all of the auth heavy lifting, it comes at a whopping 120 lines of code: [Gloogle Backend repository](https://github.com/supertokens/Gloogle/tree/main/backend). + + +### **Gloogle Auth** + +Now, in OAuth2 land, servers also need to show a login screen somehow. There are two schools of thought with this one - some like co-locating their auth UI with the server, others like to keep the front-end part of the auth story separate. Team Gloogle, being cutting edge went for the second approach and went for a full fledged React app for the Auth screen: + +![login with google](./login-with-google.png) + +Happily enough, SuperTokens' unified login comes with support for that scenario too. In fact, as long as you make the backend aware of the frontend via the [website config option](https://github.com/supertokens/Gloogle/blob/master/backend/src/app.js#L77-L78)(and [vice-versa](https://github.com/supertokens/Gloogle/blob/master/gloogle-auth/src/auth.ts#L10-L11)), it all just works. + +Here's how that looks like: [Gloogle Auth](https://github.com/supertokens/Gloogle/tree/master/gloogle-auth). + + +### **GloogleDocs - A VanillaJS App** + +GloogleDocs is our straightforward document editing application. We went for vanillaJS when we first decided to build it - it was a different time. But, that doesn't have to stop us from being able to put our app under a single auth roof: + + + +And here's the source for a peek under the hood: [GloogleDocs repository](https://github.com/supertokens/Gloogle/tree/main/GloogleDocs). + + +### **GloogleMail - A React App** + +Of course, no self-respecting tech empire is complete without an email app. We built this one using React - and, as luck would have it, it was fairly easy to pull off putting this one under a unified login roof (in fact, easier than Gloogle Docs). Here's Gloogle Mail in action: + + + + +[GloogleMail repository](https://github.com/supertokens/Gloogle/tree/main/GloogleMail) for the source and more details. + + +### **GloogleCalendar - A SolidJS App** + +As the tech landscape evolved, so did Gloogle's tech choices. One of our newer addition is Gloogle Calendar - A SolidJS app, for that added `Signals` goodness. But, regardless of whether we're dealing with a modern, established or kinda outdated stack - SuperTokens's unified login just works. Here's Gloogle Calendar in action: + + + + +[GloogleCalendar repository](https://github.com/supertokens/Gloogle/tree/main/GloogleCalendar) to see how it all works. + + +### **Putting it all together** + +While you can clone the repo and run the Gloogle empire locally, here’s a video to see it in action: + + +Highlights: + + + +* Pay attention to the URL - on our first login attempt, we get redirected to localhost:3001 - which is the address of Gloogle Auth. Once we enter the correct credentials, we’re back to localhost:5173 (Gloogle Docs), in a logged-in state. +* On our second login try, for Gloogle Mail, the login screen isn’t shown at all - Gloogle Auth already remembers who we are and redirects us back to Gloogle Mail. Neat right? +* The same scenario applies to our third attempt on the video, for Gloogle Calendar. + + +## **The Good, The Bad, and The OAuth2** + +Now, I won't lie to you—setting up Unified Login isn't all sunshine and rainbows. There's a bit of red tape involved, especially when creating OAuth2 clients for each of your applications. But hey, that's the price we pay for security and convenience, right? + +On the bright side, once you've got it all set up, managing authentication across your Gloogle empire becomes a breeze. Your users can log in once and access all your services seamlessly. It's like magic, but with more HTTP requests. 🧙‍♂️ + + +## **Wrapping Up** + +So there you have it, folks—Unified Login with SuperTokens in a nutshell. Is it a bit complex? Sure. Is it worth it? Absolutely. Just imagine the looks on your users' faces when they realize they only need to remember one password for all your Gloogle services. Priceless. + +Remember, authentication doesn't have to be a nightmare. With the right tools and a bit of patience, you can create a login experience that's smoother than a freshly waxed surfboard. Now go forth and unify those logins! 🚀 + + +## **Key Takeaways** + + + +1. Unified Login is great for managing authentication across multiple applications. +2. OAuth2 is like a fancy restaurant—lots of roles and fancy passes. +3. Tokens are your new best friends. +4. Setting up Unified Login involves some steps, but it's worth it. +5. Always test your authentication flow thoroughly. + +Now, if you'll excuse me, I need to go check my GloogleMail. Happy coding! 👩‍💻👨‍💻 diff --git a/content/unified-login/login-with-google.png b/content/unified-login/login-with-google.png new file mode 100644 index 00000000..d724dc70 Binary files /dev/null and b/content/unified-login/login-with-google.png differ diff --git a/content/user-authentication-in-node/index.md b/content/user-authentication-in-node/index.md new file mode 100644 index 00000000..be45d122 --- /dev/null +++ b/content/user-authentication-in-node/index.md @@ -0,0 +1,373 @@ +--- +title: How to Authenticate and Authorize Users in a Node.js Express App +date: "2024-11-02" +description: "A step by step guide on how to Authenticate and Authorize Users in a Node.js Express App" +cover: "user-authentication-in-node.png" +category: "programming" +author: "Mostafa Ibrahim" +--- + +# Table of Contents + +- [Introduction](#introduction) +- [Handling Authorization in Node.js](#handling-authorization-in-nodejs) +- [Node.js User Authentication Prerequisites](#nodejs-user-authentication-prerequisites) +- [How to Implement User Authentication in Node.js](#how-to-implement-user-authentication-in-nodejs) + - [Backend Implementation](#backend-implementation) + - [Step 1: User Registration Process](#step-1-user-registration-process) + - [Step 2: Login and Session Management](#step-2-login-and-session-management) + - [Step 3: Protecting Routes with Middleware](#step-3-protecting-routes-with-middleware) + - [Frontend Implementation](#frontend-implementation) +- [Common Pitfalls and Security Best Practices](#common-pitfalls-and-security-best-practices) +- [Simplify Authentication with Supertokens](#simplify-authentication-with-supertokens) +- [Conclusion](#conclusion) + +# **Introduction** +Authentication and authorization are essential for web applications to ensure that only legitimate users gain access and that they can perform actions based on their permissions. **Node.js** and **Express.js** are popular tools for building these systems because they allow developers to create fast, scalable apps efficiently. + +However, implementing authentication can be challenging—**securing passwords, managing sessions**, and ensuring tokens aren’t misused require careful planning. Authorization adds more complexity by defining user roles and permissions, ensuring users only access what they’re allowed to. Good user management is critical for protecting both **user data** and **application security**, while also maintaining a smooth user experience. +# **Handling Authorization in Node.js** + +#### **Difference Between Authentication and Authorization** +- **Authentication:** + This process confirms the **identity of the user**—essentially verifying who they are. It typically involves methods like **username and password checks**, **social login**, or **multi-factor authentication** (MFA). For example, when a user logs into an application, authentication ensures that the individual is who they claim to be. +- **Authorization:** + Authorization determines **what actions or resources the authenticated user can access**. Once a user is authenticated, authorization checks whether they have the necessary permissions to perform specific operations, such as editing content or accessing admin features. + +Authentication and authorization complement each other: authentication verifies the user, while authorization governs the **extent of their access** within the system. + +----- +#### **Implementing Role-Based Access Control (RBAC)** +RBAC is a widely used strategy to **manage user permissions efficiently** by assigning roles to users. It simplifies authorization by grouping permissions under specific roles. + +- **Assigning roles to users:** + Users are given predefined roles such as **admin, editor, or viewer**. Each role corresponds to a set of permissions. For example: + - **Admin**: Full access to all operations, including creating, editing, and deleting content. + - **Editor**: Can modify content but lacks access to administrative settings. + - **Viewer**: Read-only access to content. +- **Defining permissions for each role:** + Each role has specific permissions that determine **what resources the user can access** and **what actions they can perform**. For example: + - Admins can manage other users and change system configurations. + - Editors can update or delete content but cannot manage users. +- **Importance of clear access rules:** + - Well-defined access rules **reduce the risk of security loopholes**. For example, without proper role separation, unauthorized users could gain access to sensitive data or critical system operations. + - **Consistency** in applying roles and permissions ensures better maintainability. Centralized control via middleware helps avoid inconsistencies, preventing scenarios where users have unintended privileges. + +RBAC simplifies managing access, especially in applications with many users. By grouping permissions under roles, developers can ensure that **user privileges are clear and manageable**, helping to maintain a secure system. + + +# **Node.js User Authentication Prerequisites** +To set up a secure user [authentication system in Node.js](https://supertokens.com/blog/how-to-deploy-supertokens-with-react-nodejs-express-on-vercel), you’ll need several essential tools and packages. These will enable you to handle routing, password encryption, token management, and cookie parsing, laying the groundwork for a robust authentication flow. + +#### **Setting Up the Environment** + +Install the following packages + +```bash +npm init -y +npm install express bcrypt jsonwebtoken cookie-parser +``` + +Run the server with the following command + +```bash +node server.js +``` + +----- +#### **Choosing an Authentication Method** + +There are several popular methods for handling authentication in web applications. Here’s an overview of the most commonly used approaches: + +- **JWT (JSON Web Tokens)**: JWTs are used for **stateless authentication**, meaning the server doesn’t store session information. Instead, a token is generated when the user logs in, which includes encoded user data and is sent with each request. The server then verifies the token to authenticate the user, making JWTs ideal for scalable, stateless applications. +- **Session-based Authentication**: This method involves storing session data on the server to keep track of user activity. When a user logs in, a session is created on the server, and a unique session ID is sent to the user’s browser, often in a cookie. This session ID is then used to identify the user for future requests. Session-based authentication is commonly used in applications where maintaining user state is essential. +- **OAuth**: OAuth is often used for third-party login, allowing users to sign in with existing accounts from services like Google, Facebook, or GitHub. It simplifies user login by leveraging these providers for authentication, eliminating the need for users to create new credentials for each application. OAuth is widely used in applications that prioritize user convenience and wish to offer social login options. + + +#### **Setting Up the Server and Authentication Routes** + +To configure the server, connect to MongoDB, and set up authentication routes, write the following code in the `Index.js` file: +### **Index.js** + +```typescript +const express = require('express'); +const mongoose = require('mongoose'); +const cors = require('cors'); +const dotenv = require('dotenv'); +const Message = require('./models/Message'); +const authRoutes = require('./routes/auth'); +const auth = require('./middleware/auth'); + +dotenv.config(); +const app = express(); +const PORT = process.env.PORT || 5000; + +app.use(cors()); +app.use(express.json()); + + + +// Routes +app.use('/api/auth', authRoutes); + +// Protected route (only accessible with a valid token) +app.get('/api/private', auth, (req, res) => { + res.send('This is a protected route'); + }); + + + +app.get('/', (req, res) => { + res.send('Hello World!'); +}); + +app.post('/message', async (req, res) => { + const newMessage = new Message({ text: req.body.text }); + try{ + await newMessage.save(); + res.status(201).json(newMessage); + } catch (error) { + res.status(500).json({ error: 'Error saving message' }); + } +}) + + +mongoose + .connect(process.env.MONGO\_URI) + .then(() => console.log('MongoDB Connected')) + .catch((err) => console.log('MongoDB connection error:', err)); + +app.listen(PORT, () => { + console.log(`Server is running on port ${PORT}`); +}); +``` + +# **How to Implement User Authentication in Node.js** +## **Backend Implementation** +### **Step 1: User Registration Process** +To securely register users, start by creating a Mongoose schema with fields for name, email, and password. Then, hash the password with `bcrypt` before saving it to enhance security. Finally, include basic validation to ensure required fields and unique email entries. To implement this setup, write the following code: + +### **userModel.js/Models** +```typescript +const mongoose = require('mongoose'); +const bcrypt = require('bcryptjs'); + +const userSchema = new mongoose.Schema({ + name: { type: String, required: true }, + email: { type: String, required: true, unique: true }, + password: { type: String, required: true }, + }); + +// Hash password before saving +userSchema.pre('save', async function (next) { + if (!this.isModified('password')) return next(); + this.password = await bcrypt.hash(this.password, 10); + next(); + }); + +module.exports = mongoose.model('User', userSchema); +``` + +### **Step 2: Login and Session Management** +To set up a secure login flow, validate user credentials by checking the stored hashed password in the database. JWT tokens will be used to maintain stateless sessions and manage token expiration, adding an extra layer of security. To implement this, write the following code in `Auth.js/Routes`: +### **Auth.js/Routes** +```typescript +const express = require('express'); +const User = require('../models/User'); +const jwt = require('jsonwebtoken'); +const bcrypt = require('bcryptjs'); +const router = express.Router(); + + +// Register a new user +router.post('/register', async (req, res) => { + const {name, email, password} = req.body; + try{ + const newUser = new User({ name, email, password }); + await newUser.save(); + res.status(201).json({message: 'User registered successfully' }); + } catch (error) { + res.status(400).json({ error: 'User already exists' }); + } +}); + + +//Login user and generate JWT token +router.post('/login', async (req, res) => { + const { email, password } = req.body; + try{ + const user = await User.findOne({ email }); + if (!User) return res.status(404).json({ error: 'User not found'}); + + const isMatch = await bcrypt.compare(password, user.password); + if (!isMatch) return res.status(401).json({ error: 'Invalid credentials' }); + + const token = jwt.sign({ userId: user.\_id }, process.env.JWT\_SECRET, { expiresIn: '1h'}); + res.json({ token }); + } catch (error) { + res.status(500).json({ error: 'Server error' }); + } +}); + +module.exports = router; +``` +### **Step 3: Protecting Routes with Middleware** +To restrict access to certain routes, middleware is used to ensure only authenticated users can access specific pages or data. The following code demonstrates a middleware function that checks for a valid token, verifies it, and grants access if authenticated. Write this code in `Auth.js/Middleware`: +### **Auth.js/Middleware** +```typescript +const jwt = require('jsonwebtoken'); + +const auth = (req, res, next) => { + const token = req.header('Authorization')?.split(' ')[1]; + if (!token) return res.status(401).json({ error: 'Access denied. No token provided.' }); + + try { + const decode = jwt.verify(token, process.env.JWT\_SECRET); + req.user = decode; + next(); + } catch (error) { + res.status(400).json({ error: 'Invalid Token' }); + } +}; + +module.exports = auth; +``` +This middleware function `auth` verifies if the request contains a valid JSON Web Token (JWT) in the authorization header. It checks for the token, verifies it using the secret key, and either allows access by calling `next()` or denies access if the token is invalid or missing. + +For implementing registration and login with JWT generation, add the following routes in `Auth.js/Routes`: +### **Auth.js/Routes** +```typescript +const express = require('express'); +const User = require('../models/User'); +const jwt = require('jsonwebtoken'); +const bcrypt = require('bcryptjs'); +const router = express.Router(); + + +// Register a new user +router.post('/register', async (req, res) => { + const {name, email, password} = req.body; + try{ + const newUser = new User({ name, email, password }); + await newUser.save(); + res.status(201).json({message: 'User registered successfully' }); + } catch (error) { + res.status(400).json({ error: 'User already exists' }); + } +}); + + +//Login user and generate JWT token +router.post('/login', async (req, res) => { + const { email, password } = req.body; + try{ + const user = await User.findOne({ email }); + if (!User) return res.status(404).json({ error: 'User not found'}); + + const isMatch = await bcrypt.compare(password, user.password); + if (!isMatch) return res.status(401).json({ error: 'Invalid credentials' }); + + const token = jwt.sign({ userId: user.\_id }, process.env.JWT\_SECRET, { expiresIn: '1h'}); + res.json({ token }); + } catch (error) { + res.status(500).json({ error: 'Server error' }); + } +}); + +module.exports = router; +``` +## **Frontend Implementation** +Finally, to create a simple login form that authenticates users, use the following code: +### **Login.js** +```typescript +import React, { useState } from 'react'; +import axios from 'axios'; + +function Login({ onLogin }) { // Accept onLogin as a prop + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [message, setMessage] = useState(''); + + const handleSubmit = async (e) => { + e.preventDefault(); // Prevents the page from refreshing on form submission + + try { + const { data } = await axios.post('http://localhost:5000/api/auth/login', { + email, + password + }); + localStorage.setItem('token', data.token); // Store JWT in localStorage + setMessage('Login Successful'); + onLogin(); // Call onLogin to inform the App component of the login status + } catch (error) { + setMessage('Login failed. Check your credentials.'); + } + }; + + return ( +
+

Login

+
+ setEmail(e.target.value)} + /> + setPassword(e.target.value)} + /> + +
+

{message}

+
+ ); +} + +export default Login; +``` + +# **Common Pitfalls and Security Best Practices** +Building a secure authentication and authorization system requires more than just checking passwords and tokens. Developers must adopt a range of best practices to safeguard user data, prevent unauthorized access, and ensure smooth user experiences. This section highlights common vulnerabilities—like insecure password storage, session mismanagement, and token misuse—and provides practical solutions to address them effectively. +#### **Password Management** +- **Avoid storing plain-text passwords:** Store passwords securely using **encryption techniques like hashing**. Libraries such as `bcrypt` or `argon2` generate hashed passwords that are computationally infeasible to reverse. This way, even if attackers gain access to the database, the original passwords remain protected. +- **Regularly update password policies:** Encourage the use of strong passwords and implement features like password expiration or complexity requirements to minimize vulnerabilities. +#### **Session and Token Management** +- **Short [expiration times for tokens](https://www.linkedin.com/pulse/deciding-token-expiration-time-subramanian-krishnan/):** Use **short-lived tokens** to limit the risk from compromised credentials. For instance, access tokens may expire in 15 minutes, and refresh tokens should be rotated frequently. +- **Store sensitive information securely:** Keep keys, secrets, and tokens safe by storing them in **environment variables**. Avoid hardcoding these sensitive values directly into the codebase to prevent exposure during development or deployment. +#### **Error Handling and Feedback** +- **Avoid exposing internal information:** Carefully design error messages to prevent leaking critical system information. For example, avoid messages like "Invalid username or password" to prevent attackers from inferring valid usernames. +- **Provide user-friendly but secure responses:** Make sure error messages offer users relevant feedback without revealing sensitive details. +#### **Using HTTPS** +- **Encrypt all communication between clients and servers** by using **HTTPS**. Encryption prevents sensitive data, such as login credentials or tokens, from being intercepted during transmission. +#### **CSRF Protection** +- **Prevent [Cross-Site Request Forgery (CSRF) attacks](https://portswigger.net/web-security/csrf):** Use **anti-CSRF tokens** for requests that modify data (non-GET requests). Libraries like `csurf` for Express or built-in protection from tools like **Supertokens** can simplify the process​. +#### **XSS Protection** +- **Mitigate Cross-Site Scripting (XSS) risks:** Use **HttpOnly cookies** to store tokens, ensuring they are inaccessible via JavaScript. This limits exposure to malicious scripts that might run on the client side. Additionally, validate user input and escape content properly to prevent injection attacks​. + +By following these best practices, developers can create more secure systems, safeguarding both user data and the application from common vulnerabilities. + +# **Simplify Authentication with Supertokens** +#### **Introduction to Supertokens** +Supertokens is a **developer-friendly authentication platform** designed to simplify the complexities of managing user sessions and secure access. It provides ready-made solutions for common challenges like **user registration, login flows, session handling, and token management**, so developers don't have to build these systems from scratch. With a focus on efficiency and security, Supertokens offers both flexibility and scalability for applications of all sizes. +#### **How Supertokens Helps** +- **Session Management Made Easy:** Supertokens automatically handles **JWT-based sessions** and token rotation, eliminating the need for manual token configurations. This ensures **stateless authentication** with minimal setup. +- **Built-in Social Login:** It includes support for social login providers such as **Google and Facebook**, allowing users to sign up seamlessly without complex custom configurations. +- **Multi-Factor Authentication (MFA):** For applications that require **stronger security**, Supertokens provides support for **MFA** out of the box, offering advanced protection without adding unnecessary development overhead. +#### **Advantages Over Manual Implementation** +- **Development Efficiency:** By providing **secure, pre-built APIs**, Supertokens reduces the amount of time needed to set up authentication and session management. +- **Reliable and Tested Authentication Flows:** Supertokens ensures that **authentication processes work consistently** by adhering to best practices and implementing features like token rotation and expiration by default. +- **Lower Complexity:** With Supertokens managing the backend intricacies of authentication, teams can **focus on core application features**, reducing complexity while maintaining security. +#### **Supertokens’ Security Protections: CSRF and XSS Mitigation** +- **CSRF Protection:** Supertokens includes **built-in CSRF protection** for non-GET API routes. This ensures that only legitimate requests are processed, reducing the risk of unauthorized actions through cross-site request forgery attacks​. +- **XSS Protection:** For enhanced session security, Supertokens uses **HttpOnly cookies** to store tokens, which prevents them from being accessed by JavaScript in case of an XSS attack​. This makes session management safer by mitigating the risks associated with script injections. + +Supertokens provides a secure, scalable solution that automates much of the work involved in authentication and session management. By implementing Supertokens, developers can ensure their applications are protected while also saving time and effort that would otherwise go into managing these systems manually. +# **Conclusion** +Authentication and authorization are essential for building secure web applications, requiring developers to carefully balance **security, usability, and performance**. These components ensure that only verified users gain access to the system and that their actions are appropriately controlled through permissions. This article covered the fundamental steps to build a secure authentication system, focusing on **user registration, login, session management, and role-based access control (RBAC)** to manage user permissions effectively. + +For developers looking to streamline the implementation process, **Supertokens** offers a powerful, ready-to-use solution. It reduces the time and complexity of managing tokens, sessions, and user roles while incorporating **advanced security features** such as **XSS and CSRF protection**. Explore [Supertokens](https://supertokens.com/product) to **simplify your authentication system**, saving development effort and enhancing your application’s security and reliability​. + diff --git a/static/blog-meta-images/authelia-alternatives.png b/static/blog-meta-images/authelia-alternatives.png new file mode 100644 index 00000000..837279b3 Binary files /dev/null and b/static/blog-meta-images/authelia-alternatives.png differ diff --git a/static/blog-meta-images/enterprise-sso.png b/static/blog-meta-images/enterprise-sso.png new file mode 100644 index 00000000..ae58db45 Binary files /dev/null and b/static/blog-meta-images/enterprise-sso.png differ diff --git a/static/blog-meta-images/flask-user-authentication.png b/static/blog-meta-images/flask-user-authentication.png new file mode 100644 index 00000000..a57a3808 Binary files /dev/null and b/static/blog-meta-images/flask-user-authentication.png differ diff --git a/static/blog-meta-images/how-to-secure-a-nestjs-app.png b/static/blog-meta-images/how-to-secure-a-nestjs-app.png new file mode 100644 index 00000000..341ea04c Binary files /dev/null and b/static/blog-meta-images/how-to-secure-a-nestjs-app.png differ diff --git a/static/blog-meta-images/unified-login.png b/static/blog-meta-images/unified-login.png new file mode 100644 index 00000000..7200aa98 Binary files /dev/null and b/static/blog-meta-images/unified-login.png differ diff --git a/static/blog-meta-images/user-authentication-in-node.png b/static/blog-meta-images/user-authentication-in-node.png new file mode 100644 index 00000000..c9e83228 Binary files /dev/null and b/static/blog-meta-images/user-authentication-in-node.png differ diff --git a/static/blog-seo/config.json b/static/blog-seo/config.json index bf183fc5..398970fa 100644 --- a/static/blog-seo/config.json +++ b/static/blog-seo/config.json @@ -1794,5 +1794,168 @@ ], "title": "What is FIDO", "schema": "" + }, + { + "path": "/blog/how-to-secure-a-nestjs-app", + "metaTags": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + " ", + "", + "" + ], + "title": "How to secure a NestJs Application", + "schema": "" + }, + { + "path": "/blog/authelia-alternatives", + "metaTags": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + " ", + "", + "" + ], + "title": "7 Top Authelia Alternatives for Enhanced Authentication in 2025", + "schema": "" + }, { + "path": "/blog/enterprise-sso", + "metaTags": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + " ", + "", + "" + ], + "title": "Best Practices for Enterprise SSO", + "schema": "" + }, { + "path": "/blog/unified-login", + "metaTags": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + " ", + "", + "" + ], + "title": "Unified Login: Because Who Doesn't Love a Good OAuth2 Adventure?", + "schema": "" + }, { + "path": "/blog/user-authentication-in-node", + "metaTags": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + " ", + "", + "" + ], + "title": "How to Authenticate and Authorize Users in a Node.js Express App", + "schema": "" + }, { + "path": "/blog/7-common-iam-risks-and-how-to-avoid-theme", + "metaTags": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + " ", + "", + "" + ], + "title": "7 Common IAM Risks and How to Avoid Them", + "schema": "" + }, { + "path": "/blog/flask-user-authentication", + "metaTags": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + " ", + "", + "" + ], + "title": "Adding Authentication to Your Flask Backend with SuperTokens", + "schema": "" } ] \ No newline at end of file diff --git a/static/blog-seo/sitemapconfig.json b/static/blog-seo/sitemapconfig.json index 3006f71c..653e9960 100644 --- a/static/blog-seo/sitemapconfig.json +++ b/static/blog-seo/sitemapconfig.json @@ -196,5 +196,29 @@ }, { "location": "https://supertokens.com/blog/authentik-vs-keycloak" + }, + { + "location": "https://supertokens.com/blog/how-to-secure-a-nestjs-app" + }, + { + "location": "https://supertokens.com/blog/what-is-fido" + }, + { + "location": "https://supertokens.com/blog/authelia-alternatives" + }, + { + "location": "https://supertokens.com/blog/enterprise-sso" + }, + { + "location": "https://supertokens.com/blog/unified-login" + }, + { + "location": "https://supertokens.com/blog/user-authentication-in-node" + }, + { + "location": "https://supertokens.com/blog/7-common-iam-risks-and-how-to-avoid-them" + }, + { + "location": "https://supertokens.com/blog/flask-user-auth" } ] \ No newline at end of file diff --git a/static/card_covers/7-common-iam-risks-and-how-to-avoid-them.png b/static/card_covers/7-common-iam-risks-and-how-to-avoid-them.png new file mode 100644 index 00000000..8ea03a17 Binary files /dev/null and b/static/card_covers/7-common-iam-risks-and-how-to-avoid-them.png differ diff --git a/static/card_covers/authelia-alternatives.png b/static/card_covers/authelia-alternatives.png new file mode 100644 index 00000000..1dd03892 Binary files /dev/null and b/static/card_covers/authelia-alternatives.png differ diff --git a/static/card_covers/enterprise-sso.png b/static/card_covers/enterprise-sso.png new file mode 100644 index 00000000..a5faf81b Binary files /dev/null and b/static/card_covers/enterprise-sso.png differ diff --git a/static/card_covers/flask-user-authentication.png b/static/card_covers/flask-user-authentication.png new file mode 100644 index 00000000..89a15848 Binary files /dev/null and b/static/card_covers/flask-user-authentication.png differ diff --git a/static/card_covers/how-to-secure-a-nestjs-app.png b/static/card_covers/how-to-secure-a-nestjs-app.png new file mode 100644 index 00000000..42bb2b15 Binary files /dev/null and b/static/card_covers/how-to-secure-a-nestjs-app.png differ diff --git a/static/card_covers/unified-login.png b/static/card_covers/unified-login.png new file mode 100644 index 00000000..d75d1344 Binary files /dev/null and b/static/card_covers/unified-login.png differ diff --git a/static/card_covers/user-authentication-in-node.png b/static/card_covers/user-authentication-in-node.png new file mode 100644 index 00000000..c9e83228 Binary files /dev/null and b/static/card_covers/user-authentication-in-node.png differ diff --git a/static/covers/7-common-iam-risks-and-how-to-avoid-them.png b/static/covers/7-common-iam-risks-and-how-to-avoid-them.png new file mode 100644 index 00000000..28960005 Binary files /dev/null and b/static/covers/7-common-iam-risks-and-how-to-avoid-them.png differ diff --git a/static/covers/authelia-alternatives.png b/static/covers/authelia-alternatives.png new file mode 100644 index 00000000..837279b3 Binary files /dev/null and b/static/covers/authelia-alternatives.png differ diff --git a/static/covers/enterprise-sso.png b/static/covers/enterprise-sso.png new file mode 100644 index 00000000..ae58db45 Binary files /dev/null and b/static/covers/enterprise-sso.png differ diff --git a/static/covers/flask-user-authentication.png b/static/covers/flask-user-authentication.png new file mode 100644 index 00000000..a57a3808 Binary files /dev/null and b/static/covers/flask-user-authentication.png differ diff --git a/static/covers/how-to-secure-a-nestjs-app.png b/static/covers/how-to-secure-a-nestjs-app.png new file mode 100644 index 00000000..341ea04c Binary files /dev/null and b/static/covers/how-to-secure-a-nestjs-app.png differ diff --git a/static/covers/unified-login.png b/static/covers/unified-login.png new file mode 100644 index 00000000..7200aa98 Binary files /dev/null and b/static/covers/unified-login.png differ diff --git a/static/covers/user-authentication-in-node.png b/static/covers/user-authentication-in-node.png new file mode 100644 index 00000000..c9e83228 Binary files /dev/null and b/static/covers/user-authentication-in-node.png differ