<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Web Security - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Web Security - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 09 Jun 2026 23:07:18 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/web-security/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How Attribute-Based Access Control Helps You Write Better Authorization Rules ]]>
                </title>
                <description>
                    <![CDATA[ Every application that handles user data eventually hits the same problem: not all users should see the same things. A junior nurse should not be able to access every patient record in the hospital. A ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-attribute-based-access-control-helps-you-write-better-authorization-rules/</link>
                <guid isPermaLink="false">6a21b44e09761aac249579f9</guid>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ access control ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Aiyedogbon Abraham ]]>
                </dc:creator>
                <pubDate>Thu, 04 Jun 2026 17:22:22 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/1bcd9989-cf38-4375-a0ed-03cf1bd3c3b8.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every application that handles user data eventually hits the same problem: not all users should see the same things.</p>
<p>A junior nurse should not be able to access every patient record in the hospital. A contractor should not be able to read internal financial reports. An employee logged in from an unrecognized device at 2AM probably should not be editing production configuration files.</p>
<p>Simple role-based systems handle obvious cases well. But as applications grow and access rules become more nuanced, those systems start to crack. You end up creating more and more specific roles, like <code>finance_viewer</code>, <code>finance_viewer_us_only</code>, <code>finance_viewer_us_only_readonly</code>, until the roles themselves become unmanageable.</p>
<p>Attribute-Based Access Control (ABAC) was designed to solve exactly this problem. It shifts from "what role does this user have?" to "what do we know about this user, this resource, and this situation?" and makes access decisions based on all of those factors together.</p>
<p>In this guide, you'll learn how ABAC works, how it evolved from earlier access control models, how policies are structured, how to implement it in code, and when to use it.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-how-access-control-has-evolved">How Access Control Has Evolved</a></p>
</li>
<li><p><a href="#heading-what-is-attribute-based-access-control">What is Attribute-Based Access Control?</a></p>
</li>
<li><p><a href="#heading-the-four-building-blocks-of-abac">The Four Building Blocks of ABAC</a></p>
</li>
<li><p><a href="#heading-how-an-abac-decision-is-made">How an ABAC Decision is Made</a></p>
</li>
<li><p><a href="#heading-how-to-write-abac-policies">How to Write ABAC Policies</a></p>
</li>
<li><p><a href="#heading-how-to-implement-abac-in-code">How to Implement ABAC in Code</a></p>
</li>
<li><p><a href="#heading-abac-vs-rbac-when-to-use-which">ABAC vs RBAC: When to Use Which</a></p>
</li>
<li><p><a href="#heading-real-world-use-cases">Real-World Use Cases</a></p>
</li>
<li><p><a href="#heading-enterprise-abac-considerations">Enterprise ABAC Considerations</a></p>
</li>
<li><p><a href="#heading-limitations-and-challenges">Limitations and Challenges</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a href="#heading-glossary">Glossary</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the most from this article, you should have:</p>
<ul>
<li><p>A basic understanding of web authentication (logins, sessions, tokens)</p>
</li>
<li><p>Familiarity with how users and resources relate in applications</p>
</li>
<li><p>Some experience reading JavaScript or pseudocode</p>
</li>
</ul>
<p>No prior knowledge of access control theory is required.</p>
<h2 id="heading-how-access-control-has-evolved">How Access Control Has Evolved</h2>
<p>To understand why ABAC exists, it helps to understand what came before it and why each generation fell short.</p>
<h3 id="heading-discretionary-and-mandatory-access-control">Discretionary and Mandatory Access Control</h3>
<p>Early access control models emerged from Department of Defense applications in the 1960s and 1970s. According to NIST Special Publication 800-162, these were Discretionary Access Control (DAC) and Mandatory Access Control (MAC).</p>
<p>In DAC, the owner of a resource decides who can access it. Think of a file on your computer where you choose who can read or edit it. In MAC, access is governed by a central authority using labels like "Classified" or "Top Secret." The system enforces these labels, not individual owners.</p>
<p>Both worked for their original purposes but didn't scale well to the complexity of modern networked systems.</p>
<h3 id="heading-identity-based-access-control-and-access-control-lists">Identity-Based Access Control and Access Control Lists</h3>
<p>As networks grew, identity-based access control (IBAC) became common. The most familiar implementation is the Access Control List (ACL), a list of users or groups attached to a resource, specifying what each can do.</p>
<p>ACLs are simple and transparent, but they create a management burden as systems grow. Every new user needs to be added to every relevant list. Every permission change means hunting through lists across multiple resources. And when someone leaves the organization, you need to find and remove them everywhere.</p>
<p>Failure to do this consistently leads to users accumulating privileges they should no longer have.</p>
<h3 id="heading-role-based-access-control">Role-Based Access Control</h3>
<p>Role-Based Access Control (RBAC) was a major step forward. Instead of assigning permissions directly to users, RBAC assigns them to roles. Users are then assigned roles. A hospital might have roles like <code>nurse</code>, <code>doctor</code>, <code>admin</code>, and <code>billing_staff</code>, each with different permissions.</p>
<p>This made administration much more manageable. Adding a new employee means assigning them appropriate roles. Removing an employee means removing their roles. Changing what nurses can do means updating the nurse role once.</p>
<p>RBAC became widely adopted and is still the right choice for many applications. But it has a structural weakness: as permission requirements become more granular, you have to create more specific roles. A nurse who can only see patients on their floor, only during their shift, or only for certain record types, needs a very specific role, or a combination of roles that interacts in complicated ways.</p>
<p>This proliferation is called "role explosion." The roles multiply until they are as difficult to manage as the individual permissions RBAC was supposed to replace.</p>
<h3 id="heading-attribute-based-access-control">Attribute-Based Access Control</h3>
<p>ABAC emerged as a response to role explosion. Instead of assigning roles that bundle fixed permissions, ABAC evaluates the actual characteristics of the user, the resource, and the context at the moment of every access request.</p>
<p>A nurse gets access to a patient record not because they have the <code>nurse</code> role, but because their job title is "Nurse Practitioner," the patient is on their assigned floor, it's currently their shift, and the record type is within their scope of care. Change any of those facts, and the access decision changes accordingly.</p>
<p>As NIST SP 800-162 defines it, ABAC is:</p>
<blockquote>
<p>"an access control method where subject requests to perform operations on objects are granted or denied based on assigned attributes of the subject, assigned attributes of the object, environment conditions, and a set of policies that are specified in terms of those attributes and conditions."</p>
</blockquote>
<h2 id="heading-what-is-attribute-based-access-control">What is Attribute-Based Access Control?</h2>
<p>ABAC is a logical access control model where every access decision is made by evaluating a set of rules against the current values of attributes. Nothing is pre-computed or cached in role assignments. Every time a user tries to do something, the system asks: given what we know about this user, this resource, and this moment, should this be allowed?</p>
<p>This makes ABAC highly precise and highly dynamic. Permissions don't accumulate over time. They don't need manual cleanup when someone's role changes. The system simply evaluates the current state of attributes every time.</p>
<p>The model is formally described in NIST's guide to ABAC as being capable of enforcing both Discretionary Access Control and Mandatory Access Control concepts, making it more expressive than models that only support one or the other.</p>
<p>Companies like Axiomatics, major government agencies, and large enterprises managing cross-organizational data sharing all rely on ABAC for its ability to scale security policies across complex environments.</p>
<h2 id="heading-the-four-building-blocks-of-abac">The Four Building Blocks of ABAC</h2>
<p>Every ABAC system is built from four types of information. Understanding these clearly is the key to understanding how ABAC works.</p>
<h3 id="heading-1-subject-attributes">1. Subject Attributes</h3>
<p>The subject is whoever or whatever is requesting access. This is usually a user, but it can also be a service, an application, or an automated system, what NIST calls a Non-Person Entity (NPE).</p>
<p>Subject attributes describe who the subject is:</p>
<pre><code class="language-plaintext">user.jobTitle         = "Nurse Practitioner"
user.department       = "Cardiology"
user.clearanceLevel   = "Confidential"
user.employmentStatus = "Active"
user.location         = "Floor 3"
user.shiftActive      = true
</code></pre>
<p>These attributes are typically sourced from an identity provider, HR system, or user directory. They're facts about the user that can be used in policies.</p>
<h3 id="heading-2-object-attributes-resource-attributes">2. Object Attributes (Resource Attributes)</h3>
<p>The object is whatever the subject is trying to access. This could be a file, a database record, an API endpoint, a service, or any other protected resource.</p>
<p>Object attributes describe what the resource is:</p>
<pre><code class="language-plaintext">record.type           = "PatientMedical"
record.floor          = "Floor 3"
record.sensitivity    = "High"
record.owner          = "Dr. Williams"
record.department     = "Cardiology"
</code></pre>
<p>Object attributes are typically assigned when a resource is created and updated throughout its lifecycle. They're facts about the resource that determine who should be able to access it.</p>
<h3 id="heading-3-action-attributes">3. Action Attributes</h3>
<p>The action is what the subject is trying to do to the object. Common actions include read, write, edit, delete, copy, execute, and share.</p>
<p>In many ABAC implementations, the action itself has attributes:</p>
<pre><code class="language-plaintext">action.type           = "read"
action.bulk           = false
</code></pre>
<p>Policies can restrict which actions are allowed independently of the other attributes. A user might be able to read a document but not delete it, even if all their other attributes match.</p>
<h3 id="heading-4-environment-conditions">4. Environment Conditions</h3>
<p>Environment conditions are contextual factors that don't belong to either the subject or the object, but that should influence the access decision. NIST describes these as "dynamic factors, independent of subject and object, that may be used as attributes at decision time to influence an access decision."</p>
<p>Examples include:</p>
<pre><code class="language-plaintext">environment.time           = "14:30"
environment.dayOfWeek      = "Wednesday"
environment.userLocation   = "Corporate Office"
environment.ipAddress      = "192.168.1.10"
environment.deviceStatus   = "compliant"
environment.threatLevel    = "low"
</code></pre>
<p>Environment conditions are what make ABAC truly dynamic. The same user, the same resource, and the same action might be allowed during business hours on a trusted device but denied at midnight from an unknown IP address.</p>
<h2 id="heading-how-an-abac-decision-is-made">How an ABAC Decision is Made</h2>
<p>When a subject tries to perform an action on an object, the ABAC system runs through a specific process:</p>
<h3 id="heading-step-1-collect-attributes">Step 1: Collect Attributes</h3>
<p>The system gathers current attributes for the subject, object, action, and environment. This might involve querying a user directory, reading resource metadata, and checking current time and location.</p>
<h3 id="heading-step-2-find-applicable-policies">Step 2: Find Applicable Policies</h3>
<p>The system identifies which policies apply to this particular request. A request to read a patient record might have several policies that apply: one about clinical staff access, one about after-hours access, and one about record sensitivity levels.</p>
<h3 id="heading-step-3-evaluate-each-policy">Step 3: Evaluate Each Policy</h3>
<p>Each applicable policy evaluates the collected attributes and returns permit or deny.</p>
<h3 id="heading-step-4-reconcile-conflicts">Step 4: Reconcile Conflicts</h3>
<p>If multiple policies apply and they conflict, the system uses predefined combining rules. Common approaches are "deny overrides" (if any policy says deny, the request is denied) or "permit overrides" (if any policy says permit, the request is permitted).</p>
<h3 id="heading-step-5-enforce-the-decision">Step 5: Enforce the Decision</h3>
<p>The system grants or denies access based on the final decision.</p>
<p>This process happens every time an access request is made. There's no caching of role assignments or pre-computed permission tables. The decision reflects the current state of all attributes at the moment of the request.</p>
<h2 id="heading-how-to-write-abac-policies">How to Write ABAC Policies</h2>
<p>Policies are the logic at the heart of ABAC. They're written as conditional rules that reference attributes. A well-written policy reads like a business rule, because that's exactly what it is.</p>
<h3 id="heading-simple-boolean-policy">Simple Boolean Policy</h3>
<p>The most basic form evaluates whether certain attributes match:</p>
<pre><code class="language-javascript">// Policy: Only active employees can access internal resources
function canAccessInternalResource(user) {
  return user.employmentStatus === "Active";
}
</code></pre>
<p><strong>What this does:</strong> Checks a single attribute, employment status, before allowing access. Any inactive, suspended, or terminated user is denied, regardless of their roles or past access history.</p>
<h3 id="heading-multi-attribute-policy">Multi-Attribute Policy</h3>
<p>Real policies typically combine multiple attributes:</p>
<pre><code class="language-javascript">// Policy: A nurse can read a patient record
// if the patient is on their assigned floor
// and during their active shift

function canReadPatientRecord(user, record, environment) {
  const isNurse = user.jobTitle === "Nurse Practitioner";
  const isAssignedFloor = user.assignedFloor === record.floor;
  const isActiveDuty = user.shiftActive === true;

  return isNurse &amp;&amp; isAssignedFloor &amp;&amp; isActiveDuty;
}
</code></pre>
<p><strong>What this does:</strong> Combines three conditions using AND logic. All three must be true for access to be granted. Change the nurse's floor assignment, and they immediately lose access to records on the previous floor, without any manual intervention.</p>
<h3 id="heading-environment-aware-policy">Environment-Aware Policy</h3>
<p>Adding environment conditions makes policies context-sensitive:</p>
<pre><code class="language-javascript">// Policy: Users can only access sensitive financial records
// during business hours from the corporate network

function canAccessSensitiveFinancialRecord(user, record, environment) {
  const isFinanceStaff = user.department === "Finance";
  const isHighSensitivity = record.sensitivity === "High";
  
  // If this is a high-sensitivity record, apply time and location controls
  if (isHighSensitivity) {
    const currentHour = new Date(environment.timestamp).getHours();
    const isBusinessHours = currentHour &gt;= 9 &amp;&amp; currentHour &lt; 17;
    const isCorporateNetwork = environment.ipRange === "corporate";

    return isFinanceStaff &amp;&amp; isBusinessHours &amp;&amp; isCorporateNetwork;
  }

  // Lower sensitivity records only require finance department membership
  return isFinanceStaff;
}
</code></pre>
<p><strong>What this does:</strong> Applies stricter controls to higher-sensitivity resources. The same user gets access to low-sensitivity records at any time, but high-sensitivity records require them to be on the corporate network during business hours. The policy logic mirrors the actual business rule: sensitive data needs more protection.</p>
<h3 id="heading-ownership-based-policy">Ownership-Based Policy</h3>
<p>ABAC can also implement discretionary ownership rules:</p>
<pre><code class="language-javascript">// Policy: A user can edit a document
// if they own it, or if they have editor permissions
// and the document isn't locked

function canEditDocument(user, document, action) {
  const isOwner = document.ownerId === user.id;
  const hasEditorPermission = user.permissions.includes("document.edit");
  const isUnlocked = document.status !== "locked";

  return (isOwner || hasEditorPermission) &amp;&amp; isUnlocked;
}
</code></pre>
<p><strong>What this does:</strong> Combines ownership (an attribute of the relationship between user and document) with explicit permissions and resource state. An editor can't edit a locked document even if they have the edit permission. An owner can edit their own documents but not locked ones.</p>
<h2 id="heading-how-to-implement-abac-in-code">How to Implement ABAC in Code</h2>
<p>Let's build a simple ABAC evaluation engine that puts these pieces together.</p>
<h3 id="heading-step-1-define-the-attribute-structure">Step 1: Define the Attribute Structure</h3>
<p>First, define clear data structures for your attributes:</p>
<pre><code class="language-javascript">// A user (subject) requesting access
const user = {
  id: "user-123",
  name: "Sarah Chen",
  department: "Cardiology",
  jobTitle: "Nurse Practitioner",
  clearanceLevel: 2,
  assignedFloor: "Floor 3",
  shiftActive: true,
  employmentStatus: "Active"
};

// A resource (object) being accessed
const patientRecord = {
  id: "record-456",
  type: "PatientMedical",
  floor: "Floor 3",
  sensitivity: 2,
  ownerId: "doctor-789",
  department: "Cardiology"
};

// Environment conditions
const environment = {
  timestamp: new Date().toISOString(),
  ipAddress: "10.0.1.25",
  ipRange: "corporate",
  deviceCompliant: true
};
</code></pre>
<h3 id="heading-step-2-write-policy-functions">Step 2: Write Policy Functions</h3>
<p>Write individual policies as pure functions that take attributes and return boolean values:</p>
<pre><code class="language-javascript">// policies/patientRecord.js

// Policy 1: User must be active and clinical staff
function isClinicalStaff(user) {
  const clinicalTitles = [
    "Nurse Practitioner",
    "Physician",
    "Resident",
    "Medical Assistant"
  ];
  return (
    user.employmentStatus === "Active" &amp;&amp;
    clinicalTitles.includes(user.jobTitle)
  );
}

// Policy 2: Record must be within the user's assigned area
function isAssignedToRecord(user, record) {
  return (
    user.department === record.department &amp;&amp;
    user.assignedFloor === record.floor
  );
}

// Policy 3: User must be on active shift
function isOnActiveShift(user) {
  return user.shiftActive === true;
}

// Policy 4: High-sensitivity records require compliant devices
function meetsDeviceRequirements(record, environment) {
  if (record.sensitivity &gt;= 3) {
    return environment.deviceCompliant === true;
  }
  return true; // No device requirement for lower sensitivity
}
</code></pre>
<p><strong>What this does:</strong> Each policy is a small, focused function. This makes policies easy to test individually, easy to read, and easy to reuse across different access decisions. A policy for "is this user clinical staff" can be applied to many different resource types.</p>
<h3 id="heading-step-3-build-an-evaluation-engine">Step 3: Build an Evaluation Engine</h3>
<p>Combine your policies into a decision engine:</p>
<pre><code class="language-javascript">// abac/engine.js

function evaluateAccess(user, resource, action, environment, policies) {
  // Collect all policy results
  const results = policies.map(policy =&gt; {
    try {
      return policy(user, resource, action, environment);
    } catch (error) {
      console.error(`Policy evaluation error: ${error.message}`);
      return false; // Fail closed: deny on error
    }
  });

  // Deny-overrides: if any policy denies, access is denied
  return results.every(result =&gt; result === true);
}

// Assemble policies for reading patient records
const readPatientRecordPolicies = [
  (user) =&gt; isClinicalStaff(user),
  (user, record) =&gt; isAssignedToRecord(user, record),
  (user) =&gt; isOnActiveShift(user),
  (user, record, action, environment) =&gt; meetsDeviceRequirements(record, environment)
];

// Make an access decision
const canRead = evaluateAccess(
  user,
  patientRecord,
  "read",
  environment,
  readPatientRecordPolicies
);

console.log(`Access ${canRead ? "granted" : "denied"}`);
// → Access granted (all conditions met)
</code></pre>
<p><strong>What this does:</strong> The engine loops through each policy function, passing in the relevant attributes. If all policies return true, access is granted. If any returns false, access is denied. This is called "deny-overrides combining". The <code>try-catch</code> ensures that if a policy throws an error, access is denied rather than granted, following the security principle of fail-closed.</p>
<h3 id="heading-step-4-add-attribute-collection">Step 4: Add Attribute Collection</h3>
<p>In a real application, attributes come from multiple sources:</p>
<pre><code class="language-javascript">// attributes/collector.js

async function collectAttributes(userId, resourceId) {
  // Collect in parallel for performance
  const [user, resource, environment] = await Promise.all([
    fetchUserAttributes(userId),      // From identity provider or HR system
    fetchResourceAttributes(resourceId), // From resource metadata store
    collectEnvironmentConditions()    // Time, IP, device status
  ]);

  return { user, resource, environment };
}

async function fetchUserAttributes(userId) {
  // This would query your user directory, LDAP, or identity provider
  const user = await userDirectory.findById(userId);
  const shift = await shiftService.getActiveShift(userId);
  
  return {
    ...user,
    shiftActive: shift !== null,
    assignedFloor: shift?.floor || null
  };
}

async function collectEnvironmentConditions() {
  return {
    timestamp: new Date().toISOString(),
    ipAddress: request.ip,
    ipRange: await networkService.classifyIP(request.ip),
    deviceCompliant: await deviceService.checkCompliance(request.deviceId)
  };
}
</code></pre>
<p><strong>What this does:</strong> Attribute collection is separated from policy evaluation. This is an important design decision: it means you can test policies with any attribute values without needing real users or resources. It also means you can swap out the source of attributes (say, moving from an on-premise directory to a cloud identity provider) without changing your policies.</p>
<h3 id="heading-step-5-integrate-with-your-api">Step 5: Integrate with Your API</h3>
<p>Use the evaluation engine in your API handlers:</p>
<pre><code class="language-javascript">// middleware/abac.js

function requireAccess(action, resourceType) {
  return async (req, res, next) =&gt; {
    try {
      const { user, resource, environment } = await collectAttributes(
        req.user.id,
        req.params.id
      );

      const policies = getPoliciesFor(resourceType, action);
      const allowed = evaluateAccess(user, resource, action, environment, policies);

      if (!allowed) {
        // Log the denial for audit purposes
        auditLog.record({
          userId: req.user.id,
          resourceId: req.params.id,
          action,
          decision: "denied",
          timestamp: new Date()
        });

        return res.status(403).json({ error: "Access denied" });
      }

      next();
    } catch (error) {
      // Fail closed: deny access on unexpected errors
      return res.status(403).json({ error: "Access denied" });
    }
  };
}

// Use in route definitions
app.get(
  "/patient-records/:id",
  authenticate(),                               // First verify identity
  requireAccess("read", "patientRecord"),       // Then evaluate ABAC
  patientRecordController.getById               // Then handle the request
);
</code></pre>
<p><strong>What this does:</strong> The ABAC check lives in middleware that runs between authentication and the route handler. Authentication establishes who the user is. ABAC decides whether that user can do what they're trying to do. This separation keeps authorization logic out of your business logic.</p>
<h2 id="heading-abac-vs-rbac-when-to-use-which">ABAC vs RBAC: When to Use Which</h2>
<p>RBAC isn't obsolete. It's genuinely the right choice for many applications. The question is which model fits your specific access requirements.</p>
<h3 id="heading-rbac-strengths">RBAC Strengths</h3>
<p>RBAC is simple to understand, simple to implement, and simple to audit. If you can describe your access requirements as a list of roles with fixed permissions, RBAC works well. Most SaaS applications start with RBAC and it serves them fine for years.</p>
<p>A typical RBAC check looks like:</p>
<pre><code class="language-javascript">// Simple RBAC: does the user have the required role?
function canAccess(user, requiredRole) {
  return user.roles.includes(requiredRole);
}
</code></pre>
<p>It's fast, clear, and easy to debug. When something goes wrong, you check which roles the user has and which roles the resource requires.</p>
<h3 id="heading-where-rbac-breaks-down">Where RBAC Breaks Down</h3>
<p>RBAC struggles when permissions need to depend on factors that aren't captured by a role. If you need to express "finance managers can view financial records, but only for their own region, and only during business hours," you're outside what a role alone can express cleanly.</p>
<p>You either need an extremely specific role (<code>finance_manager_us_east_business_hours</code>) that creates the role explosion problem, or you add conditional logic to your application code that effectively recreates ABAC, just in a less organized way.</p>
<h3 id="heading-rbac-vs-abac-comparison">RBAC vs ABAC Comparison</h3>
<table>
<thead>
<tr>
<th>Factor</th>
<th>RBAC</th>
<th>ABAC</th>
</tr>
</thead>
<tbody><tr>
<td>Logic</td>
<td>Permissions assigned to roles, roles assigned to users</td>
<td>Policies evaluate attributes at decision time</td>
</tr>
<tr>
<td>Granularity</td>
<td>Coarse-grained</td>
<td>Fine-grained and context-aware</td>
</tr>
<tr>
<td>Flexibility</td>
<td>Low, new rules require new roles</td>
<td>High, update policies without changing roles</td>
</tr>
<tr>
<td>Scalability</td>
<td>Role explosion under complexity</td>
<td>Scales with policy complexity, not role count</td>
</tr>
<tr>
<td>Auditability</td>
<td>Simple, check role assignments</td>
<td>Requires logging attributes at decision time</td>
</tr>
<tr>
<td>Complexity</td>
<td>Low</td>
<td>Higher, more moving parts</td>
</tr>
<tr>
<td>Best for</td>
<td>Simple, stable permission structures</td>
<td>Complex, dynamic, or context-dependent permissions</td>
</tr>
</tbody></table>
<h3 id="heading-combining-both-models">Combining Both Models</h3>
<p>RBAC and ABAC work well together. A common pattern is to use RBAC for coarse-grained access control (which sections of your application can this user see?) and ABAC for fine-grained control within those sections (which specific records can they access?).</p>
<p>For example, a role might grant access to the patient records section of a hospital system. Within that section, ABAC policies determine which specific records a user can view or edit based on their department, assigned floor, and active shift.</p>
<h2 id="heading-real-world-use-cases">Real-World Use Cases</h2>
<h3 id="heading-healthcare-records-management">Healthcare Records Management</h3>
<p>Healthcare is one of the clearest examples of why ABAC matters. Patient privacy regulations require precise access control, and patient care requires that the right staff can access records quickly when they need them.</p>
<p>An ABAC policy in a hospital might allow a nurse to view a patient's record only when:</p>
<ol>
<li><p>the patient is currently admitted to the nurse's assigned floor,</p>
</li>
<li><p>the nurse is on an active shift,</p>
</li>
<li><p>the access occurs from within the hospital network,</p>
</li>
<li><p>and the record type is within the nurse's care scope.</p>
</li>
</ol>
<p>According to WorkOS's ABAC analysis, in emergency situations ABAC systems can automatically expand access rights. For example, an ER doctor automatically gains broader access to patient records to provide immediate care, with this access being time-bound and closely monitored.</p>
<p>All of these rules would require dozens of roles in an RBAC system, and those roles would still struggle to handle the emergency access scenario dynamically.</p>
<h3 id="heading-corporate-data-access">Corporate Data Access</h3>
<p>Large enterprises typically have employees across departments, roles, locations, and clearance levels who need different views of the same underlying data. A document might be accessible to finance managers in the US region during business hours, accessible to executives globally at any time, but inaccessible to contractors entirely.</p>
<p>ABAC expresses all of these rules in policies. As employees change departments, go on leave, or change roles, their attributes update in the identity system and their access changes automatically, with no manual ACL updates required.</p>
<h3 id="heading-government-and-classified-information">Government and Classified Information</h3>
<p>The US federal government's adoption of ABAC is described in NIST SP 800-162, which was developed to address the Federal Identity, Credential, and Access Management (FICAM) requirements. Federal agencies deal with information shared across organizational boundaries, with varying classification levels and need-to-know requirements.</p>
<p>ABAC allows an analyst in one agency to access information from another agency without requiring the second agency to pre-provision an account for them. The analyst's clearance attributes, organizational affiliation, and project assignments are evaluated against the resource's classification and access rules at the time of the request.</p>
<h3 id="heading-multi-tenant-saas-applications">Multi-Tenant SaaS Applications</h3>
<p>SaaS applications that serve multiple organizations need to ensure strict data isolation between tenants while supporting complex permission structures within each tenant.</p>
<p>ABAC handles this naturally. A resource attribute like <code>record.tenantId</code> is evaluated against the user attribute <code>user.tenantId</code>, and no cross-tenant access is possible through policy. Within a tenant, ABAC supports as much complexity as the tenant's policies require.</p>
<h2 id="heading-enterprise-abac-considerations">Enterprise ABAC Considerations</h2>
<p>Deploying ABAC at enterprise scale introduces several challenges that don't exist in smaller implementations.</p>
<h3 id="heading-policy-administration">Policy Administration</h3>
<p>Policies need to be authored, reviewed, tested, and deployed. According to NIST SP 800-162, this requires a Policy Administration Point (PAP), an interface for creating and managing policies. Without proper tooling, policies become difficult to audit and maintain.</p>
<p>In practice, this means treating policies like code: version control, code review, and automated testing.</p>
<h3 id="heading-attribute-quality-and-freshness">Attribute Quality and Freshness</h3>
<p>ABAC is only as good as the attributes it evaluates. If user attributes are stale, for example, for a user who changed departments but whose directory entry hasn't been updated, the access decisions will be wrong.</p>
<p>NIST warns that "attributes that are not refreshed as often will ultimately be less secure than attributes that are refreshed in real time." Building reliable attribute pipelines from authoritative sources is often the hardest part of ABAC deployment.</p>
<h3 id="heading-performance">Performance</h3>
<p>Evaluating policies on every request has a performance cost. Each evaluation may require fetching attributes from multiple sources. To manage this, many implementations use attribute caching, but caching introduces the staleness problem described above.</p>
<p>The solution is to cache with appropriate TTLs (time-to-live values) based on how quickly each attribute type can change. A user's department changes rarely and can be cached for hours. A user's active shift status might change every 8 hours and needs a shorter cache. Real-time location might not be cacheable at all.</p>
<h3 id="heading-audit-logging">Audit Logging</h3>
<p>Because ABAC makes decisions dynamically, auditing requires logging the attributes used in each decision, not just the decision itself. A log entry that says "access denied" is only useful if it also captures why access was denied and which attributes failed to satisfy which policies.</p>
<p>NIST notes that without tracking attribute values at decision time, accountability requirements can't be met.</p>
<h2 id="heading-limitations-and-challenges">Limitations and Challenges</h2>
<p>ABAC is powerful, but it's not the right solution for every access control problem. It's worth being honest about its limitations before committing to an implementation.</p>
<p><strong>Complexity</strong>: According to NIST SP 800-162, "an ABAC system is more complicated, and therefore more costly to implement and maintain, than simpler access control systems." The flexibility that makes ABAC powerful also makes it harder to reason about. A user asking "why can't I access this?" requires examining all the attributes that were evaluated and which conditions weren't met.</p>
<p><strong>Policy Conflicts</strong>: In complex systems with many policies, conflicts between policies can occur. Two policies might individually seem correct but together produce unexpected results. Resolving these conflicts requires clear precedence rules and careful policy design.</p>
<p><strong>Attribute Management Overhead</strong>: Maintaining accurate attributes across large user populations requires investment in identity infrastructure. Attributes from different systems need to be normalized, validated, and kept synchronized. As NIST describes it, organizations need an entire attribute management infrastructure, not just a policy engine.</p>
<p><strong>Testing is Hard</strong>: Because access depends on the combination of potentially dozens of attributes, testing edge cases comprehensively requires thought. A policy that works correctly for typical cases might behave unexpectedly for unusual attribute combinations.</p>
<p><strong>Not Always Worth the Investment</strong>: For applications with straightforward access requirements, ABAC introduces unnecessary complexity. If your needs can be expressed cleanly as a set of roles with fixed permissions, RBAC is the better choice.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Attribute-Based Access Control represents a genuine evolution in how applications manage authorization. Rather than maintaining ever-growing lists of roles and permissions, ABAC evaluates the actual characteristics of users, resources, and context at the moment of every request.</p>
<p>It solves the role explosion problem that plagues complex RBAC implementations. It enables access rules that reflect real business policies rather than technical approximations of them. It handles dynamic scenarios, emergencies, time-based restrictions, and cross-organizational access that are difficult or impossible to express with static roles.</p>
<p>But ABAC isn't universally better. It's more complex to build, harder to debug, and requires investment in attribute management infrastructure that simpler models don't need. Many applications are well-served by RBAC, and some use RBAC and ABAC together.</p>
<p>The right question isn't "should I use ABAC?" It's "are my access requirements complex enough that the investment in ABAC pays off?" If your access rules change frequently, depend on resource or environment context, or need to scale across organizational boundaries, ABAC is worth serious consideration.</p>
<p>Start by identifying where your current access control model is breaking down. If you're creating roles to represent every edge case, if you're writing conditional logic inside route handlers that checks specific attribute values, or if users are accumulating permissions they should no longer have, those are signals that a more expressive model would help.</p>
<p>ABAC is the tool for when roles aren't enough.</p>
<h2 id="heading-glossary">Glossary</h2>
<p><strong>ABAC (Attribute-Based Access Control)</strong>: An access control method where authorization decisions are made by evaluating policies against the attributes of subjects, objects, actions, and environment conditions. Defined by NIST as the approach where "subject requests to perform operations on objects are granted or denied based on assigned attributes."</p>
<p><strong>Subject</strong>: The entity requesting access to a resource. Usually a human user, but can also be a service, automated process, or device. Also called the "requestor."</p>
<p><strong>Object</strong>: The resource being protected, such as a file, database record, API endpoint, service, or any system resource whose access is managed by the ABAC system.</p>
<p><strong>Attribute</strong>: A characteristic of a subject, object, action, or environment expressed as a name-value pair. For example, <code>user.department = "Finance"</code> or <code>record.sensitivity = "High"</code>.</p>
<p><strong>Subject Attributes</strong>: Properties describing the user or service making the request, such as job title, department, clearance level, or current location.</p>
<p><strong>Object Attributes</strong>: Properties describing the resource being accessed, such as its type, owner, sensitivity level, or department.</p>
<p><strong>Environment Conditions</strong>: Contextual factors independent of both subject and object that influence access decisions. Examples include time of day, day of week, IP address, device compliance status, or current threat level.</p>
<p><strong>Policy</strong>: A rule or set of rules that evaluates attribute values to determine whether a specific access request should be permitted or denied. ABAC policies are typically written as logical conditions.</p>
<p><strong>Policy Decision Point (PDP)</strong>: The component of an ABAC system that evaluates policies and attributes to compute an access decision.</p>
<p><strong>Policy Enforcement Point (PEP)</strong>: The component that intercepts access requests and enforces the decisions made by the PDP.</p>
<p><strong>Policy Information Point (PIP)</strong>: The component that retrieves attribute values needed by the PDP to make decisions.</p>
<p><strong>Policy Administration Point (PAP)</strong>: The component that provides an interface for creating, testing, and managing policies.</p>
<p><strong>RBAC (Role-Based Access Control)</strong>: An access control model that assigns permissions to roles and users to roles. Simpler than ABAC but less expressive for complex, dynamic access requirements.</p>
<p><strong>Role Explosion</strong>: The proliferation of increasingly specific roles in an RBAC system as access requirements become more granular, eventually making the roles as difficult to manage as individual permissions.</p>
<p><strong>DAC (Discretionary Access Control)</strong>: An access control model where resource owners control who can access their resources. Common in file systems.</p>
<p><strong>MAC (Mandatory Access Control)</strong>: An access control model where access is governed by a central authority using classification labels, independent of resource owner preferences.</p>
<p><strong>ACL (Access Control List)</strong>: A list associated with a resource that specifies which users or groups have which permissions. Common in identity-based access control systems.</p>
<p><strong>Non-Person Entity (NPE)</strong>: A subject that is not a human user, such as an automated service, application, or network device, that can request access to resources.</p>
<p><strong>Attribute Caching</strong>: Storing previously retrieved attribute values to improve performance, at the cost of potentially using stale data for access decisions.</p>
<p><strong>Deny-Overrides Combining</strong>: A policy combining rule where if any applicable policy returns deny, the overall decision is deny, regardless of other policies that may return permit.</p>
<p><strong>Fail-Closed</strong>: A security design principle where unexpected errors or missing information result in access being denied rather than granted, reducing the risk of unauthorized access.</p>
<p><em>Source: Definitions adapted from NIST Special Publication 800-162, Guide to Attribute Based Access Control (ABAC) Definition and Considerations, January 2014 (with updates through August 2019).</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Secure iOS Apps in Swift: Common Security Pitfalls and How to Fix Them ]]>
                </title>
                <description>
                    <![CDATA[ These days, there are many ways attackers can try to compromise your applications. And thanks to the continued increase in cyberattacks, the demand for secure mobile applications – and by extension, secure coding – has never been higher. So if you’re... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-secure-ios-apps-in-swift-common-security-pitfalls-and-how-to-fix-them/</link>
                <guid isPermaLink="false">68ffdf1761d216440f5bb38a</guid>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ios app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alex Tray ]]>
                </dc:creator>
                <pubDate>Mon, 27 Oct 2025 21:07:35 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761599240278/644f6ebb-6092-4ea0-99e3-a568bfb0390c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>These days, there are many ways attackers can try to compromise your applications. And thanks to the continued increase in cyberattacks, the demand for secure mobile applications – and by extension, secure coding – has never been higher.</p>
<p>So if you’re an iOS developer, you should also learn to prioritize security at every stage of app development.</p>
<p>Swift, Apple’s modern programming language, offers a wealth of tools and frameworks that simplify development while enhancing security, but only when used correctly.</p>
<p>This article explores 10 common security pitfalls in Swift-based iOS apps and offers practical strategies to mitigate them.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>Before diving in, you’ll need:</p>
<ul>
<li><p>Working knowledge of Swift and iOS development.</p>
</li>
<li><p>Access to Xcode.</p>
</li>
<li><p>Basic understanding of how iOS apps communicate with servers.</p>
</li>
<li><p>Familiarity with Terminal/command line basics.</p>
</li>
</ul>
<p>The code examples are practical and explained step-by-step, making them accessible to junior developers while still offering value to experienced ones looking to strengthen their app's security.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<dl>
<ul>
<li><a href="" id="heading-what-are-the-most-prevalent-security-traps-in-swift-ios-applications">What are the Most Prevalent Security Traps in Swift iOS Applications?</a>
<ul>
<li><a href="" id="heading-1-insecure-data-storage">1. Insecure Data Storage</a></li>
<li><a href="" id="heading-2-weak-network-communication">2. Weak Network Communication</a></li>
<li><a href="" id="heading-3-improper-input-validation">3. Improper Input Validation</a></li>
<li><a href="" id="heading-4-hardcoding-secrets">4. Hardcoding Secrets</a></li>
<li><a href="" id="heading-5-insufficient-authentication-and-authorization">5. Insufficient Authentication and Authorization</a></li>
<li><a href="" id="heading-6-insecure-logging-and-error-handling">6. Insecure Logging and Error Handling</a></li>
<li><a href="" id="heading-7-ignoring-code-obfuscation-and-reverse-engineering">7. Ignoring Code Obfuscation and Reverse Engineering</a></li>
<li><a href="" id="heading-8-insecure-third-party-libraries">8. Insecure Third-Party Libraries</a></li>
<li><a href="" id="heading-9-insufficient-biometric-and-multi-factor-authentication">9. Insufficient Biometric and Multi-Factor Authentication</a></li>
<li><a href="" id="heading-10-disregarding-periodic-security-testing">10. Disregarding Periodic Security Testing</a></li>
</ul>
</li>
</ul>
</dl>

<h2 id="heading-what-are-the-most-prevalent-security-traps-in-swift-ios-applications"><strong>What are the Most Prevalent Security Traps in Swift iOS Applications?</strong></h2>
<p>Swift and iOS offer robust security features, but mistakes still happen. Following are the most common traps and how to fix them:</p>
<h3 id="heading-1-insecure-data-storage">1. Insecure Data Storage</h3>
<p>Among the most common mistakes developers make is having sensitive data stored insecurely. Passwords, tokens, or even individual user data can be left by accident in UserDefaults or local storage in unencrypted form. </p>
<p>While UserDefaults is convenient for small amounts of data, it is not secure for sensitive data as it is so easily accessible to attackers if the device is compromised.</p>
<h4 id="heading-how-to-fix">How to Fix:</h4>
<p>Use the Keychain Services API to securely store sensitive data. Keychain encrypts data and binds it to the device so that it can't be accessed by other unauthorized applications or users.</p>
<p>You can securely store credentials using libraries in Swift such as KeychainAccess or the built-in SecItemAdd and SecItemCopyMatching functions.</p>
<p>For example, this how you can store a user password in Keychain so as to ensure sensitive data is stored securely:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">do</span> {

<span class="hljs-keyword">try</span> keychain.<span class="hljs-keyword">set</span>(<span class="hljs-string">"userPassword123"</span>, key: <span class="hljs-string">"userPassword"</span>)

} <span class="hljs-keyword">catch</span> {

    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error saving to Keychain: \(error)"</span>)

}
</code></pre>
<p>Behind the scenes, here’s what happens when you call <code>keychain.set("userPassword123", key: "userPassword")</code> inside a KeychainManager class that uses Apple’s native Security framework for storage:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Security

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">KeychainManager</span> </span>{
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">set</span><span class="hljs-params">(<span class="hljs-number">_</span> value: String, key: String)</span></span> <span class="hljs-keyword">throws</span> {
     <span class="hljs-comment">// 1. Convert string to Data</span>
     <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> data = value.data(using: .utf8) <span class="hljs-keyword">else</span> {
         <span class="hljs-keyword">throw</span> <span class="hljs-type">NSError</span>(domain: <span class="hljs-string">"KeychainManager"</span>, code: -<span class="hljs-number">1</span>)
     }

     <span class="hljs-comment">// 2. Build the query dictionary</span>
     <span class="hljs-keyword">let</span> query: [<span class="hljs-type">String</span>: <span class="hljs-type">Any</span>] = [
         <span class="hljs-comment">// Store as password</span>
         kSecClass <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecClassGenericPassword,
         <span class="hljs-comment">// Your app's bundle identifier</span>
         kSecAttrService <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: <span class="hljs-string">"com.yourapp.keychain"</span>,
         <span class="hljs-comment">// "userPassword"</span>
         kSecAttrAccount <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: key,
         <span class="hljs-comment">// "userPassword123" encrypted</span>
         kSecValueData <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: data,
         kSecAttrAccessible <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecAttrAccessibleAfterFirstUnlock
     ]
     <span class="hljs-comment">// 3. Save to keychain (iOS encrypts it automatically)</span>
     <span class="hljs-keyword">let</span> status = <span class="hljs-type">SecItemAdd</span>(query <span class="hljs-keyword">as</span> <span class="hljs-type">CFDictionary</span>, <span class="hljs-literal">nil</span>)
     <span class="hljs-comment">// 4. Check if successful</span>
     <span class="hljs-keyword">guard</span> status == errSecSuccess <span class="hljs-keyword">else</span> {
         <span class="hljs-keyword">throw</span> <span class="hljs-type">NSError</span>(domain: <span class="hljs-string">"KeychainManager"</span>, code: <span class="hljs-type">Int</span>(status))
     }
 }
}
</code></pre>
<p>When this function runs, iOS converts the string value, such as "userPassword123", into encrypted binary data and stores it securely in the device’s Keychain database. The entry is saved under the provided key (for example, "userPassword"), and only your app can access it.</p>
<p>Behind the scenes, the Keychain leverages strong security features, including hardware-backed encryption using device-specific keys, optional biometric protection through Face ID or Touch ID, and app-level isolation to ensure that no other app can read or modify your stored credentials.</p>
<h3 id="heading-2-weak-network-communication">2. Weak Network Communication</h3>
<p>Transmitting sensitive data over the network is another area prone to vulnerabilities. Using unencrypted HTTP connections exposes your app to man-in-the-middle (MITM) attacks, allowing attackers to intercept and modify data in transit.  </p>
<p><strong>The Problem</strong>: When data travels between your app and server over an insecure connection, attackers on the same network (like public Wi-Fi) can:</p>
<ul>
<li><p>Read sensitive information (passwords, personal data, payment details)</p>
</li>
<li><p>Modify requests and responses</p>
</li>
<li><p>Impersonate your legitimate server</p>
</li>
</ul>
<h4 id="heading-how-to-fix-1">How to Fix:</h4>
<p><strong>1. Always Use HTTPS</strong><br>HTTPS encrypts all data in transit, making it unreadable to attackers. iOS's App Transport Security (ATS) enforces this by blocking insecure HTTP connections by default:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ❌ INSECURE - HTTP connection (blocked by ATS by default)</span>
<span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string: <span class="hljs-string">"http://api.example.com/login"</span>)

<span class="hljs-comment">// ✅ SECURE - HTTPS connection</span>
<span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string: <span class="hljs-string">"https://api.example.com/login"</span>)
</code></pre>
<p>You’ll want to avoid adding ATS exceptions to your Info.plist unless absolutely necessary. If a third-party API only supports HTTP, contact them to upgrade or find a more secure alternative.</p>
<p><strong>2. Implement Certificate Pinning (Advanced Protection)</strong></p>
<p>Even with HTTPS, your app could still be vulnerable to sophisticated MITM attacks. An attacker could install a fraudulent certificate on a user's device (through malware or social engineering), for example, and intercept HTTPS traffic that appears valid. The attacker's fake certificate would be trusted by the device, allowing them to decrypt and read "secure" communications.</p>
<p>Certificate pinning solves this by making your app trust only your specific server's certificate, rejecting all others – even if they're otherwise valid.</p>
<p><strong>How Certificate Pinning Works:</strong></p>
<p>Your app stores the expected certificate (or its public key hash) and validates it during each connection:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureNetworkManager</span>: <span class="hljs-title">NSObject</span>, <span class="hljs-title">URLSessionDelegate</span> </span>{

    <span class="hljs-comment">// Store your server's certificate hash</span>
    <span class="hljs-comment">// Get this by running: openssl x509 -in certificate.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> expectedPublicKeyHash = <span class="hljs-string">"YOUR_CERTIFICATE_HASH_HERE"</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">urlSession</span><span class="hljs-params">(
        <span class="hljs-number">_</span> session: URLSession,
        didReceive challenge: URLAuthenticationChallenge,
        completionHandler: @escaping <span class="hljs-params">(URLSession.AuthChallengeDisposition, URLCredential?)</span></span></span> -&gt; <span class="hljs-type">Void</span>
    ) {
        <span class="hljs-comment">// Step 1: Check if this is a server trust challenge (certificate validation)</span>
        <span class="hljs-keyword">guard</span> challenge.protectionSpace.authenticationMethod == <span class="hljs-type">NSURLAuthenticationMethodServerTrust</span>,
              <span class="hljs-keyword">let</span> serverTrust = challenge.protectionSpace.serverTrust
        <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Not a certificate challenge; use default handling</span>
            completionHandler(.performDefaultHandling, <span class="hljs-literal">nil</span>)
            <span class="hljs-keyword">return</span>
        }

        <span class="hljs-comment">// Step 2: Validate that the server's certificate matches our pinned certificate</span>
        <span class="hljs-keyword">if</span> isValidServerTrust(serverTrust) {
            <span class="hljs-comment">// Certificate matches - proceed with the connection</span>
            completionHandler(.useCredential, <span class="hljs-type">URLCredential</span>(trust: serverTrust))
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Certificate doesn't match - reject the connection to prevent MITM attack</span>
            completionHandler(.cancelAuthenticationChallenge, <span class="hljs-literal">nil</span>)
        }
    }

    <span class="hljs-comment">// Validates the server's certificate against our pinned hash</span>
    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isValidServerTrust</span><span class="hljs-params">(<span class="hljs-number">_</span> serverTrust: SecTrust)</span></span> -&gt; <span class="hljs-type">Bool</span> {
        <span class="hljs-comment">// Extract the server's certificate</span>
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> serverCertificate = <span class="hljs-type">SecTrustGetCertificateAtIndex</span>(serverTrust, <span class="hljs-number">0</span>) <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
        }

        <span class="hljs-comment">// Get the public key from the certificate</span>
        <span class="hljs-keyword">let</span> serverPublicKey = <span class="hljs-type">SecCertificateCopyKey</span>(serverCertificate)
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> publicKey = serverPublicKey <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
        }

        <span class="hljs-comment">// Convert the public key to data and hash it</span>
        <span class="hljs-keyword">var</span> error: <span class="hljs-type">Unmanaged</span>&lt;<span class="hljs-type">CFError</span>&gt;?
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> publicKeyData = <span class="hljs-type">SecKeyCopyExternalRepresentation</span>(publicKey, &amp;error) <span class="hljs-keyword">as</span> <span class="hljs-type">Data?</span> <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
        }

        <span class="hljs-comment">// Hash the public key using SHA-256</span>
        <span class="hljs-keyword">let</span> publicKeyHash = <span class="hljs-type">SHA256</span>.hash(data: publicKeyData)
        <span class="hljs-keyword">let</span> publicKeyHashString = <span class="hljs-type">Data</span>(publicKeyHash).base64EncodedString()

        <span class="hljs-comment">// Compare with our expected hash</span>
        <span class="hljs-keyword">return</span> publicKeyHashString == expectedPublicKeyHash
    }
}
</code></pre>
<p>What this code does, step-by-step:</p>
<ol>
<li><p><code>urlSession(_:didReceive:completionHandler:)</code> – This method is called whenever your app makes an HTTPS connection. iOS asks: "Should I trust this server's certificate?"</p>
</li>
<li><p>Check authentication method – We verify this is a server trust challenge (certificate validation), not some other type of authentication.</p>
</li>
<li><p>Validate the certificate – We call <code>isValidServerTrust()</code>, which:</p>
<ul>
<li><p>Extracts the server's certificate from the connection</p>
</li>
<li><p>Gets the public key from that certificate</p>
</li>
<li><p>Hashes the public key using SHA-256</p>
</li>
<li><p>Compares the hash to our stored, expected hash</p>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li>Make a decision:</li>
</ol>
<ul>
<li><p>If hashes match, then the server is legitimate. Proceed with <code>.useCredential</code>.</p>
</li>
<li><p>If hashes don't match, we have a potential MITM attack. Cancel with <code>.cancelAuthenticationChallenge</code>.</p>
</li>
</ul>
<p>So how does this prevent MITM attacks? Even if an attacker installs a fraudulent certificate on the user's device and intercepts traffic, their certificate's hash won't match your pinned hash. Your app will reject the connection, preventing the attacker from decrypting your traffic.</p>
<p><strong>3. Additional Protection: Recommend a VPN on Public Wi-Fi</strong></p>
<p>You can also recommend that users connect through a VPN when on public Wi-Fi for an added layer of security, and provide guidance on <a target="_blank" href="https://surfshark.com/blog/how-to-use-a-vpn">how to use a VPN</a> effectively to keep their data safe.</p>
<p>For developers, maintaining strong app security also depends on having a well-optimized system, learning <a target="_blank" href="https://cleanmymac.com/blog/macos-tahoe-slow">how to speed up a slow Mac</a> can help ensure smoother builds, faster testing, and a more secure overall development workflow.</p>
<h3 id="heading-3-improper-input-validation">3. Improper Input Validation</h3>
<p>Some developers neglect correct input validation, leading to a number of vulnerabilities including SQL injection, remote code execution, and data corruption.</p>
<p>While Swift has strong typing support, some developers don’t sanitize user input or API responses. Incorporating real-time <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-email-validation-api-for-flask-user-authentication/">API email validation</a> ensures that users provide legitimate, properly formatted email addresses before they are stored or processed, reducing both security risks and data quality issues.</p>
<h4 id="heading-how-to-fix-2">How to Fix:</h4>
<p>Input validation is your first line of defense against malicious data. Here's how to protect your iOS applications:</p>
<p><strong>1. Validate User Input with Patterns</strong></p>
<p>Always validate user input using regular expressions or predefined patterns before processing. For example, when accepting email addresses:</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isValidEmail</span><span class="hljs-params">(<span class="hljs-number">_</span> email: String)</span></span> -&gt; <span class="hljs-type">Bool</span> {
    <span class="hljs-keyword">let</span> emailRegex = <span class="hljs-string">"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"</span>
    <span class="hljs-keyword">let</span> emailPredicate = <span class="hljs-type">NSPredicate</span>(format: <span class="hljs-string">"SELF MATCHES %@"</span>, emailRegex)
    <span class="hljs-keyword">return</span> emailPredicate.evaluate(with: email)
}

<span class="hljs-comment">// Only accept properly formatted data</span>
<span class="hljs-keyword">guard</span> isValidEmail(userEmail) <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Reject invalid input</span>
    <span class="hljs-keyword">return</span>
}
</code></pre>
<p>This ensures that only properly formatted data is accepted, preventing malformed or malicious input from entering your system.</p>
<p><strong>2. Sanitize API Responses</strong></p>
<p>Never trust external data. Always validate and sanitize API responses before using them:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> userAge = apiResponse[<span class="hljs-string">"age"</span>] <span class="hljs-keyword">as</span>? <span class="hljs-type">Int</span>,
   userAge &gt;= <span class="hljs-number">0</span> &amp;&amp; userAge &lt;= <span class="hljs-number">150</span> {
    <span class="hljs-comment">// Safe to use</span>
    user.age = userAge
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Handle invalid data appropriately</span>
    <span class="hljs-keyword">throw</span> <span class="hljs-type">ValidationError</span>.invalidAge
}
</code></pre>
<p><strong>3. Use Parameterized Queries (Most Critical)</strong></p>
<p>The most dangerous mistake is building database queries through string concatenation. Consider this vulnerable code:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ❌ NEVER DO THIS - Vulnerable to SQL Injection</span>
<span class="hljs-keyword">let</span> username = userInput  <span class="hljs-comment">// Could be: "admin' OR '1'='1"</span>
<span class="hljs-keyword">let</span> query = <span class="hljs-string">"SELECT * FROM users WHERE username = '\(username)'"</span>
database.execute(query)
</code></pre>
<p>If a malicious user enters admin' OR '1'='1 as their username, the query becomes:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">users</span> <span class="hljs-keyword">WHERE</span> username = <span class="hljs-string">'admin'</span> <span class="hljs-keyword">OR</span> <span class="hljs-string">'1'</span>=<span class="hljs-string">'1'</span>
</code></pre>
<p>This would return all users in the database instead of just one, potentially exposing sensitive data. The secure solution uses parameterized queries:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ✅ SAFE - Using parameterized queries</span>
<span class="hljs-keyword">let</span> query = <span class="hljs-string">"SELECT * FROM users WHERE username = ?"</span>
database.execute(query, withArgumentsIn: [username])
</code></pre>
<p>In this approach, the <code>?</code> is a placeholder that the database treats as a parameter, not as part of the SQL command. The username value is passed separately in the <code>withArgumentsIn</code> array.</p>
<p>This means that even if a user tries to inject SQL code like <code>admin' OR '1'='1</code>, the database will treat the entire string as a literal username to search for – not as executable SQL code. The database engine automatically escapes any special characters, completely eliminating the risk of SQL injection.</p>
<p>By separating the query structure from the data, parameterized queries ensure that user input can never alter the intended logic of your SQL statements.</p>
<h3 id="heading-4-hardcoding-secrets">4. Hardcoding Secrets</h3>
<p>API keys, credentials, or private tokens hard-coded in the source code is another serious security mistake. Attackers can extract such secrets from compiled binaries using reverse-engineering tools, especially for apps released to the public.</p>
<p>Once exposed, these credentials can be used to access your backend services, potentially leading to data breaches or unauthorized charges.</p>
<h4 id="heading-the-problem-hardcoded-secrets">The Problem – Hardcoded Secrets:</h4>
<pre><code class="lang-swift"><span class="hljs-comment">// NEVER DO THIS</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">APIClient</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> apiKey = <span class="hljs-string">"1234567890abcdef"</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> secretToken = <span class="hljs-string">"sk_live_51H..."</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">makeRequest</span><span class="hljs-params">()</span></span> {
        <span class="hljs-comment">// These secrets are embedded in your binary</span>
        <span class="hljs-keyword">let</span> headers = [<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">"Bearer \(apiKey)"</span>]
    }
}
</code></pre>
<p><strong>How to Fix:</strong></p>
<p>Never store sensitive credentials directly in your code. Here are secure alternatives:</p>
<p><strong>Solution 1: Fetch Secrets from Backend at Runtime</strong></p>
<p>The most secure approach is to never store secrets on the client at all. Instead, authenticate users and let your backend make authorized API calls:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">APIClient</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> sessionToken: <span class="hljs-type">String?</span>

    <span class="hljs-comment">// User logs in and receives a temporary session token</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">authenticateUser</span><span class="hljs-params">(email: String, password: String)</span></span> async <span class="hljs-keyword">throws</span> {
        <span class="hljs-keyword">let</span> response = <span class="hljs-keyword">try</span> await backend.login(email: email, password: password)
        <span class="hljs-comment">// Store only a temporary, user-specific session token</span>
        <span class="hljs-keyword">self</span>.sessionToken = response.sessionToken
    }

    <span class="hljs-comment">// Backend handles the actual API calls with the real API key</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchUserData</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; <span class="hljs-type">UserData</span> {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> token = sessionToken <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">throw</span> <span class="hljs-type">AuthError</span>.notAuthenticated
        }

        <span class="hljs-comment">// Your backend receives this request, validates the session token,</span>
        <span class="hljs-comment">// then uses its own API keys to fetch data from third-party services</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> await backend.getUserData(sessionToken: token)
    }
}
</code></pre>
<p><strong>How this works:</strong></p>
<p>Your app never knows the actual API keys. When a user needs data, your app sends a request to your own backend server with a session token. Your backend validates the token, then uses its own securely stored API keys to make the actual third-party API calls. This way, the real secrets never leave your server.</p>
<p><strong>Solution 2: Environment Variables or Config Files (Development Only)</strong></p>
<p>For development environments, use .xcconfig files that are excluded from version control:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Secrets.xcconfig (add to .gitignore!)</span>
<span class="hljs-type">API_KEY</span> = your_dev_api_key_here
<span class="hljs-type">API_SECRET</span> = your_dev_secret_here

<span class="hljs-comment">// Access in your code through Info.plist</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> apiKey: <span class="hljs-type">String</span> = {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> key = <span class="hljs-type">Bundle</span>.main.object(forInfoDictionaryKey: <span class="hljs-string">"API_KEY"</span>) <span class="hljs-keyword">as</span>? <span class="hljs-type">String</span> <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"API_KEY not found in configuration"</span>)
        }
        <span class="hljs-keyword">return</span> key
    }()
}
</code></pre>
<p><strong>Important</strong>: This approach is only suitable for non-production environments! Never ship production API keys with your app, even in config files.</p>
<h3 id="heading-5-insufficient-authentication-and-authorization">5. Insufficient Authentication and Authorization</h3>
<p>Relying on client-side authentication and authorization checks is risky. Attackers can cause the app to bypass these checks and access in an unauthorized way by brute forcing or tampering with the app/runtime.</p>
<h4 id="heading-how-to-fix-3">How to Fix:</h4>
<ul>
<li><p>Do authentication and authorization on the server side instead of the client-side.</p>
</li>
<li><p>Use JWT (JSON Web Tokens) or OAuth 2.0 for authenticated user login.</p>
</li>
<li><p>Token expiration and refresh logic needs to be implemented in order to minimize the likelihood of token theft.</p>
</li>
</ul>
<p><strong>Example: Securely sending JWT:</strong></p>
<pre><code class="lang-swift"><span class="hljs-keyword">let</span> request = <span class="hljs-type">URLRequest</span>(url: apiURL)

request.setValue(<span class="hljs-string">"Bearer \(jwtToken)"</span>, forHTTPHeaderField: <span class="hljs-string">"Authorization"</span>)
</code></pre>
<h3 id="heading-6-insecure-logging-and-error-handling">6. Insecure Logging and Error Handling</h3>
<p>Extensive and insecure logging practices, as well as uncaught exceptions, can lead to the exposure of sensitive information including usernames, passwords, and API keys.</p>
<h4 id="heading-how-to-fix-4">How to Fix:</h4>
<ul>
<li><p>Log sensitive information carefully.</p>
</li>
<li><p>Implement controlled error management and provide the minimum amount of information in user-presented messages.</p>
</li>
<li><p>Implement secure logging libraries that mask or encrypt personal data.</p>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-keyword">do</span> {
    <span class="hljs-keyword">try</span> someRiskyOperation()
} <span class="hljs-keyword">catch</span> {
    <span class="hljs-comment">// Log error securely</span>
    <span class="hljs-type">Logger</span>.log(<span class="hljs-string">"Operation failed: \(error.localizedDescription)"</span>)
}
</code></pre>
<h3 id="heading-7-ignoring-code-obfuscation-and-reverse-engineering">7. Ignoring Code Obfuscation and Reverse Engineering</h3>
<p>Swift binaries can be reverse-engineered to expose sensitive business logic, algorithms, or hidden secrets. Attackers use tools like Hopper Disassembler, class-dump, or IDA Pro to decompile your app and analyze how it works internally. This risk is often underestimated, especially for smaller apps, but any app can be a target.</p>
<p>This means that when you compile a Swift app, the resulting binary contains:</p>
<ul>
<li><p>Class names and method signatures</p>
</li>
<li><p>String literals (URLs, error messages, keys)</p>
</li>
<li><p>The structure of your code logic</p>
</li>
<li><p>Algorithm implementations</p>
</li>
</ul>
<p>An attacker can extract this information and use it to understand your app's authentication flow and bypass it, copy your proprietary algorithms, find hardcoded API endpoints or keys you thought were "hidden", discover premium features to unlock without paying, and so on.</p>
<p><strong>Why It's Bad – Real Example:</strong></p>
<p>Let's imagine you have a premium feature check in your app:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FeatureManager</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isPremiumUser</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Bool</span> {
        <span class="hljs-comment">// Check if user has premium access</span>
        <span class="hljs-keyword">let</span> hasSubscription = <span class="hljs-type">UserDefaults</span>.standard.bool(forKey: <span class="hljs-string">"premium_unlocked"</span>)
        <span class="hljs-keyword">return</span> hasSubscription
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">unlockPremiumFeature</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">guard</span> isPremiumUser() <span class="hljs-keyword">else</span> {
            showPaywall()
            <span class="hljs-keyword">return</span>
        }
        <span class="hljs-comment">// Show premium content</span>
        showPremiumContent()
    }
}
</code></pre>
<p>An attacker could reverse-engineer your app and discover that the method <code>isPremiumUser()</code> controls access, and that it simply checks a <code>UserDefaults</code> key called <code>premium_unlocked</code>. They would then know that they could use runtime manipulation tools to set this value to true, bypassing your paywall entirely.</p>
<p><strong>How to Fix:</strong></p>
<p><strong>1. Use Swift Compiler Optimizations</strong></p>
<p>Enable optimization flags that strip debugging symbols and make the binary harder to read:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// In your build settings:</span>
<span class="hljs-comment">// - Set "Optimization Level" to "-O" (or -Osize) for release builds</span>
<span class="hljs-comment">// - Enable "Strip Debug Symbols During Copy" = YES</span>
<span class="hljs-comment">// - Set "Strip Style" to "All Symbols"</span>
</code></pre>
<p>This removes function names and makes the compiled code less readable – though class/method names remain partially visible.</p>
<p><strong>2. Use Symbol Obfuscation Tools</strong></p>
<p>Tools like SwiftShield can rename your classes, methods, and properties to meaningless names:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Before obfuscation (readable to attackers):</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FeatureManager</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">isPremiumUser</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Bool</span> { ... }
}

<span class="hljs-comment">// After obfuscation (harder to understand):</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">a7f3b2</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">x9k2m</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Bool</span> { ... }
}
</code></pre>
<p>While this doesn't prevent reverse engineering, it makes it significantly harder for attackers to understand what the code does.</p>
<p><strong>3. Move Sensitive Logic to the Server (Best Practice)</strong></p>
<p>Instead of checking premium status locally, verify it server-side:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// ✅ Secure approach - Server validates everything</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FeatureManager</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">unlockPremiumFeature</span><span class="hljs-params">()</span></span> async {
        <span class="hljs-keyword">do</span> {
            <span class="hljs-comment">// Server checks if user truly has premium access</span>
            <span class="hljs-keyword">let</span> hasAccess = <span class="hljs-keyword">try</span> await backend.verifyPremiumAccess(userId: currentUserId)

            <span class="hljs-keyword">if</span> hasAccess {
                showPremiumContent()
            } <span class="hljs-keyword">else</span> {
                showPaywall()
            }
        } <span class="hljs-keyword">catch</span> {
            <span class="hljs-comment">// Handle error</span>
            showPaywall()
        }
    }
}
</code></pre>
<p><strong>How this works:</strong></p>
<p>Your backend maintains the source of truth about premium access. Even if an attacker reverse-engineers your app and tries to bypass the check, the server will reject unauthorized requests. The app becomes just a UI layer, while all critical decisions happen server-side – where attackers can't manipulate them.</p>
<p>The key principle is to assume your app code is public: never rely on client-side checks for security-critical operations like payments, access control, or authentication. Use obfuscation to make reverse engineering harder, but ultimately move sensitive logic to your secure backend</p>
<h3 id="heading-8-insecure-third-party-libraries">8. Insecure Third-Party Libraries</h3>
<p>Third-party libraries are at risk if they are hacked or outdated. Developers might inadvertently prioritize app functionality over potential security risks from dependencies, and <a target="_blank" href="https://airbyte.com/top-etl-tools-for-sources/etl-tools">ETL tools</a> can further help by streamlining the monitoring and processing of dependency-related data to identify vulnerabilities more efficiently.</p>
<p>On a broader scale, implementing strong data center security practices ensures that even if third-party components introduce risks, the underlying infrastructure remains resilient against attacks.</p>
<h4 id="heading-how-to-fix-5">How to Fix:</h4>
<ul>
<li><p>Use only high-quality, well-maintained libraries.</p>
</li>
<li><p>Update dependencies and monitor CVEs (Common Vulnerabilities and Exposures).</p>
</li>
<li><p>Audit library code if it handles sensitive data.</p>
</li>
</ul>
<h3 id="heading-9-insufficient-biometric-and-multi-factor-authentication">9. Insufficient Biometric and Multi-Factor Authentication</h3>
<p>Most applications rely on passwords alone, which are vulnerable to being hacked. Enabling biometrics like Face ID or Touch ID enhances security for users.</p>
<h4 id="heading-how-to-fix-6">How to Fix:</h4>
<ul>
<li><p>Tie LocalAuthentication framework for biometric authentication.</p>
</li>
<li><p>Combine biometrics with server-based authentication for multifactor authentication (MFA).</p>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> LocalAuthentication

<span class="hljs-keyword">let</span> context = <span class="hljs-type">LAContext</span>()

<span class="hljs-keyword">var</span> error: <span class="hljs-type">NSError?</span>

<span class="hljs-keyword">if</span> context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &amp;error) {

    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,

                        localizedReason: <span class="hljs-string">"Access your account"</span>) { success, authError <span class="hljs-keyword">in</span>

        <span class="hljs-type">DispatchQueue</span>.main.async {

         <span class="hljs-keyword">if</span> success {

                <span class="hljs-comment">// Proceed securely</span>

         } <span class="hljs-keyword">else</span> {

                <span class="hljs-comment">// Handle failure (authError may contain the reason)</span>

                <span class="hljs-built_in">print</span>(<span class="hljs-string">"Authentication failed: \(authError?.localizedDescription ?? "</span><span class="hljs-type">Unknown</span> error<span class="hljs-string">")"</span>)

         }

     }

}

} <span class="hljs-keyword">else</span> {

<span class="hljs-comment">// Biometrics not available, check error for details</span>

    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Biometrics unavailable: \(error?.localizedDescription ?? "</span><span class="hljs-type">Unknown</span> error<span class="hljs-string">")"</span>)

}
</code></pre>
<h3 id="heading-10-disregarding-periodic-security-testing">10. Disregarding Periodic Security Testing</h3>
<p>Apps, despite following best practices during development, often contain unexplored vulnerabilities that emerge from complex interactions, third-party dependencies, or newly discovered attack vectors. Regular security testing is absolutely essential to discover these vulnerabilities before attackers exploit them.</p>
<p>Security testing should happen at multiple stages, using accessible tools and practices:</p>
<ol>
<li><p><strong>Automated security scans:</strong> Run automatically with every build to catch common issues.</p>
</li>
<li><p><strong>Self-conducted code audits:</strong> Regular security-focused reviews of your own code using established guidelines.</p>
</li>
<li><p><strong>Vulnerability scanning tools:</strong> Use free tools like MobSF to analyze your app for security flaws.</p>
</li>
<li><p><strong>Dependency audits:</strong> Checking third-party libraries for known security vulnerabilities.</p>
</li>
</ol>
<p><strong>How to Fix:</strong></p>
<p><strong>1. Implement Automated Security Scans in CI/CD</strong></p>
<p>Integrate security scanning tools into your continuous integration pipeline so every code change is automatically checked:</p>
<pre><code class="lang-swift"># <span class="hljs-type">Example</span>: <span class="hljs-type">GitHub</span> <span class="hljs-type">Actions</span> workflow <span class="hljs-keyword">for</span> automated security scanning
name: <span class="hljs-type">Security</span> <span class="hljs-type">Scan</span>

on: [push, pull_request]

jobs:
  security-scan:
    runs-on: macos-latest

    steps:
      - name: <span class="hljs-type">Checkout</span> code
        uses: actions/checkout@v3

      - name: <span class="hljs-type">Run</span> <span class="hljs-type">MobSF</span> <span class="hljs-type">Security</span> <span class="hljs-type">Scan</span>
        run: |
          # <span class="hljs-type">Mobile</span> <span class="hljs-type">Security</span> <span class="hljs-type">Framework</span> - scans <span class="hljs-keyword">for</span> common vulnerabilities
          docker run -v $(pwd):/app opensecurity/mobile-security-framework-mobsf

      - name: <span class="hljs-type">Dependency</span> <span class="hljs-type">Vulnerability</span> <span class="hljs-type">Check</span>
        run: |
          # <span class="hljs-type">Check</span> <span class="hljs-type">CocoaPods</span>/<span class="hljs-type">SPM</span> dependencies <span class="hljs-keyword">for</span> known <span class="hljs-type">CVEs</span>
          brew install dependency-check
          dependency-check --scan ./<span class="hljs-type">Podfile</span>.lock --format <span class="hljs-type">JSON</span>

      - name: <span class="hljs-type">Secret</span> <span class="hljs-type">Detection</span>
        run: |
          # <span class="hljs-type">Detect</span> accidentally committed secrets
          brew install truffleHog
          truffleHog filesystem . --json

      - name: <span class="hljs-type">Fail</span> build on critical issues
        run: |
          <span class="hljs-keyword">if</span> grep -q <span class="hljs-string">"CRITICAL"</span> security-report.json; then
            echo <span class="hljs-string">"Critical security issues found!"</span>
            exit <span class="hljs-number">1</span>
          fi
</code></pre>
<p><strong>Automated scans check for:</strong></p>
<ul>
<li><p>Hardcoded API keys, tokens, or passwords</p>
</li>
<li><p>Insecure network configurations (allowing HTTP instead of HTTPS)</p>
</li>
<li><p>Weak cryptographic algorithms</p>
</li>
<li><p>Known vulnerabilities in third-party libraries</p>
</li>
<li><p>Improper SSL/TLS certificate validation</p>
</li>
<li><p>Insecure data storage (storing sensitive data in UserDefaults)</p>
</li>
<li><p>Excessive app permissions</p>
</li>
</ul>
<p><strong>Example output from an automated scan:</strong></p>
<pre><code class="lang-swift"><span class="hljs-type">Security</span> <span class="hljs-type">Scan</span> <span class="hljs-type">Results</span>:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[<span class="hljs-type">CRITICAL</span>] <span class="hljs-type">Hardcoded</span> <span class="hljs-type">API</span> <span class="hljs-type">Key</span> <span class="hljs-type">Found</span>
  <span class="hljs-type">File</span>: <span class="hljs-type">APIClient</span>.swift:<span class="hljs-number">15</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">API</span> key <span class="hljs-string">"sk_live_abc123..."</span> detected <span class="hljs-keyword">in</span> source code

[<span class="hljs-type">HIGH</span>] <span class="hljs-type">Insecure</span> <span class="hljs-type">HTTP</span> <span class="hljs-type">Connection</span>
  <span class="hljs-type">File</span>: <span class="hljs-type">NetworkManager</span>.swift:<span class="hljs-number">42</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">App</span> allows cleartext <span class="hljs-type">HTTP</span> traffic to api.example.com
  <span class="hljs-type">Fix</span>: <span class="hljs-type">Enforce</span> <span class="hljs-type">HTTPS</span> or add exception to <span class="hljs-type">Info</span>.plist <span class="hljs-keyword">if</span> <span class="hljs-keyword">required</span>

[<span class="hljs-type">MEDIUM</span>] <span class="hljs-type">Weak</span> <span class="hljs-type">Encryption</span> <span class="hljs-type">Algorithm</span>
  <span class="hljs-type">File</span>: <span class="hljs-type">DataEncryption</span>.swift:<span class="hljs-number">28</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">Using</span> <span class="hljs-type">MD5</span> <span class="hljs-keyword">for</span> hashing (cryptographically broken)
  <span class="hljs-type">Fix</span>: <span class="hljs-type">Use</span> <span class="hljs-type">SHA</span>-<span class="hljs-number">256</span> or better

[<span class="hljs-type">LOW</span>] <span class="hljs-type">Outdated</span> <span class="hljs-type">Dependency</span>
  <span class="hljs-type">Library</span>: <span class="hljs-type">Alamofire</span> <span class="hljs-number">4.2</span>.<span class="hljs-number">0</span>
  <span class="hljs-type">Issue</span>: <span class="hljs-type">Known</span> vulnerability <span class="hljs-type">CVE</span>-<span class="hljs-number">2021</span>-<span class="hljs-number">12345</span>
  <span class="hljs-type">Fix</span>: <span class="hljs-type">Update</span> to version <span class="hljs-number">5.6</span>.<span class="hljs-number">0</span> or later
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
<span class="hljs-type">Build</span> <span class="hljs-type">Failed</span>: <span class="hljs-number">2</span> critical issues must be fixed before deployment
</code></pre>
<p><strong>2. Use MobSF (Mobile Security Framework) for Vulnerability Analysis</strong></p>
<p>MobSF is a free, automated tool that analyzes your iOS app for security issues:</p>
<pre><code class="lang-swift"># <span class="hljs-type">Install</span> and run <span class="hljs-type">MobSF</span> locally
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p <span class="hljs-number">8000</span>:<span class="hljs-number">8000</span> opensecurity/mobile-security-framework-mobsf

# <span class="hljs-type">Upload</span> your .ipa file through the web interface at localhost:<span class="hljs-number">8000</span>
# <span class="hljs-type">MobSF</span> will analyze and provide a detailed security report
</code></pre>
<p>What MobSF checks:</p>
<ul>
<li><p>Binary analysis for hardcoded secrets</p>
</li>
<li><p>Insecure data storage patterns</p>
</li>
<li><p>Weak cryptographic implementations</p>
</li>
<li><p>Insecure network connections</p>
</li>
<li><p>Code quality and security best practices</p>
</li>
<li><p>Compliance with security standards</p>
</li>
</ul>
<p><strong>3. Conduct Regular Code Audits Using OWASP MSTG</strong></p>
<p>Use the OWASP Mobile Security Testing Guide as a checklist to audit your own code:</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Example: Following OWASP MSTG recommendations for secure storage</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureStorage</span> </span>{
    <span class="hljs-comment">// ❌ Insecure - UserDefaults is not encrypted</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">saveTokenInsecurely</span><span class="hljs-params">(<span class="hljs-number">_</span> token: String)</span></span> {
        <span class="hljs-type">UserDefaults</span>.standard.<span class="hljs-keyword">set</span>(token, forKey: <span class="hljs-string">"authToken"</span>)
    }

    <span class="hljs-comment">// ✅ Secure - Using Keychain as OWASP recommends</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">saveTokenSecurely</span><span class="hljs-params">(<span class="hljs-number">_</span> token: String)</span></span> <span class="hljs-keyword">throws</span> {
        <span class="hljs-keyword">let</span> data = token.data(using: .utf8)!
        <span class="hljs-keyword">let</span> query: [<span class="hljs-type">String</span>: <span class="hljs-type">Any</span>] = [
            kSecClass <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecClassGenericPassword,
            kSecAttrAccount <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: <span class="hljs-string">"authToken"</span>,
            kSecValueData <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: data,
            kSecAttrAccessible <span class="hljs-keyword">as</span> <span class="hljs-type">String</span>: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
        ]

        <span class="hljs-type">SecItemDelete</span>(query <span class="hljs-keyword">as</span> <span class="hljs-type">CFDictionary</span>)
        <span class="hljs-keyword">let</span> status = <span class="hljs-type">SecItemAdd</span>(query <span class="hljs-keyword">as</span> <span class="hljs-type">CFDictionary</span>, <span class="hljs-literal">nil</span>)

        <span class="hljs-keyword">guard</span> status == errSecSuccess <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">throw</span> <span class="hljs-type">StorageError</span>.saveFailed
        }
    }
}
</code></pre>
<p><strong>OWASP MSTG Checklist for Self-Audit:</strong></p>
<ul>
<li><p>[ ] Are all sensitive data encrypted at rest?</p>
</li>
<li><p>[ ] Is HTTPS enforced for all network calls?</p>
</li>
<li><p>[ ] Are certificates properly validated?</p>
</li>
<li><p>[ ] Is sensitive data excluded from logs?</p>
</li>
<li><p>[ ] Are API keys and secrets not hardcoded?</p>
</li>
<li><p>[ ] Is user input validated and sanitized?</p>
</li>
<li><p>[ ] Are authentication tokens stored securely in Keychain?</p>
</li>
</ul>
<p><strong>4. Automated Dependency Scanning</strong></p>
<p>Monitor your dependencies continuously for newly discovered vulnerabilities:</p>
<pre><code class="lang-swift"># <span class="hljs-type">For</span> <span class="hljs-type">CocoaPods</span> projects
gem install cocoapods-audit
pod audit

# <span class="hljs-type">For</span> <span class="hljs-type">Swift</span> <span class="hljs-type">Package</span> <span class="hljs-type">Manager</span>
# <span class="hljs-type">Use</span> <span class="hljs-type">GitHub</span> <span class="hljs-type">Dependabot</span> (free <span class="hljs-keyword">for</span> <span class="hljs-keyword">public</span> repos) or
brew install swift-outdated
swift-outdated
</code></pre>
<p>And set up automated alerts with these tools:</p>
<ul>
<li><p><strong>GitHub Dependabot:</strong> Automatically creates PRs when vulnerable dependencies are detected (free)</p>
</li>
<li><p><strong>Snyk</strong>: Free tier available for open-source projects</p>
</li>
<li><p><strong>OWASP Dependency-Check:</strong> Free command-line tool</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Developing secure iOS apps using Swift is all about forward-thinking. You should do all you can to avoid these common errors, like insecure storage of data, poor network communication, hard-coded secrets, or poor authentication.</p>
<p>Using Keychain for confidential information, requiring HTTPS, input validation, and multifactor authentication are all steps that decrease risk.</p>
<p>Regular testing for security vulnerabilities and limiting third-party library use can also further enhance your app's security.</p>
<p>Security is a continuous responsibility. Swift provides tools, but the developers need to apply those tools carefully. Security being tackled right from the start protects users' information, creates trust, and protects the reputation of the application.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Google Dorking: How to Find Hidden Information on the Web ]]>
                </title>
                <description>
                    <![CDATA[ Let’s learn how to find hidden information online by using advanced search operators on Google. The internet holds vast amounts of information. Much of this information is accessible through Google. But did you know you can use Google in ways beyond ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/google-dorking-how-to-find-hidden-information-on-the-web/</link>
                <guid isPermaLink="false">671bf3858ac006ad747be97f</guid>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ethicalhacking ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #cybersecurity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Fri, 25 Oct 2024 19:37:41 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729872503418/1e5921bc-52ba-4410-86a3-5e96a2c22405.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let’s learn how to find hidden information online by using advanced search operators on Google.</p>
<p>The internet holds vast amounts of information. Much of this information is accessible through Google.</p>
<p>But did you know you can use Google in ways beyond simple searches? There’s a method called “Google Dorking” that lets you do this.</p>
<p>Google Dorking helps you find hidden or overlooked data on websites. It uses advanced search operators to locate hidden files, sensitive data, and more.</p>
<p>Google Dorking allows us to be very specific with our searches. Instead of just typing in regular keywords, we combine them with operators. These operators help Google narrow down its search results.</p>
<p>Before we dive in, a word of caution. While Google Dorking can be a powerful tool for research or cybersecurity testing, it also carries some risks. Using it for unauthorized access to secure information is illegal. So use it safely and correctly!</p>
<p>Now let’s learn how to “dork” Google.</p>
<h1 id="heading-google-dorking-operators"><strong>Google Dorking Operators</strong></h1>
<p>Here’s a list of every common Google Dorking operator along with its purpose.</p>
<h3 id="heading-site"><strong>Site</strong></h3>
<p>Restricts search results to a specific domain or website. Example: <code>site:</code><a target="_blank" href="http://example.com"><code>example.com</code></a> will show results only from that site.</p>
<h3 id="heading-intitle"><strong>InTitle</strong></h3>
<p>Searches for pages with a specific word or phrase in the page title. Example: <code>intitle:login</code> will find pages with "login" in the title.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729872545025/c2c88f8b-d14c-4da4-91f5-78ea9d87fb48.jpeg" alt="InTitle results" class="image--center mx-auto" width="1100" height="468" loading="lazy"></p>
<h3 id="heading-inurl"><strong>InURL</strong></h3>
<p>The <code>inurl</code> operator is used to find specific words within the URL structure of web pages. It can help locate pages with particular keywords embedded in their web address.</p>
<p>For example, using <code>inurl:login</code> with other terms like <code>inurl:customer</code> or <code>inurl:secure</code> can reveal login pages for different sites.</p>
<p>An example of its use is <code>inurl:</code><a target="_blank" href="http://admin.It"><code>admin</code></a>. This displays URLs containing “admin,” often leading to administrative or management pages.</p>
<p>For more advanced searches, <code>inurl:pho?id=</code> can be useful to identify sites that might be vulnerable to SQL injection. URLs structured this way often include database query strings.</p>
<h3 id="heading-filetype"><strong>FileType</strong></h3>
<p>The <code>filetype</code> operator enables users to search for documents with a specific file extension. This includes extensions like PDF, DOC, or XLS.</p>
<p>The <code>filetype</code> operator makes it helpful for locating publicly accessible reports, presentations, and documents. For instance, <code>filetype:pdf financial report</code> finds PDF files related to financial reporting.</p>
<p>Combining <code>filetype</code> with certain keywords allows for more targeted searches. For example, searching <code>filetype:xlsx budget</code> could find Excel files related to budget details.</p>
<p><code>filetype:docx confidential</code> might reveal DOCX documents containing potentially sensitive terms like “confidential,” leading to internal-use files that may be accessible publicly.</p>
<h3 id="heading-cache"><strong>Cache</strong></h3>
<p>Shows Google’s cached version of a webpage, even if it’s been removed. Example: <code>cache:</code><a target="_blank" href="http://example.com"><code>example.com</code></a> shows the cached version of that page.</p>
<h3 id="heading-allintext"><strong>AllInText</strong></h3>
<p>Searches for pages that contain all the specified words in the body text. Example: <code>allintext:"username password"</code> will return pages with both words in the text.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729872601325/87fbbd02-d5b0-43c0-9893-cef035927711.jpeg" alt="All in text results" class="image--center mx-auto" width="1100" height="827" loading="lazy"></p>
<h3 id="heading-allintitle"><strong>AllInTitle</strong></h3>
<p>Searches for pages with all specified words in the title. Example: <code>allintitle:login admin</code> finds pages with both words in the title.</p>
<h3 id="heading-allinurl"><strong>AllInUrl</strong></h3>
<p>Searches for pages with multiple specified words in the URL. Example: <code>allinurl:admin login</code> finds URLs that contain both "admin" and "login."</p>
<h3 id="heading-inanchor"><strong>InAnchor</strong></h3>
<p>Finds pages with specific text in anchor links (the clickable text of a link). Example: <code>inanchor:"click here"</code> finds links where the clickable text is "click here."</p>
<h3 id="heading-before-and-after"><strong>Before and After</strong></h3>
<p>Finds pages published before or after a specific date. Example: <code>before:2020</code> will find pages published before 2020. <code>after:2020</code> will find pages published after 2020.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729872642187/5e3a17ca-c428-4711-82d8-c904182d1d58.jpeg" alt="Before and after results" class="image--center mx-auto" width="1100" height="645" loading="lazy"></p>
<h3 id="heading-or"><strong>OR</strong></h3>
<p>Combines two search terms and returns results containing either of them. Example: <code>admin OR login</code> shows pages with either "admin" or "login."</p>
<h3 id="heading-minus"><strong>Minus (-)</strong></h3>
<p>Excludes specific words from the search results. Example: <code>admin -login</code> shows pages with “admin” but without “login.”</p>
<h3 id="heading-asterisk"><strong>Asterisk (*)</strong></h3>
<p>Acts as a wildcard to substitute any word or phrase. Example: <code>"admin * login"</code> will find pages with any word between "admin" and "login."</p>
<h3 id="heading-intext"><strong>InText</strong></h3>
<p>Searches for specific words in the main body of the page, not just titles or URLs. Example: <code>intext:"confidential"</code> finds pages where "confidential" appears in the content.</p>
<h3 id="heading-location"><strong>Location</strong></h3>
<p>Restricts results to a specific geographical location. Example: <code>location:USA</code> shows results focused on the USA.</p>
<h2 id="heading-how-to-protect-yourself-from-google-dorking"><strong>How to Protect Yourself from Google Dorking</strong></h2>
<p>If you own a website or manage sensitive information online, understanding Google Dorking can help you secure your data. Here are some steps you can take to protect yourself:</p>
<ol>
<li><p><strong>Use Robots.txt Files</strong> The robots.txt file on a website tells search engines what content they shouldn’t index. Make sure that sensitive web pages or files are protected from being indexed by Google.</p>
</li>
<li><p><strong>Use Password Protection</strong> If certain parts of your website are sensitive, use password protection. Google can’t access password-protected content, so it won’t show up in search results.</p>
</li>
<li><p><strong>Avoid Storing Sensitive Files Publicly</strong> Do not store sensitive information like database backups, configuration files, or email lists on publicly accessible parts of your server.</p>
</li>
<li><p><strong>Regularly Check for Exposed Information</strong> Use your own Google Dorking searches to see if sensitive files are showing up on Google. This can help you catch and secure information before anyone else finds it.</p>
</li>
<li><p><strong>Use Web Vulnerability Scanners</strong> Tools like OWASP ZAP or Burp Suite can help you scan your own site for exposed data. These tools may catch things that you might overlook manually.</p>
</li>
</ol>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Google Dorking can be both helpful and dangerous, depending on how you use it. On one hand, it lets you uncover hidden information and refine your search skills. On the other, it can expose sensitive data if used irresponsibly.</p>
<p>Understanding the techniques of Google Dorking can make you a better internet user and help you secure your own data.</p>
<p>To learn how to hack machines in the real world, join our private community <a target="_blank" href="https://www.skool.com/hackershub">Hacker's Hub.</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Prevent Web API Attacks with Data Validation – Web API Security Guide ]]>
                </title>
                <description>
                    <![CDATA[ Adequate data protection and user confidentiality are key responsibilities for web developers. Hence, it is important to ensure the highest possible security while building API endpoints. The act of application security is a shared responsibility amo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/web-api-security-guide/</link>
                <guid isPermaLink="false">66bb58d7965d5c9ed5487ba4</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Validation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 03 Apr 2024 09:13:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/apidat.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Adequate data protection and user confidentiality are key responsibilities for web developers. Hence, it is important to ensure the highest possible security while building API endpoints.</p>
<p>The act of application security is a shared responsibility amongst the client and server developers and negligence of one’s role can be disastrous. <a target="_blank" href="https://www.statista.com/statistics/1307426/number-of-data-breaches-worldwide/#:~:text=During%20the%20fourth%20quarter%20of,concerns%20of%20company%20leaders%20worldwide.">Statistics</a> show that data breaches in 2023 resulted in exposure of over 8 million data records worldwide.</p>
<p>In this article, I'll be highlighting key areas of API security, which involves data validation.  This concept is quite crucial in helping you protect your API from web attacks via malicious user data. This tutorial is well-suited for all backend developers regardless of years of experience.</p>
<p>To be able to follow this tutorial, here are some prerequisites:</p>
<ul>
<li>Knowledge of Node.js</li>
<li>Knowledge of npm and package installation</li>
</ul>
<p>With that in place, let’s get started.</p>
<h2 id="heading-how-does-data-validation-work">How Does Data Validation Work?</h2>
<p>First of all, what is data validation? Data validation simply entails ensuring the accuracy and reliability of the data received from external sources before onward data processing. </p>
<p>It is a key component of web API security as it is essential for preventing the occurrence of web injection attacks, SQL attacks and NoSQL attacks. To know more about these, you can check this <a target="_blank" href="https://owasp.org/www-community/Injection_Flaws#:~:text=Description,connected%20to%20the%20vulnerable%20application.">link</a>.</p>
<p>Note that data validation is needed but not limited to the following backend operations.:</p>
<ul>
<li>User login and sign up</li>
<li>Response query</li>
<li>Updating server databases</li>
</ul>
<p>All these can be used as avenues by mischievous black hat hackers to gain access to the server database and obtain sensitive user details or even wreak havoc by formatting the entire database.</p>
<h2 id="heading-popular-data-validation-tools">Popular Data Validation Tools</h2>
<p>So far, there are lot of tools that can help the programmer achieve efficient data validation in API development. </p>
<p>They help you avoid reinventing the wheel of using long regex code to validate data. They provide a whole lot of features, including error handling and validation customization functionalities.  </p>
<p>Some of these tools include:<br>•    <a target="_blank" href="https://joi.dev">Joi</a><br>•    <a target="_blank" href="https://zod.dev/">Zod</a><br>•    <a target="_blank" href="https://www.npmjs.com/package/yup">Yup</a><br>•    <a target="_blank" href="https://ajv.js.org/">AJv</a><br>•    <a target="_blank" href="https://valibot.dev/">Valibot</a><br>•    <a target="_blank" href="https://www.npmjs.com/package/validatorjs">Validator.js</a><br>•    <a target="_blank" href="https://docs.superstructjs.org/guides/02-validating-data">Superstruct</a></p>
<p>To further shed light on these tools, we'll compare some of the most popular data validation tools mentioned above.</p>
<h2 id="heading-pros-and-cons-of-data-validation-tools">Pros and Cons of Data Validation Tools</h2>
<p>To further enlighten you about these JavaScript validation tools, I will be highlighting some pros and cons of three of these popular JavaScript validation tools.</p>
<h3 id="heading-joi">Joi</h3>
<h6 id="heading-pros">Pros</h6>
<ul>
<li>It has a strong, large user community and development support</li>
<li>It has built-in capabilities to handle complex validations</li>
</ul>
<h6 id="heading-cons">Cons</h6>
<ul>
<li>It’s syntax is quite verbose</li>
</ul>
<h3 id="heading-zod">Zod</h3>
<h6 id="heading-pros-1">Pros</h6>
<ul>
<li>It is easily compatible with Typescript projects</li>
<li>It has efficient error-handling capabilities</li>
</ul>
<h6 id="heading-cons-1">Cons</h6>
<ul>
<li>Async validation isn’t supported.</li>
</ul>
<h3 id="heading-yup">Yup</h3>
<h6 id="heading-pros-2">Pros</h6>
<ul>
<li>It mainly uses declarative syntax to set its validation tool which confers its simplicity</li>
<li>It has a comparable fast performance.</li>
</ul>
<h6 id="heading-cons-2">Cons</h6>
<ul>
<li>It doesn’t provide customization features</li>
<li>It has limited ability to handle complex validations</li>
</ul>
<p>For the purpose of this tutorial, we'll use Joi as our data validation tool.</p>
<h2 id="heading-introduction-to-joi">Introduction to Joi</h2>
<p>Joi is a simple and efficient JavaScript-based data validation tool that is based on the schema-type configuration.</p>
<p>It has built-in capabilities for validating the occurrence of data in various forms, but not limited to Booleans, strings, functions and intervals. It can also handle complex validation operations.</p>
<p>Additionally, it provides minimal caching functionalities. More information about the tool can be found <a target="_blank" href="https://joi.dev/api/?v=17.12.2">here</a>.</p>
<h2 id="heading-how-to-set-up-joi">How to Set Up Joi</h2>
<p>In this section, we'll set up Joi in our local environment. To install Joi, navigate to the code folder via the command line and run this:</p>
<pre><code class="lang-bash">npm i joi
</code></pre>
<p>A message confirming successful installation should be displayed. With that completed, we can demonstrate the power of Joi in validating user registration in our demo API.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<p>In this project, you'll use Joi to validate the input received from the client with the intent to sign up on the server. The default code for the user sign-up function for the Node.js application can be found <a target="_blank" href="https://github.com/oluwatobi2001/location-backend/blob/master/Controller/Authentication.js">here</a>.</p>
<p>Go on and import the installed Joi package into your code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Joi = <span class="hljs-built_in">require</span>(<span class="hljs-string">"joi"</span>);
</code></pre>
<p>Before writing our signup controller, we'll initialize the Joi library within the code file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> SignUpSchema = Joi.object({});
</code></pre>
<p>In this project, we'll validate the email, password and username parameters received from the client.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> SignUpSchema = Joi.object({
    <span class="hljs-attr">email</span>: Joi.string().email({
        <span class="hljs-attr">minDomainSegments</span>: <span class="hljs-number">2</span>,
        <span class="hljs-attr">tlds</span>: {
            <span class="hljs-attr">allow</span>: [<span class="hljs-string">'com'</span>, <span class="hljs-string">'net'</span>]
        }
    }),
    <span class="hljs-attr">username</span>: Joi.string().alphanum().min(<span class="hljs-number">3</span>).max(<span class="hljs-number">15</span>).required(),
    <span class="hljs-attr">password</span>: Joi.string().min(<span class="hljs-number">8</span>).required()
});
</code></pre>
<p>The email parameter object ensures that the email address is a string, and the domain site is limited to .com and .net, disallowing other forms of domains.</p>
<p>For the username parameter, it ensures that it is a string containing both letters and numbers with a minimum character count of 3 and a maximum character count of 15. The required function ensures that these conditions must be met or the entire request won't be validated.</p>
<p>The password parameter ensures that the password supplied is in a string format with a minimum character count of 8, and it is also required.</p>
<p>To apply it to our endpoints, we include this within the controller function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { error, value } = SignUpSchema.validate(req.body, { <span class="hljs-attr">abortEarly</span>: <span class="hljs-literal">false</span> });
<span class="hljs-keyword">if</span> (error) {
    res.status(<span class="hljs-number">400</span>).json(error.details);
    <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>This function gets executed before inserting the user details into the database. The schema tries to validate the received input and then proceeds to the database if successfully validated.</p>
<p>The <code>abortEarly</code> feature is included to allow for all parameters to be assessed. All the errors will be displayed if there is any.</p>
<p>The above can also be replicated in the Login controller function. You can also check out the <a target="_blank" href="https://joi.dev/api/?v=17.12.2">documentation</a> for other examples of complex validation options using Joi.</p>
<p>The final code for the project is displayed below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">"jsonwebtoken"</span>);
<span class="hljs-keyword">const</span> userSchema = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../Schema/User"</span>);
<span class="hljs-keyword">const</span> Joi = <span class="hljs-built_in">require</span>(<span class="hljs-string">"joi"</span>);
<span class="hljs-keyword">const</span> bcrypt = <span class="hljs-built_in">require</span>(<span class="hljs-string">"bcrypt"</span>);
<span class="hljs-keyword">const</span> { createNewColumn, checkRecordsExists, insertRecord } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../utils/sqlSchemaFunction'</span>);

<span class="hljs-keyword">const</span> generateAccessToken = <span class="hljs-function">(<span class="hljs-params">use</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> jwt.sign({ <span class="hljs-attr">userID</span>: use }, process.env.JWT, { <span class="hljs-attr">expiresIn</span>: <span class="hljs-string">"1d"</span> });
}

<span class="hljs-keyword">const</span> SignUpSchema = Joi.object({
    <span class="hljs-attr">email</span>: Joi.string().email({ <span class="hljs-attr">minDomainSegments</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">tlds</span>: { <span class="hljs-attr">allow</span>: [<span class="hljs-string">'com'</span>, <span class="hljs-string">'net'</span>] } }),
    <span class="hljs-attr">username</span>: Joi.string().alphanum().min(<span class="hljs-number">3</span>).max(<span class="hljs-number">15</span>).required(),
    <span class="hljs-attr">password</span>: Joi.string().min(<span class="hljs-number">8</span>).required()
});

<span class="hljs-keyword">const</span> loginSchema = Joi.object({
    <span class="hljs-attr">email</span>: Joi.string().email({ <span class="hljs-attr">minDomainSegments</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">tlds</span>: { <span class="hljs-attr">allow</span>: [<span class="hljs-string">'com'</span>, <span class="hljs-string">'net'</span>] } }),
    <span class="hljs-attr">password</span>: Joi.string().min(<span class="hljs-number">8</span>).required()
});

<span class="hljs-keyword">const</span> register = <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> email = req.body.email;
    <span class="hljs-keyword">const</span> password = req.body.password;

    <span class="hljs-keyword">if</span> (!email || !password) {
        res.status(<span class="hljs-number">400</span>).json(<span class="hljs-string">"Please supply the email or password"</span>);
        <span class="hljs-keyword">return</span>; 
    }

    <span class="hljs-keyword">const</span> { error, value } = SignUpSchema.validate(req.body, { <span class="hljs-attr">abortEarly</span>: <span class="hljs-literal">false</span> });
    <span class="hljs-keyword">if</span> (error) {
        res.status(<span class="hljs-number">400</span>).json(error.details);
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> salt = <span class="hljs-keyword">await</span> bcrypt.genSalt(<span class="hljs-number">10</span>);
    <span class="hljs-keyword">const</span> hashedPassword = <span class="hljs-keyword">await</span> bcrypt.hash(password, salt);
    <span class="hljs-keyword">const</span> user = {
        <span class="hljs-attr">username</span>: req.body.username,
        <span class="hljs-attr">email</span>: email,
        <span class="hljs-attr">password</span>: hashedPassword
    };

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> userAlreadyExists = <span class="hljs-keyword">await</span> checkRecordsExists(<span class="hljs-string">"users"</span>, <span class="hljs-string">"email"</span>, email);
        <span class="hljs-keyword">if</span> (userAlreadyExists) {
            res.status(<span class="hljs-number">400</span>).json(<span class="hljs-string">"Email must be unique"</span>);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">await</span> insertRecord(<span class="hljs-string">"users"</span>, user);
            res.status(<span class="hljs-number">200</span>).json(<span class="hljs-string">"User created successfully"</span>);
        }
    } <span class="hljs-keyword">catch</span> (err) {
        res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">err</span>: err.message });
    }
};

<span class="hljs-built_in">module</span>.exports = { register };
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/SUccessValid-1.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>API testing in Postman</em></p>
<p>Ensuring that the code followed our defined schema resulted in it being successfully executed.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. I hope you’ve learned about data validation, various data validation tools and data validation best practices.</p>
<p>You can also reach out to me and check out my other articles <a target="_blank" href="https://www.freecodecamp.org/news/author/oluwatobi/">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Tabnabbing and How to Prevent it ]]>
                </title>
                <description>
                    <![CDATA[ Sometimes when you're building a website, you may need a link to open in a new tab. What you might not realize, though, is that doing so could leave your users vulnerable to malicious attacks via a practice called "tabnabbing". And while nothing is f... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-tabnabbing/</link>
                <guid isPermaLink="false">66d45f62d1ffc3d3eb89de04</guid>
                
                    <category>
                        <![CDATA[ HTML ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Juanita Washington ]]>
                </dc:creator>
                <pubDate>Mon, 16 Oct 2023 22:56:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/Tab-pg-6.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Sometimes when you're building a website, you may need a link to open in a new tab. What you might not realize, though, is that doing so could leave your users vulnerable to malicious attacks via a practice called "tabnabbing".</p>
<p>And while nothing is foolproof, there is a way to at least mitigate the effects: using the <code>noopener</code> and <code>noreferrer</code> attributes. And that's what you'll learn about in this quick tutorial.</p>
<h2 id="heading-what-is-tabnabbing">What is Tabnabbing?</h2>
<p>Tabnabbing is a type of phishing attack that targets the inactive tabs in your browser. While you're focused on your current tab, the link to the previous one can be hijacked, and you'll be redirected from the intended site to a malicious one resembling the real thing.</p>
<p>Since the malicious site looks very similar to the original, the user is typically unaware that the page they're on isn't legit once they return to that tab. Because of this, the user puts in their personal information, not knowing someone's on the other side waiting to steal it.</p>
<p>Some ways attackers might compromise a well-known website include:</p>
<ul>
<li><p>malicious ads</p>
</li>
<li><p>3rd party widgets that the website has included, which were later compromised</p>
</li>
<li><p>malicious user-generated content (like forum posts) that contain unsanitized JavaScript</p>
</li>
</ul>
<h3 id="heading-a-quick-example-of-tabnabbing">A Quick Example of Tabnabbing</h3>
<p>Think of how a website with your personal details logs you out automatically when you're inactive for too long. Since that means your attention's elsewhere, the attacker can switch out the real page for a very convincing fake.</p>
<p>When you go back to that tab, you wouldn't know the difference, so you log back in, and the phisher now has access to your private details.</p>
<p>As is the case for phishing attacks, the purpose of this action is to deceive the unsuspecting user into entering sensitive information (usually login or financial info) on the phony site.</p>
<p>This is, of course, a problem you'll want to avoid for your site when visitors come! You'll want to make sure people are safe when clicking any of your links, right?</p>
<p>So now you're going to learn how to make your corner of the internet a little bit safer—starting with learning how to open a new tab to begin with.</p>
<h2 id="heading-how-to-open-a-link-in-a-new-tab-in-html">How to Open a Link in a New Tab in HTML</h2>
<p>To open a link in a new tab, write out a link how you would in HTML, then just add the target attribute, setting the value to blank, like this: <code>target="_blank"</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Learn to code for free at <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span> =<span class="hljs-string">"https://www.freecodecamp.org/"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span>freeCodeCamp.org!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">p</span>/&gt;</span>
</code></pre>
<p>On the page, it would look like this:</p>
<p>Learn to code for free at <a target="_blank" href="https://www.freecodecamp.org/">freeCodeCamp.org!</a></p>
<h2 id="heading-how-to-add-a-noopenernoreferrer-attribute">How to Add a <code>Noopener</code>/<code>Noreferrer</code> Attribute</h2>
<p>Unfortunately, the more tabs you have open (who doesn't multitask on their browser?), the more susceptible you are to tabnabbing. This is because the longer a tab stays inactive, the higher the chance a phisher can strike, swapping the real page with a fake.</p>
<p>So, how do you prevent this? By adding <code>rel="noopener noreferrer"</code> to your anchor, like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Learn to code for free at <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span> =<span class="hljs-string">"https://www.freecodecamp.org/"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"noopener noreferrer"</span>&gt;</span>freeCodeCamp.org!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">p</span>/&gt;</span>
</code></pre>
<h3 id="heading-why-use-noopener-and-noreferrer">Why use <code>noopener</code> and <code>noreferrer</code>?</h3>
<p>Using <code>noopener</code> prevents bad actors and links from accessing the previous tab or window that opened the current one. This is done by setting the <code>Window.opener()</code> property to null.</p>
<p>Adding <code>noreferrer</code> prevents external sites from knowing that you've linked to them, which means your traffic data won't be sent their way.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>You should now have an understanding of what tabnabbing is and how protect your links (and users) against it. Hope you found this helpful and best of luck to you!</p>
<p>If you have indeed found this helpful, I have more tech articles on my <a target="_blank" href="https://jwashingtondev.hashnode.dev/">blog</a>. If you want to connect, I'm on <a target="_blank" href="https://www.linkedin.com/in/juanita-washington-freelance-writer-web-developer-saas-tech/">linkedin</a>!</p>
<p>If you want to read more about all this, here are some resources:</p>
<ol>
<li><p><a target="_blank" href="https://easydmarc.com/blog/what-is-tabnabbing-and-how-it-works/">EASYDMARC - What is Tabnabbing and how it works</a></p>
</li>
<li><p><a target="_blank" href="https://www.elegantthemes.com/blog/wordpress/rel-noopener-noreferrer-nofollow">Elegant Themes - What is the "noopener noreferrer" tag and what does it mean?</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/opener">MDN - the Window.opener() property</a></p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Web Security in Django – How to Build a Secure Web Application ]]>
                </title>
                <description>
                    <![CDATA[ By Jacob Isah  Web security is an important aspect of the web application development process. Especially as more data is stored, managed, and shared.  As a web developer, it's essential to prioritize security measures to protect your company’s users... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-secure-django-web-app/</link>
                <guid isPermaLink="false">66d45f3347a8245f78752a4a</guid>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 31 Aug 2023 18:52:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/Web-Security-in-Django---How-to-Build-a-Secure-Web-Application.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jacob Isah </p>
<p>Web security is an important aspect of the web application development process. Especially as more data is stored, managed, and shared. </p>
<p>As a web developer, it's essential to prioritize security measures to protect your company’s users and data from potential threats.   </p>
<p>In this article, I will demonstrate web security best practices by building a secure web application using Django, a powerful Python web framework. I'll cover password hashing, secure session management, authentication, authorization, and other key security considerations with accompanying code examples.  </p>
<p>Before continuing with this article, keep in mind that this isn't intended for absolute beginners. You should have a good understanding of Python to get the most out of this guide. </p>
<p>If you need to brush up on your basic programming skills in Python and Django before continuing, here are a couple resources to help you out:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/python-for-everybody/">Python for Everybody</a> from Dr. Chuck</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/django-for-everybody-learn-the-popular-python-framework-from-dr-chuck/">Django for Everybody</a>, also from Dr. Chuck</li>
</ul>
<p>You will get access to the code at the end of the article.</p>
<h2 id="heading-set-up-your-file-structure">Set Up Your File Structure</h2>
<p>Let's say that we want to store our project on the desktop. The first thing do is to set up our file structure. Let's start by creating a root directory for our project on the desktop (<code>WebSec</code> in this case).</p>
<pre><code class="lang-python">mkdir WebSec
cd WebSec
</code></pre>
<h3 id="heading-create-a-virtual-environment-and-activate-it">Create a Virtual Environment and Activate It</h3>
<p>On Linux (Ubuntu):</p>
<pre><code class="lang-python">python3 -m venv my_env

Source my_env/bin/activate
</code></pre>
<p>And on Windows:</p>
<pre><code class="lang-python">python -m venv my_env

my_env\Scripts\activate.bat
</code></pre>
<h2 id="heading-how-to-create-the-django-project">How to Create the Django Project</h2>
<p>First, if you don't already have it, you'll need to install Django using the following command:</p>
<pre><code class="lang-python">python -m pip install Django
</code></pre>
<p>Then you can use this command to create the project:</p>
<pre><code class="lang-python">django-admin startproject web_sec_project .
</code></pre>
<p>And finally, use this command to create the app:</p>
<pre><code class="lang-python">django-admin startapp web_sec_app
</code></pre>
<p>Your file structure should look like this at the end:</p>
<pre><code class="lang-python">WebSec
    my_env/
    web_sec_app/
        __pycache__/
        migrations/
        templates/
        admin.py
        apps.py
        forms.py
        models.py
        tests.py
        urls.py
        views.py
    web_sec_project/
        __pycache__/
        __init__.py
        asgi.py
        settings.py
        urls.py
        wsgi.py
    db.sqlite3
    manage.py
</code></pre>
<h3 id="heading-run-your-server">Run Your Server</h3>
<p>On your IDE terminal run the following command and test if your project is working. If so, you are good to go.</p>
<pre><code class="lang-python">python manage.py runserver
</code></pre>
<p>Ensure that you add your app to your project:</p>
<p><img src="https://lh4.googleusercontent.com/5KMFSFkkzM4T-YPujI0_9tm6FdnoTQRfJ8FbfVAZfChJfnkLRjvOSnyfq3PzIiLLWr-h-r5_mw9OOk55yJtXJ4OOjhu0wIwKiTiX5T_-7TN-oHt4elagFQ_st3mAxFHU-bWlR3JCcpcdn6b1BGgVSg" alt="Image" width="1203" height="472" loading="lazy">
<em>Check that your app is added</em></p>
<p>Now let’s start building and implementing web security.</p>
<h2 id="heading-password-hashing">Password Hashing</h2>
<p>The first line of defense when implementing web security is ensuring that user passwords are properly protected. And instead of storing passwords in plaintext, it's a good idea to hash them. We'll use cryptographic hashing to safeguard sensitive user information. </p>
<p>Cryptographic hashing, also known as hash functions or hash algorithms, is a fundamental concept in cryptography and computer security. It involves taking an input (or "message") and transforming it into a fixed-size string of characters, which is typically a sequence of numbers and letters. This output is called the "hash value" or "hash code."</p>
<p>Django provides a secure password hashing mechanism by default, using the <strong>PBKDF2</strong> algorithm with a <strong>SHA-256</strong> hash. </p>
<p>Django uses a robust and secure password hashing mechanism to protect user passwords. This mechanism helps ensure that even if the database is compromised, attackers cannot easily retrieve users' plaintext passwords. Django's password hashing mechanism consists of <strong>PBKDF2.</strong></p>
<p><strong>PBKDF2</strong> is a simple cryptographic key derivation function that is resistant to <a target="_blank" href="https://en.wikipedia.org/wiki/Dictionary_attack">dictionary attacks</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Rainbow_table">rainbow table attacks</a>. It is based on iteratively deriving <strong>HMAC</strong> many times with some padding. This ensures that even if the database is compromised, the passwords remain unreadable.</p>
<p>To demonstrate this, we are going to create a new user with a hashed password and save the user with their hashed password in the database.</p>
<p>First, we import the <code>User</code>  from the User model. Then, we import <code>make_password</code>. Here's the code to do that:</p>
<pre><code class="lang-python"><span class="hljs-comment">#web_sec_app/views.py</span>

<span class="hljs-keyword">from</span> django.contrib.auth.hashers <span class="hljs-keyword">import</span> make_password
<span class="hljs-keyword">from</span> django.contrib.auth.models <span class="hljs-keyword">import</span> User

<span class="hljs-comment"># Create User views here.</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">UserView</span>(<span class="hljs-params">request</span>):</span>
    users = User.objects.all()
    password = <span class="hljs-string">'password'</span>
    hashed_password = make_password(password)
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'create_user.html'</span>, 
                {<span class="hljs-string">'users'</span>: users, <span class="hljs-string">'hashed_password'</span>: hashed_password})
</code></pre>
<h2 id="heading-secure-session-management">Secure Session Management</h2>
<p>Session management is key to maintaining user state across multiple requests. Django comes with a built-in session management system that stores session data on the server-side. We'll ensure that the session data is encrypted and the session ID is secure to prevent session hijacking attacks.</p>
<p>To achieve secure session management, we will make sure we have a secure session cookie, which will require HTTPS. We are also going to prevent <code>JavaScript</code> access to the session cookie. The session expires when the browser is closed.</p>
<pre><code class="lang-python">SESSION_COOKIE_SECURE = <span class="hljs-literal">True</span>
</code></pre>
<p>This setting tells Django to only send the session cookie over HTTPS connections. When set to <code>True</code>, the session cookie will not be sent over unencrypted HTTP connections. This is important for protecting sensitive session data, such as user authentication tokens, from being intercepted by malicious actors on insecure networks.</p>
<pre><code class="lang-python">SESSION_COOKIE_HTTPONLY = <span class="hljs-literal">True</span>
</code></pre>
<p>Setting <code>SESSION_COOKIE_HTTPONLY</code> to <code>True</code> adds an extra layer of security. When this is enabled, the session cookie cannot be accessed by JavaScript code running on the client's browser. This helps mitigate certain types of cross-site scripting (XSS) attacks, where an attacker tries to steal session data using malicious scripts.</p>
<pre><code class="lang-python">SESSION_EXPIRE_AT_BROWSER_CLOSE = <span class="hljs-literal">True</span>
</code></pre>
<p>When <code>SESSION_EXPIRE_AT_BROWSER_CLOSE</code> is set to <code>True</code>, the session will expire and be deleted once the user closes their web browser. This provides a mechanism for creating short-lived sessions that automatically end when the user finishes their browsing session. It's useful for scenarios where you want to ensure that users are logged out when they close their browser, enhancing security for shared or public computers.</p>
<p>Your <code>settings.py</code> file should contain the following:</p>
<pre><code class="lang-python">SESSION_COOKIE_SECURE = <span class="hljs-literal">True</span> 
SESSION_COOKIE_HTTPONLY = <span class="hljs-literal">True</span>
SESSION_EXPIRE_AT_BROWSER_CLOSE = <span class="hljs-literal">True</span>
</code></pre>
<h2 id="heading-authentication-and-authorization">Authentication and Authorization</h2>
<p>Proper authentication and authorization procedures are important for limiting access to certain parts of the web application.</p>
<p>In this section, I'll demonstrate how to implement user login and authentication using Django's authentication framework. I'll also define access control based on user roles to ensure that only authorized users can access certain views and features.</p>
<pre><code class="lang-python"><span class="hljs-meta">@user_passes_test(lambda u: u.is_superuser)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">admin</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'admin.html'</span>, {<span class="hljs-string">'username'</span>: request.user.username})
</code></pre>
<p>The code above is used to restrict access to the admin view based on whether the user is a superuser (admin) or not. </p>
<p>If the user is a superuser, they are allowed to access the view, and the template <code>admin.html</code> is rendered with their username displayed. If the user is not a superuser, they will be redirected to a default unauthorized view, unless additional handling is implemented. </p>
<p>This ensures that only authorized users with admin privileges can access the 'admin.html' page.</p>
<h2 id="heading-cross-site-scripting-xss-protection">Cross-Site Scripting (XSS) Protection</h2>
<p>Cross-Site Scripting (XSS) is a common vulnerability that allows hackers to inject malicious scripts into web pages viewed by other users. </p>
<p>In this section, we'll explore how to implement Content Security Policy (CSP) headers to prevent unauthorized script execution and protect our application against XSS attacks.</p>
<p>CSP headers work by creating a set of rules that define which content sources are allowed and which are blocked. This significantly reduces the attack surface for XSS vulnerabilities, making it much harder for attackers to execute unauthorized scripts on your application. </p>
<p>It's important to carefully configure CSP policies to strike a balance between security and functionality, as overly restrictive policies could potentially break legitimate functionality in your application.</p>
<pre><code class="lang-python">CSP_DEFAULT_SRC = (<span class="hljs-string">"'self'"</span>,)
</code></pre>
<h2 id="heading-cross-site-request-forgery-csrf-protection">Cross-Site Request Forgery (CSRF) Protection</h2>
<p>CSRF attacks occur when malicious websites trick users into taking unauthorized actions on other sites where they are authenticated. Django offers built-in protection against CSRF attacks using CSRF tokens.</p>
<p>It is one of the most common methods used for preventing CSRF attacks using CSRF tokens. </p>
<p>When a user loads a web page that requires user interaction, the server generates a unique token and includes it in the form or the request data. This token is typically associated with the user's session. When the user submits the form or initiates an action, the server checks if the submitted token matches the one associated with the user's session. If they don't match, the request is rejected, as it might be an attempt to perform a CSRF attack. </p>
<p>I'll show you how to include these tokens in forms to prevent unauthorized requests.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>Create Account<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"{% url 'create_user' %}"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
   {% csrf_token %}
   <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
      <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> 
      <span class="hljs-attr">id</span>=<span class="hljs-string">"userName"</span> 
      <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control input-sm chat-input"</span> 
      <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"username"</span> 
    /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<h2 id="heading-sql-injection-prevention">SQL Injection Prevention</h2>
<p>SQL injection is a serious vulnerability that occurs when attackers manipulate user inputs to execute malicious SQL queries on the database. I'll demonstrate how Django's ORM (Object-Relational Mapping) automatically sanitizes user inputs and protects against SQL injection attacks.</p>
<p>It is important to note that even though Django's ORM offers robust defense against the majority of SQL injection attacks, developers must still adhere to best security practices, such as input validation and authorization checks, to guarantee the overall security of their web applications. </p>
<p>It's also a good idea to update Django and its dependencies frequently to take advantage of any security updates or other improvements that may be released in the future.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">request</span>):</span>
    query = request.GET.get(<span class="hljs-string">'q'</span>)
    <span class="hljs-keyword">if</span> query <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
        results = Search.objects.filter(Q(name__icontains=query) | Q(description__icontains=query))
    <span class="hljs-keyword">else</span>:
        results = []
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'search.html'</span>, {<span class="hljs-string">'results'</span>: results})
</code></pre>
<p>The code above defines a Django view function that handles search functionality by extracting a query from the request's <code>GET</code> parameters, using that query to perform a search in the Search model using the Django ORM's filter method, and then rendering a template with the search results. </p>
<p>The search is performed based on the '<strong>name</strong>' and '<strong>description</strong>' fields of the model, and the results are case-insensitive partial matches.</p>
<p>By relying on Django's ORM and its built-in features, you're leveraging a higher level of abstraction that inherently helps prevent common SQL injection vulnerabilities. </p>
<p>This code's structure and usage patterns align with best practices for writing secure queries in Django, making it less susceptible to SQL injection attacks. But it's still important to ensure that the rest of your codebase follows security best practices and that you keep your Django version and dependencies up to date to benefit from the latest security patches.</p>
<h2 id="heading-file-upload-security">File Upload Security</h2>
<p>Handling file uploads requires special attention to prevent attackers from uploading malicious files. We'll see how to validate and restrict file uploads to ensure the security of our web application.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">upload_file</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">'POST'</span>:
        uploaded_file = request.FILES.get(<span class="hljs-string">'file'</span>)
        <span class="hljs-keyword">if</span> uploaded_file:
            <span class="hljs-keyword">if</span> uploaded_file.content_type <span class="hljs-keyword">in</span> ALLOWED_FILE_EXTENSIONS:
                <span class="hljs-keyword">try</span>:
                    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'uploads/'</span> + uploaded_file.name, <span class="hljs-string">'wb+'</span>) <span class="hljs-keyword">as</span> destination:
                        <span class="hljs-keyword">for</span> chunk <span class="hljs-keyword">in</span> uploaded_file.chunks():
                            destination.write(chunk)
                    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'success.html'</span>)
                <span class="hljs-keyword">except</span> ValidationError <span class="hljs-keyword">as</span> e:
                    error_message = str(e)
                    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'fileUpload.html'</span>, {<span class="hljs-string">'error_message'</span>: error_message})
            <span class="hljs-keyword">else</span>:
                error_message = <span class="hljs-string">"Invalid file type."</span>
                <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'fileUpload.html'</span>, {<span class="hljs-string">'error_message'</span>: error_message})
        <span class="hljs-keyword">else</span>:
            error_message = <span class="hljs-string">"No file selected."</span>
            <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'fileUpload.html'</span>, {<span class="hljs-string">'error_message'</span>: error_message})
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'fileUpload.html'</span>)
</code></pre>
<p>The code snippet above defines a function called <code>upload_file</code> This function takes a request object as its argument and handles file uploads.</p>
<p>The function first checks if the request method is <code>POST</code>. If it is, then the function gets the file uploaded by the user using the <code>request.FILES.get('file')</code> method.</p>
<p>If the file is not empty, then the function checks if the file extension is in the <code>ALLOWED_FILE_EXTENSIONS</code> list. This list contains the file types that are allowed to be uploaded. If the file extension is not in the list, then the function displays an error message.</p>
<p>If the file extension is in the list, then the function tries to save the file to a directory called <code>uploads</code>. function uses the <code>with open()</code> statement to open the file in binary write mode. The file is then saved in chunks using the <code>for chunk in file.chunks()</code> loop.</p>
<p>If the file is saved successfully, then the function redirects the user to a success page. Otherwise, an error message is displayed.</p>
<p>The <code>ALLOWED_FILE_EXTENSIONS</code> list is a security measure that prevents users from uploading malicious files, such as executables or scripts. The maximum file size limit is another security measure that prevents users from uploading large files that could cause a denial-of-service attack. Storing the uploaded file in a separate directory isolates the file from the rest of the application and makes it more difficult for attackers to access it.</p>
<h2 id="heading-wrapping-up">Wrapping-up</h2>
<p>Building a secure web application is a continuous process that requires vigilance and implementing best practices. </p>
<p>In this article, I demonstrated various web security measures with code examples while building a web application using Django. </p>
<p>By implementing password hashing, secure session management, authentication, authorization, and protection against common web vulnerabilities like XSS and CSRF, I've taken important steps towards creating a robust and secure web application. </p>
<p>But web security is a vast and ever-evolving field, and it's crucial to stay updated with the latest security trends and practices to ensure your web application remains safe from potential threats. Always perform thorough security testing and regularly update your application and libraries to maintain a strong defense against potential attacks. </p>
<p>With the right security measures in place, you can confidently provide your users with a safe and secure web experience.</p>
<p>You can have access to the code <a target="_blank" href="https://github.com/Enecode/secure-web-application.git">here</a>. Thanks for reading!  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Protect Your Website Against SEO Poisoning ]]>
                </title>
                <description>
                    <![CDATA[ By Jacob Isah  In today's digital landscape, search engine optimization (SEO) is important for increasing online visibility and driving organic traffic to websites.  But cybersecurity threats, including SEO poisoning, pose a great risks to both websi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/protect-your-website-against-seo-poisoning/</link>
                <guid isPermaLink="false">66d45f3cb6b7f664236cbde3</guid>
                
                    <category>
                        <![CDATA[ cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 22 Aug 2023 16:20:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/How-to-Protect-Your-Website-Against-SEO-Poisoning.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jacob Isah </p>
<p>In today's digital landscape, search engine optimization (SEO) is important for increasing online visibility and driving organic traffic to websites. </p>
<p>But cybersecurity threats, including SEO poisoning, pose a great risks to both website owners and SEO efforts. </p>
<p>To fight these risks and safeguard websites, cybersecurity experts and SEO professionals need to collaborate.</p>
<h2 id="heading-what-is-seo-poisoning">What is SEO Poisoning?</h2>
<p>Search engines such as Google work by presenting a list of web pages to users based on their search queries. These web pages are ranked according to the importance of their content.</p>
<p>While many SEO companies specialize in optimizing websites to better position them in these search results, attackers take advantage of popular search terms and use SEO to push malicious sites higher up the ranks. This technique is called SEO poisoning.</p>
<p>The most common goal of SEO poisoning is to increase traffic to malicious sites that may host malware or attempt social engineering. </p>
<p>In this article, we will explore the security measures that cybersecurity and SEO experts should implement to avoid SEO poisoning.</p>
<h1 id="heading-how-to-protect-against-seo-poisoning">How to Protect Against SEO Poisoning</h1>
<p>Collaboration between cybersecurity experts and SEO professionals is important if you want to establish a strong security foundation while optimizing a website for search engines. </p>
<p>By working together, these teams can combine their expertise to create a secure and optimized online presence.</p>
<h2 id="heading-have-robust-website-security">Have Robust Website Security</h2>
<p>Robust website security is the basis of protecting your online presence against various cyber threats. Two important aspects of this are implementing secure coding practices and ensuring that all components of your website are kept up-to-date. </p>
<p>Cybersecurity experts should focus on implementing robust security measures on the website. This includes using secure coding practices, regularly updating software and plugins, and employing web application firewalls (WAFs) to detect and prevent attacks. </p>
<p>By ensuring a secure website environment, you can significantly reduce the risk of SEO poisoning.</p>
<h3 id="heading-secure-coding-practices">Secure Coding Practices</h3>
<p>Secure coding practices involve writing code in a way that reduces vulnerabilities and weaknesses that could be exploited by attackers. Below are some examples of secure coding practices:</p>
<ul>
<li><strong>Input Validation:</strong> Always validate and sanitize user inputs to prevent input-based attacks like SQL injection and cross-site scripting (XSS).</li>
<li><strong>Avoid Hardcoding Secrets:</strong> Avoid hardcoding sensitive information like passwords or API keys directly into the code. Instead, use environment variables or configuration files.</li>
<li><strong>Proper Authentication and Authorization:</strong> Implement strong authentication mechanisms and proper authorization controls to ensure that users can access only what they're authorized to.</li>
<li><strong>Error Handling:</strong> Implement proper error handling to avoid exposing sensitive system information to attackers and users.</li>
<li><strong>Use of Libraries and Frameworks:</strong> Use well-established libraries and frameworks that have undergone security reviews and have a track record of being secure.</li>
</ul>
<p>Secure coding practices and regular updates are essential for maintaining a robust website security posture. By writing code securely and keeping software up-to-date, you significantly reduce the risk of security breaches and ensure the smooth operation of your online presence.</p>
<h2 id="heading-use-a-secure-cms-and-plugins">Use a Secure CMS and Plugins</h2>
<p>SEO experts should carefully select reputable content management systems (CMS) and plugins that have a proven track record of security. Regularly updating them with the latest security patches is crucial to addressing vulnerabilities that could be exploited by attackers.</p>
<h3 id="heading-how-to-evaluate-the-security-of-a-cms">How to Evaluate the Security of a CMS</h3>
<ul>
<li><strong>Community and Development:</strong> A strong and active developer community is a positive sign. More eyes on the code mean faster identification and resolution of security issues.</li>
<li><strong>Regular Updates:</strong> Regular updates, especially security patches, are indicative of a CMS that takes security seriously. Avoid CMSs that have a history of infrequent or delayed updates.</li>
<li><strong>Authentication and Authorization:</strong> Check if the CMS supports strong user authentication mechanisms and proper authorization controls.</li>
<li><strong>Data Handling:</strong> A secure CMS should handle data, including user inputs and sensitive information, in a safe and encrypted manner.</li>
<li><strong>Vulnerability Reporting and Response:</strong> Look into the CMS's vulnerability reporting and response process. Do they have a clear mechanism for reporting vulnerabilities, and how quickly do they respond and release patches?</li>
</ul>
<h3 id="heading-how-to-evaluate-plugins-and-extensions">How to Evaluate Plugins and Extensions</h3>
<ul>
<li><strong>Source and Reputation:</strong> Download plugins only from reputable sources like the official plugin repository for the CMS. Avoid downloading plugins from third-party sites.</li>
<li><strong>User Ratings and Reviews:</strong> Check user reviews and ratings for plugins. If a plugin has a lot of positive reviews and a high user rating, it's generally a good sign.</li>
<li><strong>Regular Updates:</strong> Plugins that receive frequent updates are more likely to have active developers who are fixing vulnerabilities and adding features.</li>
<li><strong>Plugin Compatibility:</strong> Ensure that the plugin is compatible with the latest version of your CMS. Outdated plugins can introduce vulnerabilities.</li>
<li><strong>Permissions:</strong> Plugins should request only the necessary permissions. Be wary of plugins that require excessive permissions.</li>
</ul>
<p>Remember no CMS or plugin can guarantee 100% security. Security is a collaborative effort that involves regularly updating both your CMS and plugins, as well as following secure coding practices when developing your website.</p>
<h2 id="heading-perform-regular-security-audits">Perform Regular Security Audits</h2>
<p>Both cybersecurity and SEO professionals should conduct regular security audits to identify potential vulnerabilities or weaknesses that could lead to SEO poisoning. </p>
<p>By reviewing website code, configuration files, and server settings, they can proactively address security gaps and ensure the integrity of SEO efforts.</p>
<h2 id="heading-monitor-for-suspicious-activities">Monitor for Suspicious Activities</h2>
<p>SEO experts should be vigilant in monitoring SEO-related activities on the website. Sudden drops in search engine rankings, unusual keyword stuffing, unexpected redirects, or suspicious backlinks can indicate SEO poisoning attempts. </p>
<p>Promptly investigating and addressing such anomalies is important to preventing further damage.</p>
<p>Vigilant monitoring for unusual activities on your website is essential for early detection of SEO poisoning attempts. Here are some potential issues, why they might happen, and how to prevent them.</p>
<h3 id="heading-sudden-drop-in-search-engine-rankings">Sudden Drop in Search Engine Rankings</h3>
<ul>
<li><strong>What Happens:</strong> Your website's position in search engine results suddenly plummets.</li>
<li><strong>Why It Might Happen:</strong> It could be due to an algorithm change, but it might also be the result of a hacking attempt or SEO poisoning.</li>
<li><strong>Prevention:</strong> Regularly monitor your search engine rankings and organic traffic. Implement solid SEO practices to avoid potential penalties.</li>
</ul>
<h3 id="heading-keyword-stuffing">Keyword Stuffing</h3>
<ul>
<li><strong>What Happens:</strong> Pages on your site contain an excessive number of keywords, making content unnatural and difficult to read.</li>
<li><strong>Why It Might Happen:</strong> Malicious actors might try to manipulate search engine rankings through keyword stuffing.</li>
<li><strong>Prevention:</strong> Follow ethical SEO guidelines. Write content for users, not search engines. Use keywords naturally and provide valuable information.</li>
</ul>
<h3 id="heading-unexpected-redirects">Unexpected Redirects</h3>
<ul>
<li><strong>What Happens:</strong> Users are redirected to unrelated or malicious websites when they click on links on your site.</li>
<li><strong>Why It Might Happen:</strong> Hackers might inject malicious code into your website's files to redirect traffic for their benefit.</li>
<li><strong>Prevention:</strong> Regularly scan your website's code for any suspicious code injections. Keep your website software, themes, and plugins updated to the latest versions.</li>
</ul>
<h3 id="heading-unusual-backlinks">Unusual Backlinks</h3>
<ul>
<li><strong>What Happens:</strong> Your website has links from spammy or irrelevant sites that you didn't intend to associate with.</li>
<li><strong>Why It Might Happen:</strong> Competitors might engage in negative SEO to hurt your site's reputation or search rankings.</li>
<li><strong>Prevention:</strong> Monitor your backlink profile regularly. Use tools to disallow or remove unwanted backlinks. Build quality backlinks through ethical practices.</li>
</ul>
<h3 id="heading-unexplained-traffic-spikes">Unexplained Traffic Spikes:</h3>
<ul>
<li><strong>What Happens:</strong> Your website experiences sudden and unexpected surges in traffic.</li>
<li><strong>Why It Might Happen:</strong> It could be a sign of a <a target="_blank" href="https://www.freecodecamp.org/news/protect-against-ddos-attacks/">Distributed Denial of Service (DDoS) attack</a>, where attackers flood your site with traffic to overwhelm it.</li>
<li><strong>Prevention:</strong> Use web application firewalls (WAFs) to detect and mitigate DDoS attacks. Monitor your website's traffic patterns for anomalies.</li>
</ul>
<h3 id="heading-phishing-pages">Phishing Pages:</h3>
<ul>
<li><strong>What Happens:</strong> Attackers create fake pages on your site to steal sensitive information from users.</li>
<li><strong>Why It Might Happen:</strong> Hackers exploit vulnerabilities to inject malicious code, creating fake login or payment pages.</li>
<li><strong>Prevention:</strong> Regularly audit your website's files for unauthorized changes. Implement security plugins that scan for malicious code.</li>
</ul>
<h3 id="heading-unexpected-changes-to-content">Unexpected Changes to Content:</h3>
<ul>
<li><strong>What Happens:</strong> Your website's content is altered without your authorization.</li>
<li><strong>Why It Might Happen:</strong> Attackers with unauthorized access might change content to spread malware or deface your site.</li>
<li><strong>Prevention:</strong> Enforce strong user authentication. Monitor your website for unauthorized changes using change detection tools.</li>
</ul>
<p>By staying vigilant and proactively monitoring your website for these types of suspicious activities, SEO experts can quickly detect and respond to potential security threats. Implementing a combination of robust security measures, regular updates, and continuous monitoring will greatly enhance your website's resilience against cyber threats.</p>
<h2 id="heading-validate-user-generated-content">Validate User-Generated Content</h2>
<p>To prevent the injection of malicious links or code through user-generated content, both cybersecurity and SEO experts should implement strict validation and filtering mechanisms. </p>
<p>Utilizing CAPTCHAs, moderation systems, and content filtering tools can help maintain a secure website environment.</p>
<h3 id="heading-moderation-tools">Moderation Tools</h3>
<p>Moderation tools enable manual or automated review of user-generated content before it's published on your website. They allow you to ensure that content adheres to your platform's guidelines and standards.</p>
<p>Some popular moderation tools include:</p>
<ul>
<li><strong>Automated Profanity Filters:</strong> These tools automatically detect and block or flag content containing offensive language, slurs, or inappropriate words.</li>
<li><strong>Manual Review Queues:</strong> Content flagged by users or automated filters can be placed in a review queue for human moderators to assess before publishing.</li>
<li><strong>AI-Powered Moderation:</strong> Advanced AI algorithms can identify potentially harmful content, such as hate speech, violence, or explicit material, and flag it for review.</li>
</ul>
<h3 id="heading-content-filtering-tools">Content-Filtering Tools</h3>
<p>Content-filtering tools use predefined rules to identify and block specific types of content. These tools are particularly useful for preventing the posting of malicious links or code. </p>
<p>Here's what to look for when considering these tools:</p>
<ul>
<li><strong>URL Filtering:</strong> The tool should be able to detect and prevent the posting of malicious URLs that could lead to phishing sites, malware downloads, or other security risks.</li>
<li><strong>Code Validation:</strong> If your platform allows HTML or script embedding, ensure the tool can validate and block potentially harmful code to prevent cross-site scripting (XSS) attacks.</li>
<li><strong>Custom Rule Creation:</strong> The ability to create custom filtering rules tailored to your platform's specific needs is valuable for maintaining control over content.</li>
</ul>
<p>By implementing a combination of moderation and content-filtering tools, SEO experts can create a safer and more positive user experience on websites. Regularly reviewing and updating filtering rules, as well as staying informed about emerging content threats, will help you maintain a secure user-generated content environment.</p>
<h2 id="heading-educate-your-team-and-raise-awareness">Educate Your Team and Raise Awareness</h2>
<p>Both cybersecurity and SEO experts should educate website owners, staff, web maintainers, and clients about the risks of SEO poisoning and the importance of maintaining a secure website. Emphasize the need for strong passwords, regular updates, and secure hosting. </p>
<p>By promoting cybersecurity awareness, you can ensure the adoption of good security practices.</p>
<p>Also, make sure your teams stay updated on the latest security trends, SEO techniques, and emerging threats. This knowledge empowers them to proactively address vulnerabilities and implement effective countermeasures against SEO poisoning attacks. </p>
<p>Here are some recommended resources and ways to stay up-to-date as an expert.</p>
<h3 id="heading-online-security-news-portals">Online Security News Portals</h3>
<p>Websites like <a target="_blank" href="https://krebsonsecurity.com/">KrebsOnSecurity</a>, <a target="_blank" href="https://www.darkreading.com/">Dark Reading</a>, and <a target="_blank" href="https://news.ycombinator.com/news">Hacker News</a> provide regular updates on the latest cybersecurity threats, vulnerabilities, and best practices.</p>
<h3 id="heading-cybersecurity-blogs">Cybersecurity Blogs</h3>
<p>Follow respected cybersecurity blogs such as <a target="_blank" href="https://www.schneier.com/">Schneier</a> on Security, <a target="_blank" href="https://www.troyhunt.com/">Troy Hunt's Blog</a>, and <a target="_blank" href="https://isc.sans.edu/">the SANS Internet Storm Center</a> for in-depth analysis, insights, and commentary.</p>
<h3 id="heading-social-media">Social Media</h3>
<p>Follow reputable cybersecurity experts and organizations on platforms like Twitter (X) and LinkedIn. They often share insights, news, and discussions about the latest trends and threats.</p>
<h3 id="heading-industry-reports-and-white-papers">Industry Reports and White Papers</h3>
<p>Organizations like Verizon, Ponemon Institute, and Symantec regularly release cybersecurity reports and whitepapers with valuable insights and statistics.</p>
<h3 id="heading-webinars-and-conferences">Webinars and Conferences</h3>
<p>Participate in webinars and attend cybersecurity conferences like <a target="_blank" href="https://www.blackhat.com/">Black Hat</a>, <a target="_blank" href="https://defcon.org/">DEF CON</a>, and <a target="_blank" href="https://www.rsaconference.com/">RSA Conference</a>. These events offer deep dives into cutting-edge security research and emerging threats.</p>
<h3 id="heading-security-organizations">Security Organizations</h3>
<p>Join organizations like ISACA, (ISC)², and OWASP to access resources, research, and networking opportunities.</p>
<p>And here are some tips for SEO experts:</p>
<h3 id="heading-googles-official-blogs">Google's Official Blogs</h3>
<p>Google provides insights into algorithm updates, best practices, and changes through their blogs, like Google Webmaster Central Blog and Google Search Central Blog.</p>
<h3 id="heading-moz-and-semrush">Moz and SEMrush</h3>
<p>These platforms offer SEO tools and resources, including blogs, guides, and webinars, to keep you informed about the latest SEO trends and strategies.</p>
<h3 id="heading-search-engine-land-and-search-engine-journal">Search Engine Land and Search Engine Journal</h3>
<p>These websites provide daily news and analysis on search engine optimization, search engine marketing, and related topics.</p>
<h3 id="heading-youtube-channels-and-podcasts">YouTube Channels and Podcasts</h3>
<p>Many SEO experts and agencies share their knowledge through video tutorials and podcasts. Channels like <a target="_blank" href="https://www.youtube.com/channel/UCx7J37QuXsGL7QG6SMIpqKg">Brian Dean's Backlinko</a> and podcasts like <a target="_blank" href="https://podcasts.apple.com/us/podcast/experts-on-the-wire-an-seo-podcast/id1093560792">Experts On The Wire</a> are valuable resources.</p>
<h3 id="heading-seo-forums-and-communities">SEO Forums and Communities</h3>
<p>Engage in discussions and share insights on platforms like WebmasterWorld, Reddit's r/SEO, and <a target="_blank" href="https://www.freecodecamp.org/news/p/7c184815-476d-4ad8-9bf8-fe81015af988/Inbound.org">Inbound.org</a></p>
<h3 id="heading-seo-training-courses">SEO Training Courses</h3>
<p>Platforms like Coursera, Udemy, and LinkedIn Learning offer SEO courses that cover foundational and advanced strategies.</p>
<h3 id="heading-google-search-console-and-google-analytics">Google Search Console and Google Analytics</h3>
<p>Regularly check your website's performance metrics and search queries to stay updated on changes in user behavior and site visibility.</p>
<p>Remember to validate information from multiple trusted sources and consider cross-referencing with established experts. By consistently staying informed through these resources, you can stay ahead of the curve and implement effective cybersecurity measures and SEO strategies.</p>
<h2 id="heading-optimize-your-websites-performance">Optimize Your Website's Performance</h2>
<p>SEO experts should optimize website performance to enhance the user experience and reduce the risk of SEO poisoning. </p>
<p>Fast-loading pages, mobile-friendly designs, and efficient website architecture not only contribute to better SEO rankings but also minimize the time visitors spend on potentially compromised pages.</p>
<h3 id="heading-indirect-benefits-of-good-website-performance-in-preventing-seo-poisoning">Indirect Benefits of Good Website Performance in Preventing SEO Poisoning</h3>
<p>A fast-loading website encourages users to stay longer and engage with your content. Users are less likely to leave a site that loads quickly, reducing the chances of them encountering poisoned content that might have been inserted by attackers.</p>
<p>Also, a high bounce rate (users leaving the site quickly after landing on a page) can signal to search engines that your site's content isn't relevant or useful. A fast site with engaging content can reduce bounce rates, helping maintain positive search engine rankings.</p>
<p>A fast site with efficient code and minimal security vulnerabilities reduces this window of opportunity for attackers.</p>
<p>On the other hand, a slow website can give attackers more time to exploit vulnerabilities and insert malicious content. </p>
<p>Slow websites can also put unnecessary strain on your server's resources. Attackers might leverage this to launch resource-intensive attacks like Distributed Denial of Service (DDoS). Optimizing your site's performance can help mitigate such risks.</p>
<p>Lastly, search engine bots crawl and index websites. A slow site can hinder this process, affecting how search engines index and rank your content. A well-optimized site ensures that your content is accurately crawled and indexed.</p>
<h3 id="heading-how-to-optimize-website-performance">How to Optimize Website Performance</h3>
<ul>
<li>Use compressed and properly sized images to reduce page load times.</li>
<li>Minimize HTML, CSS, and JavaScript code to decrease load times.</li>
<li>Leverage browser caching to store certain elements locally, reducing the need to download them repeatedly.</li>
<li>Use a <a target="_blank" href="https://www.freecodecamp.org/news/cdns-speed-up-performance-by-reducing-latency/">Content Delivery Network (CDN)</a> to distribute content across multiple servers, reducing latency and improving load times.</li>
<li>Minimize the number of requests your site makes to the server by combining CSS and JavaScript files.</li>
<li>Optimize server settings, use caching mechanisms, and ensure efficient server resources allocation.</li>
<li>Ensure your site is responsive and mobile-friendly for seamless performance across devices.</li>
<li>Use efficient coding practices and consider asynchronous loading for scripts.</li>
</ul>
<p>By focusing on website performance optimization, you indirectly bolster your site's resilience against potential security threats, including SEO poisoning. A fast, user-friendly website enhances user experience, reduces vulnerabilities, and contributes to a healthy online presence.</p>
<h2 id="heading-perform-regular-backups-and-have-a-disaster-recovery-plan">Perform Regular Backups and Have a Disaster Recovery Plan</h2>
<p>Both cybersecurity and SEO experts should emphasize the importance of regular backups and make sure the company has a <a target="_blank" href="https://www.freecodecamp.org/news/disaster-recovery-plan/">robust disaster recovery plan</a>. </p>
<p>Backups allow companies to restore data to a known secure state in the event of an SEO poisoning attack or any other security incident.</p>
<h3 id="heading-disaster-recovery-involves">Disaster Recovery Involves:</h3>
<ul>
<li><strong>Planning</strong>: Identifying potential risks, threats, and vulnerabilities that could lead to data loss or system downtime. This includes natural disasters, cyberattacks, hardware failures, and more.</li>
<li><strong>Backup and Restoration:</strong> Regularly create backups of critical data and systems to ensure that if a disaster occurs, you can restore your data and systems to a functional state.</li>
<li><strong>Testing</strong>: Regularly test your disaster recovery plan to ensure that backups are accessible and can be successfully restored. Testing helps identify any issues that need to be addressed before an actual disaster occurs.</li>
<li><strong>Communication</strong>: Developing a communication plan to keep stakeholders informed during a disaster. This includes notifying employees, customers, partners, and the public about the situation and the steps being taken to recover.</li>
<li><strong>Documentation</strong>: Keep detailed documentation of your disaster recovery plan, including procedures, contacts, and any necessary passwords or access information.</li>
</ul>
<h2 id="heading-how-to-recognize-malicious-sites-from-seo-poisoning">How to Recognize Malicious Sites from SEO Poisoning</h2>
<p>Malicious sites often have content that's unrelated to the user's search query. If a site's content doesn't match what you're looking for, it could be a red flag.</p>
<p>Also, be cautious of sites with unprofessional designs, excessive ads, and cluttered layouts. Legitimate sites generally invest in good user experience.</p>
<p>Check the URL for unusual or misspelled words, extra characters, or subdomains that don't match the official site. Attackers might mimic legitimate domains to deceive users.</p>
<p>You should also be wary of domain names that look similar to popular sites but contain slight misspellings or variations. These are common in phishing attempts.</p>
<p>If a site promises unbelievable deals or offers that seem too good to be true, it's often a sign of a scam.</p>
<p>When you're using a legitimate website, it usually has clear contact information. If you can't find any contact details, it's a warning sign.</p>
<p>Additionally, poor spelling and grammar throughout the site can indicate a lack of professionalism and potentially malicious intent.</p>
<p>Finally, if the site doesn't have a padlock icon in the browser's address bar, it's not using a secure HTTPS connection, making your data vulnerable.</p>
<h2 id="heading-how-to-avoid-malicious-sites">How to Avoid Malicious Sites</h2>
<p>Malicious sites are out there, unfortunately. So here are some tips to help you recognize them and avoid them:</p>
<ul>
<li>Always double-check the URL to ensure it matches the official domain of the site you intend to visit.</li>
<li>Search engines like Google sometimes display warnings next to potentially harmful sites in search results.</li>
<li>Instead of clicking on links from search results, type the official website's URL directly into the browser.</li>
<li>Install reputable antivirus and anti-malware software that can help detect and warn you about malicious sites.</li>
<li>Regularly update your operating system, browsers, and plugins to benefit from the latest security patches.</li>
</ul>
<p>Remember, attackers use SEO poisoning to lure users into interacting with malicious sites. By staying vigilant, practicing safe browsing habits, and being cautious when encountering unfamiliar websites, you can greatly reduce the risk of falling victim to SEO poisoning and other online threats.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Solid collaboration between cybersecurity experts and SEO professionals is crucial for maintaining website security and preventing SEO poisoning attacks. </p>
<p>By implementing robust security measures, conducting regular audits, monitoring for suspicious activities, and staying informed about emerging threats, they can protect websites from malicious manipulation. </p>
<p>Educating website owners and clients about the importance of security and following best practices further strengthens the defense against SEO poisoning. </p>
<p>With a collaborative and proactive approach, cybersecurity and SEO experts can ensure the integrity of websites and optimize their online presence effectively.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is XSS? How to Protect Your Website from DOM Cross-Site Scripting Attacks ]]>
                </title>
                <description>
                    <![CDATA[ By Andrej Kovacevic Website security issues and vulnerabilities are a global problem as cyber security vulnerabilities are increasing. We have seen a major rise in the average number of these cases in the past few years, and 2021 saw an all-time high... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-protect-against-dom-xss-attacks/</link>
                <guid isPermaLink="false">66d45da34a7504b7409c3332</guid>
                
                    <category>
                        <![CDATA[ Application Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ DOM ]]>
                    </category>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 03 Jan 2023 19:51:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/xss-code-case.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Andrej Kovacevic</p>
<p><strong>Website security issues</strong> and vulnerabilities are a global problem as cyber security vulnerabilities are increasing. We have seen a major rise in the average number of these cases in the past few years, and 2021 saw an all-time high.</p>
<p>So in this tutorial, we are going to talk about DOM XSS cross-site scripting security issues and what impact they can have on your data. Make sure you read till the end. Let's begin by brushing up on some basics about DOM XSS cross-site script security.</p>
<h2 id="heading-what-is-cross-site-scripting">What is Cross-Site Scripting?</h2>
<p>Cross-site scripting, also called XSS, is a <a target="_blank" href="https://www.wix.com/blog/2022/01/website-security/">website security issue</a> that compromises user information and data when those people use a vulnerable application. The attacker can use this to circumvent the origin policy, which separates two websites from one another.</p>
<p>Attackers may use XSS to pretend to be a user, perform actions that a user would, and gain access to the user’s information. This can also allow the attackers to gain full access to the user’s information if they have permissions and privileges. It can also take over the complete actions and performance of the website if this continues.</p>
<p>To help you better understand these types of attacks, we are going to discuss some fundamentals of how XSS operates and what it does.</p>
<h2 id="heading-how-does-xss-work">How Does XSS Work?</h2>
<p>Cross-site scripting uses technology to manipulate a vulnerable site so that it sends dangerous JavaScript to users. This allows the attacker to gain complete access to the site when the script gains access to the user’s system. But the user needs to execute the JavaScript for this first.</p>
<h3 id="heading-types-of-xss-attacks">Types of XSS Attacks</h3>
<h4 id="heading-reflected-xss">Reflected XSS:</h4>
<p>This malicious script comes from the HTTP request. This is the most basic type of XSS attack, where an application could receive malicious data and reflect it immediately towards the user. </p>
<p>The attacker’s payload must be part of the request sent to a server, which is then reflected and executed onto the user’s application. </p>
<p>One example of this would be an attacker convincing someone to click on a phishing link before it takes effect.</p>
<h4 id="heading-stored-xss">Stored XSS:</h4>
<p>This malicious script comes from the database of the website. The attacker inputs the malicious request onto the server where it could stay permanently unless manually addressed. </p>
<p>For example, the attacker could input a malicious script into a comment field, which would be on display for everyone who visits the page. Even without directly engaging with the script, page visitors could fall victim to this attack.</p>
<h4 id="heading-dom-based-xss">DOM-based XSS:</h4>
<p>This more advanced vulnerability exists in client code and not on the server code. DOM-based XSS is neither reflected nor stored onto the server, but exists in a page’s Document Object Model (DOM). The web application reads the malicious code and executes it in the browser as part of the DOM, which is more difficult to detect as it doesn’t come through the server.</p>
<p>The <strong>security vulnerabilities</strong> involved in DOM XSS attacks are a serious concern for most websites. We are going to talk about some of the most common risks that you have on open source web building platforms such as WordPress with regard to DOM - XSS hacks.</p>
<p>This allows the attacker to execute malicious JavaScript code in the victim's browser, potentially allowing the attacker to steal sensitive information or perform other harmful actions on the victim's behalf.</p>
<p>Here is an example of a DOM-based XSS attack:</p>
<pre><code class="lang-javascript">&lt;script&gt;
 <span class="hljs-comment">// This function is intended to take a user supplied URL and display it on the page</span>
 <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayURL</span>(<span class="hljs-params">url</span>) </span>{
  <span class="hljs-comment">// The URL is passed through innerHTML, which can execute JavaScript code</span>
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"display"</span>).innerHTML = url;
 }
&lt;/script&gt;

&lt;!-- User supplied input is passed to the displayURL <span class="hljs-function"><span class="hljs-keyword">function</span> --&gt;
&lt;<span class="hljs-title">p</span>&gt;<span class="hljs-title">Enter</span> <span class="hljs-title">a</span> <span class="hljs-title">URL</span> <span class="hljs-title">to</span> <span class="hljs-title">display</span>: &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">text</span>" <span class="hljs-title">id</span>="<span class="hljs-title">user</span>-<span class="hljs-title">input</span>" /&gt;&lt;/<span class="hljs-title">p</span>&gt;
&lt;<span class="hljs-title">button</span> <span class="hljs-title">onclick</span>="<span class="hljs-title">displayURL</span>(<span class="hljs-params">document.getElementById(<span class="hljs-string">'user-input'</span>).value</span>)"&gt;
 <span class="hljs-title">Display</span> <span class="hljs-title">URL</span>
&lt;/<span class="hljs-title">button</span>&gt;

&lt;!-- <span class="hljs-title">The</span> <span class="hljs-title">URL</span> <span class="hljs-title">is</span> <span class="hljs-title">displayed</span> <span class="hljs-title">in</span> <span class="hljs-title">this</span> <span class="hljs-title">div</span> --&gt;
&lt;<span class="hljs-title">div</span> <span class="hljs-title">id</span>="<span class="hljs-title">display</span>"&gt;&lt;/<span class="hljs-title">div</span>&gt;</span>
</code></pre>
<p>Remember that this tutorial is purely for educational purposes, to help you recognize and defend against XSS. You shouldn't use this information to perform any of these sorts of attacks.</p>
<h2 id="heading-dom-xss-wordpress-vulnerabilities">DOM XSS – WordPress Vulnerabilities</h2>
<p>The main target of DOM XSS attacks on WordPress is its users. Users enter their details, accounts, and site credentials to access their WordPress sites and this is what the DOM XSS attacks aim to compromise online. The attackers can use DOM XSS to get access to user information and details with a single click.</p>
<p>This also includes your cookies, information, and others, making it one of the most common <strong>WordPress security vulnerabilities.</strong></p>
<p>Following are some of the top WordPress website security issues you should bear in mind to ensure better cross-site script security.</p>
<h3 id="heading-accessing-a-users-private-information">Accessing a User's Private Information</h3>
<p>One of the most common WordPress security vulnerabilities involved with DOM XSS attacks is that attackers can gain useful information and even completely take over a user’s site. This can often make things escalate fast and cause complete data compromise.</p>
<h3 id="heading-impersonating-a-user">Impersonating a User</h3>
<p>Attackers can pretend to be the user, to interact with the victim’s online users, clients, and customers to gain their information.</p>
<h3 id="heading-compromising-a-site">Compromising a Site</h3>
<p>Another common cross-site scripting security issue with websites is that these attacks can compromise the website and take access from the user. This includes displaying deviating content on the site (or content that is not originally from the site).</p>
<p>Other cases may involve changing the way WordPress looks online. Other people may also exploit the website by installing explicit content.</p>
<h3 id="heading-social-engineering">Social Engineering</h3>
<p>In more severe cases, attackers may impact the WordPress site through phishing attempts. This is a common concern for web builder security vulnerabilities that we will discuss shortly.</p>
<p>The impact of XSS cross script-security issues varies for each website. However, WordPress sites are usually at a higher risk of these kinds of compromises because users save their personal information on the website. The risk increases further if the user is an admin, as the attacker can compromise the complete WordPress site.</p>
<h2 id="heading-dom-xss-and-closed-code-web-builder-platforms">DOM XSS and Closed Code Web Builder Platforms</h2>
<p>Website builders such as Weebly, Squarespace, Webflow and Wix, unlike WordPress, are non-open source platforms. They allow users to intuitively create websites for their businesses via drag and drop DIY features without any coding or design experience. They also work hard to protect their users' security. </p>
<p>There are tons of useful tools, options, easy-to-integrate dashboards, and hosting opportunities available for users instilling their trust in these platforms. Website security issues are of course a major concern for the majority of the users on these platforms.</p>
<p>Many website builders try their best to protect the sites of their users from <a target="_blank" href="https://techbullion.com/how-to-secure-your-online-store-from-hackers/">hacker threats</a>. But out of all of the website builders available, I believe that Wix follows the NIST framework for cyber security the best and has become a major contributor to improvements in this field. </p>
<p>Wix protects users on their sites from being vulnerable to these kinds of attacks online with tools such as:</p>
<ul>
<li>Third-party updates that project against DOM XSS attacks</li>
<li>A secure Sockets Layer that protects against unwanted access for users on site</li>
<li>Round-the-clock secure web hosting which protects users against any kind of unwanted logins or phishing attempts.</li>
<li>Granting its users admin privileges, which restrict site access and control to the original owner only</li>
<li>Highlighting weak passwords and suggesting more difficult-to-decipher passwords.</li>
</ul>
<h2 id="heading-ways-to-protect-against-xss-attacks">Ways to Protect Against XSS Attacks</h2>
<p>Defending your system and users against XSS attacks often requires a multifaceted approach to ensure that your servers and applications are protected against various types of attacks.</p>
<p>The best way to defend against XSS attacks is to properly sanitize user input. This means making sure that any user input is properly encoded so that it cannot be interpreted as code by the browser. </p>
<p>Additionally, you can use a web application firewall (WAF) to help identify and block XSS attacks. It's also a good idea to keep your software and web applications up to date, as many XSS vulnerabilities can be mitigated by simply applying the latest security patches.</p>
<h3 id="heading-input-validation">Input Validation</h3>
<p>This programming technique ensures that only properly-formatted data can enter a software system. Websites can either allow or block certain values to ensure that no XSS can penetrate their servers.</p>
<h3 id="heading-escaping-or-encoding-user-input">Escaping or Encoding User Input</h3>
<p>Encoding and escaping changes user input to make them safer for the system. Encoding replaces special characters with more harmless equivalents (for example, translating &lt; to &lt;), while escaping adds special characters to protect against injection attacks.</p>
<h3 id="heading-implementing-a-content-security-policy-csp">Implementing a Content Security Policy (CSP)</h3>
<p>Content security policies help administrators mitigate XSS attacks by restricting the resources a page can load at a given time. These resources can include scripts and images that could potentially harm clients and servers.</p>
<h2 id="heading-bottom-line">Bottom Line</h2>
<p>DOM XSS cross-site scripting security issues are a serious concern for users on websites. But closed code web building platforms provide features like admin privileges, password best practices, 3<sup>rd</sup> party updates, and much more. These features make them a more secure website building option than many open code platforms.</p>
<p>You can also prevent XSS attacks by filtering input once it arrives. You can do this by ensuring that only valid input is accepted.</p>
<p>When encoding data on output, the process should be done in HTTP responses so it will not be read as active content. More complex coding might be required, such as applying combinations of URL, JavaScript, CSS, and HTML encoding, depending on the context of output.</p>
<p>Keep response headers in check so browsers will have an appropriate interpretation of content.</p>
<p>Finally, use Content Security Policy (CSP) to minimize the severity of XSS attacks.</p>
<pre><code>&lt;meta http-equiv=<span class="hljs-string">"Content-Security-Policy"</span> content=<span class="hljs-string">"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"</span>&gt;
</code></pre><p>This CSP will allow your website to load scripts and styles from the same origin (that is, your own website), but it will block scripts and styles from external sources. It will also allow the use of inline scripts and styles, but it will block eval() statements, which can be used to execute arbitrary code.</p>
<p>Of course, this is just a simple example, and you can customize your CSP to suit your specific needs. For more information on how to use CSPs to defend against XSS attacks, you can refer to the Content Security Policy Level 2 specification.</p>
<p><em>Feature image via Unsplash (Florian Olivo).</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Fuzz Web Applications using FFuf – Web Security Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ Building strong authentication systems is crucial for web applications. Now that many businesses have a growing online presence, a malicious actor taking control of your website can be devastating. In this article, we will learn how to use Ffuf, a fa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/web-security-fuzz-web-applications-using-ffuf/</link>
                <guid isPermaLink="false">66d03629ec0a2e1087e8242d</guid>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #infosec ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Thu, 10 Nov 2022 17:21:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/11/ffuf.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building strong authentication systems is crucial for web applications. Now that many businesses have a growing online presence, a malicious actor taking control of your website can be devastating.</p>
<p>In this article, we will learn how to use Ffuf, a fast web fuzzer written in Go. You will learn how to fuzz your way to find directories and files and bypass the authentication of a website using ffuf. Then you'll learn how to defend against these types of attacks.</p>
<p>Remember – to protect yourself and your websites, it helps to know how an attacker would try to get in. That way, you can more effectively keep them out.</p>
<p><strong>Note:</strong> Before we dive into using ffuf, I would like to emphasize that this tutorial is only meant to help you defend yourself against fuzzing attacks. If you use this material for malicious purposes, I am not responsible.</p>
<h2 id="heading-what-is-ffuf">What is FFuf?</h2>
<p>Ffuf is a fuzzer written in the <a target="_blank" href="https://go.dev/">Go programming language</a>.</p>
<p>Ffuf belongs to the exploitation phase in the <a target="_blank" href="https://exploitable.manishmshiva.com/ethical-hacking-lifecycle-five-stages-of-a-penetration-test-c201e8e5bbf7">pentesting lifecycle</a>. It is also the fastest open-source fuzzing tool available in the market. </p>
<p>But before we start using Ffuf, let's understand what fuzzing is.</p>
<h2 id="heading-what-is-fuzzing">What is Fuzzing?</h2>
<p>Fuzzing is a method of sending malformed or abnormal data to a system in order to get it to misbehave in some way, which could lead to the discovery of vulnerabilities.</p>
<p>Finding hidden files, sending random data to forms, or even login attempts to web applications can be considered fuzzing.</p>
<p>Then you might be wondering “How is it different from Brute forcing?”.</p>
<p>Brute forcing can be considered a part of fuzzing. In brute force, the attacker uses valid data, for example, to check if a login attempt works. But with Fuzzing, they can send random data to break the expected behavior of a system.</p>
<p>For example, if you use a tool like Ffuf and load it with hundreds of username-password combinations to try on a website, it is fuzzing. And that’s exactly what we will do using Ffuf.</p>
<p>Make sure you have written permission if you are going to try this tool on a third-party website.</p>
<h2 id="heading-how-to-install-ffuf-and-wordlists">How to Install Ffuf and Wordlists</h2>
<p>Ffuf comes pre-packaged with the Kali Linux distribution. If you want to install Ffuf on your personal computer, <a target="_blank" href="http://ffuf.me/install">here are the instructions</a>. </p>
<p>Since Ffuf is written in the Go programming language, make sure you have the Go compiler installed in your system before trying to install Ffuf.</p>
<p>If you are new to wordlists, a wordlist is a list of commonly used terms. This can be a <a target="_blank" href="https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-100.txt">password wordlist</a>, <a target="_blank" href="https://github.com/danielmiessler/SecLists/blob/master/Usernames/Names/names.txt">username wordlist</a>, subdomain wordlist, and so on. You can find a lot of <a target="_blank" href="https://github.com/danielmiessler/SecLists">useful wordlists here</a>.</p>
<p>I would recommend downloading <a target="_blank" href="https://github.com/danielmiessler/SecLists">Seclists</a>. Seclists is a collection of multiple types of lists used during security assessments. This includes usernames, passwords, URLs, etc. If you are using Kali Linux, you can find seclists under /usr/share/wordlists.</p>
<p>To try this tool in real-time, you can either use your own website or use a practice web app like the <a target="_blank" href="https://github.com/digininja/DVWA">Damn Vulnerable Web app</a> (DVWA). DVWA is an intentionally misconfigured vulnerable web application that is used by pen testers for practicing web application attacks.</p>
<h2 id="heading-fuzzing-with-ffuf">Fuzzing with Ffuf</h2>
<p>Now that you understand what Fuzzing and Wordlists are, let's start using Ffuf.</p>
<p>We will use ffuf to fuzz the web application to discover directories, find usernames, enumerate virtual hosts, and even brute-force email/password combinations.</p>
<p>You can use the help command (-h) if you want to quickly look at the options provided by Ffuf. This is useful since you don't have to memorize all the options provided by Ffuf. </p>
<pre><code>ffuf -h
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-26.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Do remember that the URL (-u) and wordlist (-w) parameters are always required.</p>
<p>Note that I'll be using <a target="_blank" href="http://localhost:3000">http://localhost:3000</a> for my examples. If you setup your own web app or use an existing website, you have to replace “localhost:3000” with the ip address or the domain name of the website.</p>
<h3 id="heading-how-to-enumerate-urls-with-ffuf">How to Enumerate URLs with Ffuf</h3>
<p>Let's see how to find some URL paths.</p>
<p>Finding URLs is useful, especially if they are being hidden from being publicly indexed. We will use the <a target="_blank" href="https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/big.txt">web content wordlist</a> from seclists to fuzz the web app for hidden URLs.</p>
<p>You can use the following command to look for URLs:</p>
<pre><code>ffuf -u http:<span class="hljs-comment">//localhost:3000/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/big.txt</span>
</code></pre><p>Here, the “FUZZ” keyword is used as a placeholder. Ffuf will try to hit the URL by replacing the word “FUZZ” with every word in the wordlist.</p>
<p>Here is what I found from the DVWA:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of looking for URLs</em></p>
<p>Interesting. You can see that we have found a few (possibly important) locations like /config, /docs, and /server-status.</p>
<p>If a real-world web app had pages that were not linked anywhere but used standard names, Ffuf would easily spot them.</p>
<h3 id="heading-how-to-enumerate-files-with-ffuf">How to Enumerate Files with Ffuf</h3>
<p>What if you want to look for specific files? Thankfully, Ffuf provides us with the extension option (-e) that we can use. We can tell Ffuf to look only for files that have certain extensions – in our case, .html,.php, and .txt.</p>
<p>We will be using the <a target="_blank" href="https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-medium-words-lowercase.txt">raft-medium-words</a> wordlist for this. Here is the command to look for specific files:</p>
<pre><code>ffuf -u http:<span class="hljs-comment">//localhost:3000/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt -e .php,.html,.txt</span>
</code></pre><p>This command looks for all the files at the root of the domain with an extension of .html, .php, and .txt. Here is the result from DVWA:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-28.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of looking for specific files</em></p>
<p>We have found a long list of files. Even if some files are not served on the web app (403 status), we can learn that there are files, just that we cannot access them yet.</p>
<p>Let’s run the same command, but now, we will only look for files that are accessible to the public. We will use the match code (-mc) flag to only look for files with a status of 200.</p>
<p>Here is the command:</p>
<pre><code>ffuf -u http:<span class="hljs-comment">//localhost:3000/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-medium-words-lowercase.txt -e .php,.html,.txt -mc 200</span>
</code></pre><p>And here is the result.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-31.png" alt="Image" width="600" height="400" loading="lazy">
<em>Files accessible to the public</em></p>
<p>You can see that we have found a few files that we can access. The login.php looks interesting, and we will use it for bypassing authentication in the following sections.</p>
<h3 id="heading-how-to-enumerate-sub-domains-using-ffuf">How to Enumerate Sub Domains using Ffuf</h3>
<p>You can also look for sub-domains in a web app using Ffuf.</p>
<p>You might have guessed the approach that we are going to use. We will replace the subdomain of the URL with the word “FUZZ” and try looking for URLs that are up.</p>
<p>Since my web app is hosted on my local system, it does not contain any subdomains. But in the real world, if you want to enumerate subdomains, here is the command. You can use the <a target="_blank" href="https://github.com/danielmiessler/SecLists/blob/master/Discovery/DNS/subdomains-top1million-5000.txt">sub domains wordlist</a> from seclists. </p>
<pre><code>ffuf -u http:<span class="hljs-comment">//FUZZ.mydomain.com -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt</span>
</code></pre><h3 id="heading-how-to-find-usernames-with-ffuf">How to Find Usernames with Ffuf</h3>
<p>Have you been annoyed when web applications don’t tell you whether you have the wrong username or password? They just tell you “This combination doesn’t work”.</p>
<p>This is to protect the web app from username/email fuzzing attacks. If authentication systems give you specific information about your login attempt, it gets easier for attackers to brute force and discover a list of usernames or emails.</p>
<p>Let’s assume that our web application tells you that you have the wrong username with the message “username does not exist”. We can use this error message to find valid usernames with the following command:</p>
<pre><code>ffuf -w /usr/share/SecLists/Usernames/top-usernames-shortlist.txt -X POST -d <span class="hljs-string">"username=FUZZ&amp;&amp;password=x"</span> -H <span class="hljs-string">"Content-Type: application/x-www-form-urlencoded"</span> -u http:<span class="hljs-comment">//mydomain.com/login -mr "username already exists"</span>
</code></pre><p>Here, we are sending POST requests to the login page, with the fuzzed usernames and a dummy password to check if the expected error message is returned. You can use a <a target="_blank" href="https://github.com/danielmiessler/SecLists/blob/master/Usernames/top-usernames-shortlist.txt">username wordlist</a> from seclists for fuzzing.</p>
<p>The -mr flag is used to match a regular expression. You can have complicated regular expressions or a simple string message to validate the requests.</p>
<p>Here is a sample response.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-32.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-brute-forcing-using-ffuf">Brute Forcing using Ffuf</h3>
<p>Now, let's do some brute forcing with Ffuf. We will try a bunch of common username/password combinations and see if anything works.</p>
<p>If the web application you are testing uses a combination of email and password, you can replace the username wordlist with a email wordlist.</p>
<p>So for this attack, we need two parameters: username and password. Also, we will be using two-word lists: as you guessed, a username wordlist and a password wordlist.</p>
<p>In addition the default placeholder <strong>FUZZ,</strong> Ffuf supports the use of variables. So we will use W1 for our username wordlist and W2 for the password wordlist.</p>
<p>Here is the command: </p>
<pre><code>ffuf -w usernames.txt:W1,<span class="hljs-regexp">/usr/</span>share/wordlists/SecLists/Passwords/Common-Credentials/<span class="hljs-number">10</span>-million-password-list-top<span class="hljs-number">-100.</span>txt:W2 -X POST -d <span class="hljs-string">"username=W1&amp;password=W2"</span> -H <span class="hljs-string">"Content-Type: application/x-www-form-urlencoded"</span> -u http:<span class="hljs-comment">//localhost:3000/login -fc 200</span>
</code></pre><p>If Ffuf finds any valid combinations, you will see the combination in the results. You can also filter by status codes (for examle filter 400 or look for 200) using the -fc or -mc flags to reduce the noise.</p>
<p>Here is a sample response.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/11/image-33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>That was fun, wasn’t it? We can find a lot of interesting information about a web app without using a complicated tool like <a target="_blank" href="https://www.kali.org/tools/burpsuite/">Burpsuite</a>.</p>
<h2 id="heading-how-to-protect-your-site-from-fuzzing">How to Protect Your Site from Fuzzing</h2>
<p>But since we are not the malicious attackers, let’s look at how to defend against fuzzing.</p>
<p>The easiest way to protect your website from fuzzing attacks is to be careful about the type of files on the web server. If you don't want something to be found, don't put it on the web server.</p>
<p>To prevent authentication bypass, it is important not to allow multiple attempts to log in. Most modern websites don't allow more than 5 consecutive login attempts. It is more secure to ask your users to reset their passwords via email instead of letting them try multiple combinations.</p>
<p>You should also be careful about the error messages returned on failed attempts. Displaying that “Email does not exist” or “Password not correct” will let the hacker know that an email or username exists. This just makes their job easier.</p>
<p>Finally, you can use <a target="_blank" href="https://www.cloudflare.com/en-gb/learning/ddos/glossary/web-application-firewall-waf/">Web Application Firewalls</a> (WAF) to monitor traffic and block suspicious IP addresses. WAFs also have options to set alerts if it comes across brute forcing attempts on your authentication methods.</p>
<h2 id="heading-summary">Summary</h2>
<p>Ffuf is a great tool to have in your pentesting toolkit. It is a simple yet fast fuzzer that makes it easy to enumerate directories, discover virtual hosts, and brute-force web applications.</p>
<p>Ffuf also has more options that will help you to look for specific information. It has support for regular expressions, rate limiting of requests, and saving your results to a file.</p>
<p>Hope you enjoyed this article. You can <a target="_blank" href="https://www.linkedin.com/in/manishmshiva/">connect with me on Linkedin</a> or <a target="_blank" href="https://blog.manishmshiva.com/">read more articles on my blog</a>. I’ll see you soon with another article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Cross-Site Request Forgery (CSRF)? Laravel Web Security Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you'll learn about Laravel web security and how to secure your web applications and protect them from Cross-Site Request Forgery, or CSRF attacks. CSRF is a malicious activity that involves an attacker performing actions on behalf o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/laravel-web-security-csrf/</link>
                <guid isPermaLink="false">66ba2fccc346e93df556b001</guid>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sule-Balogun Olanrewaju ]]>
                </dc:creator>
                <pubDate>Tue, 04 Oct 2022 21:40:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/Dark-Neon-Simple-Futuristic-UIUX-Designer-LinkedIn-Banner--7---1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you'll learn about Laravel web security and how to secure your web applications and protect them from Cross-Site Request Forgery, or CSRF attacks.</p>
<p>CSRF is a malicious activity that involves an attacker performing actions on behalf of an authenticated user. Fortunately, Laravel provides out-of-the-box measures to prevent this type of vulnerability.</p>
<p><strong>In this tutorial, you'll learn:</strong></p>
<ul>
<li>What is CSRF?</li>
<li>How to prevent a CSRF request</li>
<li>How and where CSRF verification happens</li>
</ul>
<h2 id="heading-what-is-csrf">What is CSRF?</h2>
<p>CSRF attacks hijack user sessions. They do this by tricking a user into sending a request through hidden form tags or malicious URLs (images or links) without the user's knowledge. </p>
<p>This attack leads to a change in the state of the user session, data leaks, and attackers can sometimes manipulate end-users data in an application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screenshot-2022-10-03-at-14.59.14-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>CSRF Explainer</em></p>
<p>The image above illustrates this scenario where an Actor (User) sends a request from <strong>malicious.xyz</strong> through the <strong>webserver</strong> to <strong>application.xyz</strong>. They then realize that their information has been manipulated by <strong>updating</strong> their <strong>password</strong>.</p>
<h2 id="heading-how-to-prevent-csrf-requests">How to Prevent CSRF Requests</h2>
<p>For each user session, Laravel generates secured tokens that it uses to ensure that the authenticated user is the one requesting the application. </p>
<p>Since this token changes each time a user session is regenerated, a malicious attacker can not access it. </p>
<p>Each time there’s a request to modify user information on the server-side (back end) like <code>POST</code>, <code>PUT</code>, <code>PATCH</code>, and <code>DELETE</code>, you need to include a <code>@csrf</code> in the HTML form request. The <code>@csrf</code> is thus a Blade directive used to generate a hidden token validated by the application. </p>
<p><strong>Blade directive</strong> is the syntax used within the Laravel templating engine called <strong>Blade</strong>. To create a blade file you give it a name – in our case form – followed by the blade extension. This means that the file will have the name <code>form.blade.php</code>.</p>
<p>You use the blade file to render views to users on the webpage. There are a couple of default directives or blade shorthand syntaxes you can use. For example, <code>@if</code> checks if a condition is met, <code>@empty</code> checks if records are not empty, <code>@auth</code> checks if a user is authenticated, and so on. </p>
<p>But here we are more interested with the <code>@csrf</code> directive. Here's how you use it:</p>
<pre><code class="lang-php">&lt;form method=<span class="hljs-string">"POST"</span> action=<span class="hljs-string">"{{route('pay')}}"</span>&gt;

    @csrf

&lt;/form&gt;
</code></pre>
<p>Earlier Laravel releases used to look somewhat like this – both work and do the same thing behind the scenes.</p>
<pre><code class="lang-php">&lt;form method=<span class="hljs-string">"POST"</span> action=<span class="hljs-string">"{{route('pay')}}"</span>&gt;

    &lt;input type=<span class="hljs-string">"hidden"</span> name=<span class="hljs-string">"_token"</span> value=<span class="hljs-string">"{{ csrf_token() }}"</span> /&gt;

&lt;/form&gt;
</code></pre>
<p>When the CSRF token is not present in the form request that gets sent or if it appears invalid, Laravel throws an error message "Page Expired" with a status code 419.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/Screenshot-2022-10-03-at-15.11.43-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Laravel 419 Page Expired</em></p>
<h2 id="heading-how-and-where-csrf-verification-happens">How and Where CSRF Verification Happens</h2>
<p>The <code>VerifyCsrfToken</code> middleware handles CSRF verification within the Laravel application. The middleware is registered in the Kernel.php, and found within the application's web route middleware group. This means the middleware is triggered for requests within the Web, not related to APIs.</p>
<pre><code class="lang-php"><span class="hljs-keyword">protected</span> $middlewareGroups = [
        <span class="hljs-string">'web'</span> =&gt; [
           .
           .
           .
           .
           .
            \App\Http\Middleware\VerifyCsrfToken::class,
        ],
    ];
</code></pre>
<p>The VerifyCsrfToken middleware extends the <code>Illuminate\Foundation\Http\Middleware\VerifyCsrfToken</code> class. This means that the CSRF verification is housed within the class. </p>
<p>Let's dive deeper to learn how Laravel handles the CSRF verification. </p>
<p>Within the class, we have the <code>tokensMatch</code> function.</p>
<pre><code class="lang-php"><span class="hljs-keyword">protected</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tokensMatch</span>(<span class="hljs-params">$request</span>)
    </span>{
        $token = <span class="hljs-keyword">$this</span>-&gt;getTokenFromRequest($request);

        <span class="hljs-keyword">return</span> is_string($request-&gt;session()-&gt;token()) &amp;&amp;
               is_string($token) &amp;&amp;
               hash_equals($request-&gt;session()-&gt;token(), $token);
    }
</code></pre>
<p>The function does two things:</p>
<ol>
<li><code>$this-&gt;getTokenFromRequest</code> gets the token from the incoming request attached via a hidden field or the request's header. The token is decrypted and then returned to the token variable.</li>
</ol>
<pre><code class="lang-php"><span class="hljs-keyword">protected</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getTokenFromRequest</span>(<span class="hljs-params">$request</span>)
    </span>{
        $token = $request-&gt;input(<span class="hljs-string">'_token'</span>) ?: $request-&gt;header(<span class="hljs-string">'X-CSRF-TOKEN'</span>);

        <span class="hljs-keyword">if</span> (! $token &amp;&amp; $header = $request-&gt;header(<span class="hljs-string">'X-XSRF-TOKEN'</span>)) {
            <span class="hljs-keyword">try</span> {
                $token = CookieValuePrefix::remove(<span class="hljs-keyword">$this</span>-&gt;encrypter-&gt;decrypt($header, <span class="hljs-built_in">static</span>::serialized()));
            } <span class="hljs-keyword">catch</span> (DecryptException $e) {
                $token = <span class="hljs-string">''</span>;
            }
        }

        <span class="hljs-keyword">return</span> $token;
    }
</code></pre>
<ol start="2">
<li>Cast both request token and session to a string and then use the PHP built-in hash_equals to compare if both strings are equal using the same time. The result of this operation is always a <strong>bool (true) or (false)</strong>.</li>
</ol>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>In this article, you have learned about CSRF, how to handle and protect against it, and the behind-the-scenes of how Laravel does the verification.</p>
<p>You can read more about this in the <a target="_blank" href="https://laravel.com/docs/9.x/csrf">Laravel documentation</a>. And you can read more about <a target="_blank" href="https://www.php.net/manual/en/function.hash-equals.php">PHP hash equals in the docs here</a>.</p>
<p>Happy Coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Personal Digital Security – How to Protect Yourself Online for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ By Megan Kaczanowski How do you protect yourself online without having to remember a million impossible passwords?  This is an (actually) easy to implement guide, which is the digital equivalent of locking your house when you leave.  Taking these ste... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/personal-digital-security-an-intro/</link>
                <guid isPermaLink="false">66d46068ffe6b1f641b5fa44</guid>
                
                    <category>
                        <![CDATA[ cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 30 Aug 2022 16:57:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/pexels-pixabay-207580--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Megan Kaczanowski</p>
<p>How do you protect yourself online without having to remember a million impossible passwords? </p>
<p>This is an (actually) easy to implement guide, which is the digital equivalent of locking your house when you leave. </p>
<p>Taking these steps won’t make you hack-proof (just as locking your house won’t make your house burglar-proof) but it will make you much safer online. It also won’t make your digital life any harder than carrying keys makes your day-to-day life. </p>
<p>If you're convinced that this is too much work, start with one item at a time. If you're really insistent on not reading the whole list, start with the first 5 items here.</p>
<h2 id="heading-how-to-protect-yourself-online">How to Protect Yourself Online</h2>
<h3 id="heading-set-passwords-on-all-your-devices">Set Passwords on All Your Devices</h3>
<p>Setting passwords on all your devices – like laptops, phones, tablets, routers, and so on – is the first order of business. </p>
<p>For any devices which still have default passwords enabled, change them (think about your wifi router, a home camera system like Amazon’s Blink, or a smart TV).</p>
<p>Don't reuse your passwords. That can be very difficult, but a tool like a password manager can make that much easier. Which brings us to...</p>
<h3 id="heading-use-a-password-manager">Use a Password Manager</h3>
<p>Password managers let you create one ‘master password’ and then securely store (and generate) your strong, unique passwords for each account. They give you the security of having separate passwords for every account, but the convenience of only having to remember one password. </p>
<p>I love <a target="_blank" href="https://1password.com/sign-up/">1Password</a> ($3/month) as it has an app and a browser extension (so it can autofill your passwords for you across apps and devices), but <a target="_blank" href="https://keepass.info/">KeePass</a> is a secure free option. </p>
<p>Password managers also allow you to securely store all kinds of information such as insurance numbers, bank account data, and so on. Think of it as the digital equivalent of having a fire-proof box with all your important documents. </p>
<p>Setting it up the first time (and putting all your accounts and passwords into it) is a giant pain. So go do it now. Seriously, I’ll wait.</p>
<h3 id="heading-go-back-and-do-step-2">Go back and do step 2.</h3>
<p>At least put your bank and credit card accounts, email accounts, and social media into your new password manager. Spend 5 minutes a day adding new accounts to your password manager. Over time, it will save you a significant amount of time and stress. </p>
<p>Why? Often when passwords are leaked in a breach, hackers will use something called ‘credential stuffing’. That means they will take that password and plug it into an automated tool which will try using it in as many accounts as possible. If all your accounts have the same password, either your accounts could get breached, or you have to change ALL of your passwords every time you hear about a new breach. </p>
<p>Skip the stress and get a password manager (also, set up (free!) alerts <a target="_blank" href="https://haveibeenpwned.com/">here</a> so you know when your account data has been leaked).</p>
<h3 id="heading-update-everything">Update EVERYTHING.</h3>
<p>Don’t click postpone or ignore on those pop up updates. Software updates are most often released in response to reported security vulnerabilities. Leaving your devices unpatched can leave them vulnerable to attack. </p>
<h3 id="heading-back-up-your-data-regularly">Back Up Your Data Regularly</h3>
<p>You'll want to back up your data in case you are infected with malware. You can use iCloud (but make sure you've used a secure password!), other cloud service, or a physical hard drive (I use <a target="_blank" href="https://www.amazon.com/Western-Digital-Elements-Portable-External/dp/B06W55K9N6/ref=sxin_16_mod_primary_new?asc_contentid=amzn1.osa.f1ae4c39-ef0f-4c9f-b46f-599439a8839a.ATVPDKIKX0DER.en_US&amp;asc_contenttype=article&amp;ascsubtag=amzn1.osa.f1ae4c39-ef0f-4c9f-b46f-599439a8839a.ATVPDKIKX0DER.en_US&amp;creativeASIN=B06W55K9N6&amp;crid=QOGPNSQKBZTP&amp;cv_ct_cx=1tb+hard+drive&amp;cv_ct_id=amzn1.osa.f1ae4c39-ef0f-4c9f-b46f-599439a8839a.ATVPDKIKX0DER.en_US&amp;cv_ct_pg=search&amp;cv_ct_we=asin&amp;cv_ct_wn=osp-single-source-earns-comm&amp;keywords=1+tb+harddrive&amp;linkCode=oas&amp;pd_rd_i=B06W55K9N6&amp;pd_rd_r=79c6fe5b-c726-4bb9-9535-bd2d3e9d3f73&amp;pd_rd_w=jI01U&amp;pd_rd_wg=HwiQE&amp;pf_rd_p=5846ecd6-3f37-4a28-8efc-9c817c03dbe9&amp;pf_rd_r=7HWG05FMQXGZXSAC25KV&amp;qid=1643406423&amp;sbo=RZvfv%2F%2FHxDF%2BO5021pAnSA%3D%3D&amp;sprefix=1+tb+hardrive%2Caps%2C126&amp;sr=1-2-64f3a41a-73ca-403a-923c-8152c45485fe&amp;tag=pcwosp-20">this one</a>).</p>
<h3 id="heading-use-antivirus-software-and-update-it-regularly">Use Antivirus Software (and Update it Regularly).</h3>
<p>If you can afford it, antivirus is a good idea. It's not perfect, but it's better than nothing and typically a good idea for the average user. I use <a target="_blank" href="https://www.malwarebytes.com/lp/sem/en/?gclid=CjwKCAjw4MP5BRBtEiwASfwAL9UcYA_lZYmyPRvqH48JTttDU3vtu_mWGINP1KVObSrkMI7GnID_5xoC8dUQAvD_BwE">Malware Bytes</a>.</p>
<h3 id="heading-limit-the-number-of-internet-connected-devices-you-have">Limit the Number of Internet-Connected Devices You Have.</h3>
<p>Think before purchasing devices with internet connectivity. Is an internet connected kettle worth the potential security vulnerabilities (spoiler alert: it usually isn’t.)? </p>
<p>Internet of Things devices are rarely updated and generally aren’t designed with security in mind. That means they’re often riddled with vulnerabilities. And if they’re on your home wifi network, can leave hackers an easy way in. </p>
<p>Often (but not always), more expensive devices will do a better job of protecting your security.</p>
<h3 id="heading-regularly-review-your-social-media-privacy-settings">Regularly Review Your Social Media Privacy Settings.</h3>
<p>You might be surprised at how much information is being shared. When creating new social media accounts or posts, think before you post it. The more information hackers have on you, the easier their job is. </p>
<p>Try to avoid posting too much personal information on your social media pages, as well as avoiding posting things like pictures of your credit card or boarding pass.</p>
<p>For folks who rely on social media as an income stream, wipe the metadata from your photos and videos before posting (metadata can include specific location and device information which can be accessed by anyone viewing the photo/video).</p>
<h3 id="heading-avoid-connecting-to-free-wifi-hotspots">Avoid Connecting to Free Wifi Hotspots.</h3>
<p>Free wifi hotspots are often targeted by hackers and can put you at risk of MitM attacks (Man in the Middle Attacks) where a hacker spies on your internet traffic, and may even modify it without you knowing. </p>
<p>If you can’t avoid connecting to these hotspots, buy a VPN service.</p>
<h3 id="heading-buy-a-vpn-service">Buy a VPN service.</h3>
<p>A VPN (virtual private network) provides online privacy and anonymity. This can protect you, even when you connect to public wifi hotspots. </p>
<p>I recommend using one which you can install it on multiple devices, enable automatic connection (so as soon as you connect to the internet you are automatically connected to the VPN), and select which country you want your traffic to come from. </p>
<p>The <a target="_blank" href="https://www.torproject.org/download/">TOR browser</a> is a free service, however it is less convenient, and can slow down your connection speed.</p>
<h3 id="heading-enable-multi-factor-authentication-on-your-primary-email-account">Enable Multi-Factor Authentication on Your Primary Email Account.</h3>
<p>Also known as MFA, or 2FA for 2 Factor authentication. This means that even if someone has your password, they can’t access your account. </p>
<p>Multi-factor authentication requires that you have two things to login: something you know (your password) and something you have (a code from an SMS, a code from an app like Google Authenticator, or a hardware key like YubiKey). </p>
<p>A hardware key is best, followed by an app, followed by SMS (which is still better than nothing). </p>
<p>If you’re feeling really motivated, also do so on your other accounts, but at least do so on your most important accounts. For a full list of websites which support 2FA, check <a target="_blank" href="https://twofactorauth.org/">here.</a></p>
<h3 id="heading-use-an-end-to-end-encrypted-chat-application">Use an End to End Encrypted Chat Application.</h3>
<p>End to end encryption means that your data is encrypted on the device, and that no one can read or change your message in transit (not your internet service provider (ISP), hackers, and so on). </p>
<p>In order for someone to read this type of message, generally a hacker would have to have access to your device already. iMessage, WhatsApp, Wickr, and Signal are all free options, and Facebook Messenger is secure if you choose the ‘secret’ option when starting a chat. </p>
<p>Personally, I highly recommend Signal, as it’s open-source, free, and not owned by any major tech companies. </p>
<h3 id="heading-check-out-mysudohttpsmysudocommysudo-plans-and-privacyhttpsprivacycom">Check out <a target="_blank" href="https://mysudo.com/mysudo-plans/">MySudo</a> and <a target="_blank" href="https://privacy.com/">Privacy</a>.</h3>
<p>MySudo provides phone numbers via an app with plans starting at $0.99/month. </p>
<p>These are really great for using on dating apps, food delivery apps, or any other time when you may not want to give out your personal number (because your personal phone number is being used as a password reset option or as a form of multifactor authentication). </p>
<p>They also provide virtual debit cards (though Privacy offers better virtual card options for free). Think of this as the online version of paying with pre-paid Visa cards. You can have a unique debit card number for every single purchase online so you don't have to worry the next time a vendor gets breached and credit card details are stolen.</p>
<h3 id="heading-finally-be-careful-online">Finally, Be Careful Online.</h3>
<p>Be wary of clicking links from unknown senders (in strange social media requests, texts, or emails), avoid running programs like Adobe Flash (which is notoriously insecure), and avoid websites which might give you malware (adult video streaming sites are often loaded with malicious content, as are free streaming or download sites). </p>
<p>If you need to access the link in an email (such as an alert from your bank or social media accounts), navigate to the app or website directly, rather than clicking the link in the email. </p>
<p>At the end of the day, don’t overthink it.</p>
<p><img src="https://megankaczanowski.com/content/images/2020/08/Screen-Shot-2020-08-08-at-1.02.13-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://xkcd.com/538/">https://xkcd.com/538/</a></em></p>
<p>Want to learn more? </p>
<ul>
<li><a target="_blank" href="https://megankaczanowski.com/how-to-protect-yourself-online/">What to do if your information was included in a data breach</a></li>
<li><a target="_blank" href="https://motherboard.vice.com/en_us/article/d3devm/motherboard-guide-to-not-getting-hacked-online-safety-guide">The Motherboard Guide to Not Getting Hacked</a></li>
<li><a target="_blank" href="https://www.wired.com/2017/12/digital-security-guide/">The WIRED Guide to Digital Security</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ HTTP vs HTTPS – What's the Difference? ]]>
                </title>
                <description>
                    <![CDATA[ By Karlgusta Annoh We interact with HTTP and HTTPS a lot in our day-to-day lives, but many people don't know the difference.  Most computer users just see that the browser is telling them their application is not safe and that a hacker might want to ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/http-vs-https/</link>
                <guid isPermaLink="false">66d45f6551f567b42d9f845d</guid>
                
                    <category>
                        <![CDATA[ http ]]>
                    </category>
                
                    <category>
                        <![CDATA[ https ]]>
                    </category>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 16 Aug 2022 17:47:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/07/HTTP-VS-HTTPS.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Karlgusta Annoh</p>
<p>We interact with HTTP and HTTPS a lot in our day-to-day lives, but many people don't know the difference. </p>
<p>Most computer users just see that the browser is telling them their application is not safe and that a hacker might want to steal their important information. This leads to users running away faster than Usain Bolt's current record.</p>
<p>But this is avoidable. That is where HTTPS comes in and replaces HTTP. And we are going to discuss that today. :)</p>
<h2 id="heading-heres-what-well-cover">Here's What We'll Cover:</h2>
<ol>
<li>What is HTTP?</li>
<li>How HTTP works</li>
<li>Features of HTTP</li>
<li>How to know if a site is not secure</li>
<li>Are all HTTP websites insecure?</li>
<li>What is HTTPS?</li>
<li>How HTTPS works</li>
<li>Features of HTTPS</li>
<li>How encryption works</li>
<li>How to know if a site is secure</li>
<li>What is an SSL certificate?</li>
<li>How does SSL work?</li>
<li>How can I get SSL for my website?</li>
<li>Where can I get an SSL certificate?</li>
<li>Can I get an SSL certificate for free?</li>
<li>The main differences between HTTPS and HTTP</li>
<li>Conclusion</li>
</ol>
<h2 id="heading-what-is-http">What is HTTP?</h2>
<p>Hyper Text Transfer Protocol, or HTTP, is a communication method between your browser and the site you want to visit (web server).</p>
<p>This allows you to get the information that you need from the server on your browser.</p>
<p>A good way to understand HTTP and HTTPS is by using an analogy. We know that browsers and servers communicate using HTTP. HTTP is usually in plain text. Many people around the world speak English. If a hacker who knows English hacks into your computer, they can easily see any password you input.</p>
<p>Here in Kenya, in my mother tongue, we speak Turkana. If you don't speak the language and you come to Kenya and find two Turkanas speaking, you may not understand what they are saying. </p>
<p>That's the beauty of HTTPS. It is encrypted so that the hacker hopefully doesn't understand the communication between the browser and the server.</p>
<p>![Client to server](https://user-images.githubusercontent.com/33565767/178446926-d904cc04-57cd-4427-bdcc-e76c35f8b51b.png "client/browser communicating with server")</p>
<p>If I was to go to http://www.google.com, I would expect to see Google's default page.</p>
<p>![Googles default page](https://user-images.githubusercontent.com/33565767/178450768-e1fed4a5-993d-4d49-a47f-83cce6473085.png "Google's default page")</p>
<p>The client, which in most cases is the web browser, sends a message which in computer terms is a request. Then the server will give back an answer, which is the response.</p>
<p>HTTP is very useful in sending HTML documents as well as images and videos to the web browser for the user to see. It is also used to send data to the server in HTML forms.</p>
<p>![Where HTTP Protocol sits](https://user-images.githubusercontent.com/33565767/178460366-d0568e2d-d107-4afe-a778-0ce1d224b176.png "HTTP Protocol is between the web browser(client) and the web server, which is in constant communication with the server side script and the database.")</p>
<h2 id="heading-how-http-works">How HTTP Works</h2>
<p>HTTP sends data through plain text. For example, if you were to access your bank's web page and they are using HTTP, a hacker may be able to access it and read any information that you send.</p>
<p>This is where HTTPS comes in. Many companies have implemented HTTPS to be able to allow their users to send data securely. We'll discuss this further below.</p>
<h2 id="heading-features-of-http">Features of HTTP</h2>
<ul>
<li>Plain text. Initially when HTTP was developed, developers had one thing in mind: to serve only text documents. Now, HTTP is used in more ways than it was initially intended.</li>
<li><p>Layer 7 protocol. HTTP is a layer 7 protocol in the OSI Model of networking. Layer 7 is the application layer. This layer is the top-most layer in the OSI model. The other layers include the physical, data link, network, transport, session, and presentation layer. To learn more about the OSI model, you can check out this free video on freeCodeCamp's YouTube channel by Brian Ferrill about how the internet works. There are more cookies in the jar other than the OSI model. <a target="_blank" href="https://www.youtube.com/watch?v=qiQR5rTSshw&amp;t=27s&amp;ab_channel=freeCodeCamp.org">Computer Networking Course - Network Engineering [CompTIA Network+ Exam Prep]</a></p>
</li>
<li><p>Insecure. When you send HTTP requests they are sent through plain text. Also, when you get a response, you get it through plain text. This means that anyone who can access the requests and the responses can read them.
![Insecure connection](https://user-images.githubusercontent.com/33565767/179723161-3ec27c27-df79-4749-b810-974583cf1687.png "Insecure connection during a normal HTTP connection by the user")</p>
</li>
<li>Light weight. The advantage of HTTP is that it is very lightweight. It is therefore very fast since it doesn't do the encryption stuff to secure the data, like HTTPS does.</li>
<li>HTTP usually listens on port 80.</li>
</ul>
<h2 id="heading-how-to-know-if-a-site-is-not-secure">How to Know if a Site is Not Secure</h2>
<p>When a site is not secure, Chrome will usually send a warning that says <code>Your connection is not private</code>.
![HTTP Not secure](https://user-images.githubusercontent.com/33565767/182329336-d405d5b4-f5bb-45df-b936-aa1d04b9dffd.png "Your connection is not secure when going to a site that is not secure")</p>
<p>On Chrome, the URL bar will usually show <code>Not Secure</code> in red if a site is not secure.
![Not secure URL image](https://user-images.githubusercontent.com/33565767/182329466-d2db68a8-7033-4f64-bb66-0665e8fc0c62.png "URL of an insecure website")</p>
<h2 id="heading-are-all-http-websites-insecure">Are All HTTP Websites Insecure?</h2>
<p>Well, let's look at an example. Imagine you are browsing a meme website, laughing at each one as you scroll by. If it is using HTTP, then you are off the hook. It's not a big deal.</p>
<p>You get bored and decide to go to your bank's site to access your account on your browser. If the site is not using HTTPS, you might as well be serving your account details to a hacker on a silver plate.</p>
<p>So the bottom line is, if you're browsing inconsequential information, HTTP is ok. But if you are dealing with insecure information, HTTP isn't enough.</p>
<h2 id="heading-what-is-https">What is HTTPS?</h2>
<p>Hyper Text Transfer Protocol Secure, or HTTPS, is a way that communication can happen SECURELY between your browser and the site you want to visit (web server).</p>
<h2 id="heading-how-https-works">How HTTPS Works</h2>
<p>HTTPS makes a secure connection by using a secure protocol that encrypts your data. </p>
<p>For most websites, the best way to have HTTPS is by getting an SSL (Secure Sockets Layer) Certificate or a TLS (Transport Layer Security) certificate.</p>
<p>At the moment, SSL has become advanced enough that it supports TLS. So you don't need to get a TLS certificate.</p>
<h2 id="heading-features-of-https">Features of HTTPS</h2>
<ul>
<li>Encrypts data. Data encryption happens through the TLS/SSL protocol.</li>
<li>It is a layer 4 (Transport layer) protocol. </li>
<li>Key exchanges of public and private keys happen in HTTPS to encypt and decrypt data.</li>
<li>Compared to HTTP, is it heavier. When encrpytion and decryption happens in HTTPS, it becomes heavier.</li>
<li>HTTP listens on port 443.<h2 id="heading-how-encryption-works">How Encryption Works</h2>
</li>
</ul>
<p>![How encryption works](https://user-images.githubusercontent.com/33565767/180215739-5e731309-eda1-4993-927c-c9daa400c3c5.png "I am a dev from the client text passing through an encyption")</p>
<p>Let's say I type "I am a dev". This text gets encrypted when I click send, and then it gets decrypted on the server side.</p>
<p>The same is also true from the server side. If I get a response from the server, it will first get encrypted, then it will get decrypted on the client side.</p>
<h2 id="heading-how-to-know-if-a-site-is-secure">How to Know if a Site is Secure</h2>
<p>To know that a site is secure, you usually look at the URL bar where you can see a lock. If there is a lock, the connection from the client to the server is secure.</p>
<p>![Showing that the site is secure](https://user-images.githubusercontent.com/33565767/178449484-738fb908-901d-4a61-9f8f-fa5a39029012.png "A padlock that shows the site is secure on the URL")</p>
<p>When you click on the lock icon, it tells you more about the secure connection.</p>
<p>![Shows site is secure](https://user-images.githubusercontent.com/33565767/180213859-21460cfa-6a8c-484e-81e5-5dba4fc31f2a.png "The URL section with more details of a secure site")</p>
<h2 id="heading-what-is-an-ssl-certificate">What is an SSL Certificate?</h2>
<p>An SSL certificate is a little file that tells browsers that your website –for example, freecodecamp.org – is who it says it is, and that it is reliable.</p>
<p>In order to authenticate, the certificate is able to confirm to the client (user) that the server they are connecting to is the one that manages that domain. All this is to keep the user safe from security issues such as domain spoofing.</p>
<p>It contains a public key and tells you who the owner of the website is that you are trying to connect to. If a website doesn't have an SSL certificate, it cannot be encrypted with TLS.</p>
<p>You can personally create your own SSL certificate (also known as a self-signed certificate), if you are the website owner. The problem with this approach is that browsers like Chrome don't trust these certificates. They prefer trusting certificates that are issued by a certificate authority.</p>
<h2 id="heading-how-does-ssl-encryption-work">How Does SSL Encryption Work?</h2>
<p>There are two types of SSL encryption, asymmetric and symmetric. The combination of asymmetric and symmetric is what makes SSL Encryption work. Let's look at them below to learn more.</p>
<h3 id="heading-what-is-asymmetric-encryption">What is asymmetric encryption?</h3>
<p>In Asymmetric encryption, you have two keys. These are:</p>
<ol>
<li>Public key.</li>
<li>Private key.</li>
</ol>
<p>![Asymmetric encryption](https://user-images.githubusercontent.com/33565767/181718454-847858dc-0df5-4bc5-bfaf-b6210c571d8f.png "Asymmetric (Public key) encryption")</p>
<p>The client/user/browser gives the public key to the server with which they are communicating. Then, the encyption happens with the help of the public key, and the decryption happens with the help of the server's private key.</p>
<p>The private key can only be found on that particular server. No one else has it. This shows you why asymmetric encryption is stronger and tougher to hack, because it has two different keys, the private and public key. The two keys work together to make sure the data is more secure.</p>
<p>This also tells you why the size of this encryption is 1024/2048 bits.</p>
<h3 id="heading-what-is-symmetric-encryption">What is symmetric encryption?</h3>
<p>In symmetric encryption, it's very simple. You have one key, and that's it. The client uses one key for encryption, and the server uses the same key for decrypting the data.</p>
<p>Symmetric encryption is very light weight. The size is 128/256 bits. But it is a bit easier to hack into as compared to asymmetric. This doesn't mean it is not useful. When we use SSL, we combine Asymmetric and Symmetric to be able to make the communication safer and more secure.</p>
<p>![Symmetric encryption](https://user-images.githubusercontent.com/33565767/181720497-326e0dd9-5e0b-4bfb-b01a-2effec5ab9e0.png "How symmetric encryption works by using one key on the client side to encrypt and the same key on the server side to decrypt")</p>
<h3 id="heading-how-asymmetric-symmetric-encryption-work">How asymmetric + symmetric encryption work</h3>
<p>The combination of both asymmetric and symmetric is now the double-sided wall. 
![Asymmetric and Symmetric](https://user-images.githubusercontent.com/33565767/182565306-224f199a-da88-4a68-be81-707636cc1069.png "How asymmetric and symmetric encryption work by client first sending a Hello to the server. The server then sends to the client, its public key and certificate in response. The client on step 3, sends a session key that is encrypted using the public key. On step 4, the server will decrypt the session key using the server's private key. Finally, step 5, the connection is established between the client and the server.")</p>
<p>In the first step, the server will send to the browser the asymmetric public key. As we now know, the asymmetric key has both the public key and the private key. Therefore, the browser will receive the public key.</p>
<p>After this, the browser generates a session key.</p>
<p>Symmetric encryption uses only one single key for both the client and the server. So what will happen is, the browser will generate a local session key. This is a symmetric encryption session key. It will then encrypt it, with the use of the public key which is asymmetric, given in the first step. The locally generated session key will then be combined with the public key, and sent to the server.</p>
<p>The server will then use a private key to decrypt the encrypted session key it has received. In this particular step, the server will use asymmetric private key to decrypt the session key it has received.</p>
<p>Now, once the decryption has happened, the server and the browser will use the session key for communication. The session key will only be used for that specific session.</p>
<p>Let's say you close your browser, and maybe sign in the next day – everything starts all over again. Session keys get created again.</p>
<h2 id="heading-how-can-i-get-ssl-for-my-website">How Can I Get SSL for My Website?</h2>
<p>If you are a website owner, you can acquire an SSL certificate from a certificate issuing authority. </p>
<p>You will then need to install the certificate on you web server where your website is hosted. Most of the time, the hosting company where you host your website handles this process for you.</p>
<h2 id="heading-where-can-i-get-an-ssl-certificate">Where Can I Get an SSL Certificate?</h2>
<p>There are organizations that issue security certificates. These organizations are called certificate authorities. Some of these certificate authorities include: DigiCert, Comodo, and many others.</p>
<p>Many developers get certificates from these organizations. Since they are the most widely used certificate issuers, browsers usually trust certificates from these organizations.</p>
<h2 id="heading-can-i-get-an-ssl-certificate-for-free">Can I Get an SSL Certificate for Free?</h2>
<p>Cloudflare offers SSL certificates for free. It is one of the first internet security companies to do so. </p>
<p>If you want to get one, you can <a target="_blank" href="https://www.cloudflare.com/ssl/">check it out here</a>.</p>
<h2 id="heading-what-is-https-used-for">What is HTTPS Used For?</h2>
<p>HTTPS helps a lot with security. Without it, passing sensitive information becomes a big challenge especially if your business requires a secure way of communication. </p>
<p>Sites that accept online payments like ecommerce sites typically require HTTPS. This is to avoid information such as credit card details and login information from being stolen (Source: <a target="_blank" href="https://www.entrepreneur.com/article/281633">Tony Messer</a>).</p>
<h2 id="heading-the-main-differences-between-https-and-http">The Main Differences between HTTPS and HTTP</h2>
<ul>
<li>The encryption layer is enabled in HTTPS while there is no encryption layer in HTTP.</li>
<li>Your data is protected in HTTPS while in HTTP it is not.</li>
<li>Your ranking is boosted in Google when you use HTTPS while with HTTP, you don't get any ranking boost.</li>
<li>You are protected against phishing when you use HTTPS while there is not protection when using HTTP.</li>
<li>You are compliant with the regulations of the payment industry when you use HTTPS while HTTP is non-compliant.</li>
<li>Loading HTTPS in the first few seconds may be slower than loading HTTP.</li>
<li>Getting SSL certificates can cost money while there is no certification costs with HTTP.</li>
<li>While using HTTPS, you become buddies with Google Chrome. Google Chrome doesn't like HTTP and therefore you will always be getting unsecured site notifications.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>HTTP and HTTPS are very important in our day to day lives as developers. The communication between the browser and the server is what fuels much the work we do.</p>
<p>By protecting your users' data as much as you're able so their information doesn't get stolen, you'll gain their trust and provide a better user experience.</p>
<p>See you soon.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Rate Limiter using Bucket4J and Redis ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial we will learn how to implement rate limiting in a scaled service.We will use the Bucket4J library to implement it and we will use Redis as a distributed cache. Why Use Rate Limiting? Let's get started with some basics to make sure we... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/rate-limiting-with-bucket4j-and-redis/</link>
                <guid isPermaLink="false">66c37625f278f15f931a342a</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abhinav Pandey ]]>
                </dc:creator>
                <pubDate>Fri, 01 Apr 2022 19:05:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/Rate-Limiter-with-Bucket4J-and-Redis.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial we will learn how to implement rate limiting in a scaled service.<br>We will use the <a target="_blank" href="https://github.com/vladimir-bukhtoyarov/bucket4j">Bucket4J</a> library to implement it and we will use <a target="_blank" href="https://redis.io/">Redis</a> as a distributed cache.</p>
<h2 id="heading-why-use-rate-limiting">Why Use Rate Limiting?</h2>
<p>Let's get started with some basics to make sure we understand the need for rate limiting and introduce the tools we'll be using in this tutorial.</p>
<h3 id="heading-problem-with-unlimited-rates">Problem with Unlimited Rates</h3>
<p>If a public API like the Twitter API allowed its users to make an unlimited number of requests per hour, it could lead to:</p>
<ul>
<li>resource exhaustion</li>
<li>decreasing quality of the service</li>
<li>denial of service attacks</li>
</ul>
<p>This might result in a situation where the <strong>service is unavailable or slow</strong>. It could also lead to more <strong>unexpected costs</strong> being incurred by the service.</p>
<h3 id="heading-how-rate-limiting-helps">How Rate Limiting Helps</h3>
<p>Firstly, rate-limiting can prevent denial of service attacks. When coupled with a deduplication mechanism or API keys, rate limiting can also help prevent distributed denial of service attacks.</p>
<p>Secondly, it helps in estimating traffic. This is very important for public APIs. This can also be coupled with automated scripts to monitor and scale the service.</p>
<p>And thirdly, you can use it to implement tier-based pricing. This type of pricing model means that users can pay for a higher rate of requests. The Twitter API is an example of this.</p>
<h3 id="heading-the-token-bucket-algorithm">The Token Bucket Algorithm</h3>
<p>Token Bucket is an algorithm that you can use to implement rate limiting. In short, it works as follows:</p>
<ol>
<li>A bucket is created with a certain capacity (number of tokens).</li>
<li>When a request comes in, the bucket is checked. If there is enough capacity, the request is allowed to proceed. Otherwise, the request is denied.</li>
<li>When a request is allowed, the capacity is reduced.</li>
<li>After a certain amount of time, the capacity is replenished.</li>
</ol>
<h3 id="heading-how-to-implement-token-bucket-in-a-distributed-system">How to Implement Token Bucket in a Distributed System</h3>
<p>To implement the token bucket algorithm in a distributed system, we need to use a <strong>distributed cache</strong>.</p>
<p>The cache is a <strong>key-value store</strong> to store the bucket information. We will use a Redis cache to implement this.</p>
<p>Internally, Bucket4j allows us to plug in any implementation of the Java JCache API. The <a target="_blank" href="https://redisson.org/">Redisson</a> client of Redis is the implementation we will use.</p>
<h2 id="heading-project-implementation">Project Implementation</h2>
<p>We will use the <a target="_blank" href="https://spring.io/projects/spring-boot">Spring Boot</a> framework to build our service.</p>
<p>Our service will contain the below components:</p>
<ol>
<li>A simple REST API.</li>
<li>A Redis cache connected to the service – using the Redisson client.</li>
<li>The Bucket4J library wrapped around the REST API.</li>
<li>We'll connect Bucket4J to the JCache interface which will use the Redisson client as the implementation in the background.</li>
</ol>
<p>First, we will learn to rate limit the API for all requests. Then we will learn to implement a more complex rate limiting mechanism per user or per pricing tier.</p>
<p>Let's start with the project setup.</p>
<h3 id="heading-install-dependencies">Install Dependencies</h3>
<p>Let's add the below dependencies to our <em>pom.xml</em> (or <em>build.gradle</em>) file.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- To build the Rest API --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Redisson Starter = Spring Data Redis starter(excluding other clients) and Redisson client --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.redisson<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>redisson-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.17.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Bucket4J starter = Bucket4J + JCache --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.giffing.bucket4j.spring.boot.starter<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>bucket4j-spring-boot-starter<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>0.5.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
</code></pre>
<h3 id="heading-cache-configuration">Cache Configuration</h3>
<p>Firstly, we need to start our Redis server. Let's say we have a Redis server running on port 6379 on our local machine.</p>
<p>We need to perform two steps:</p>
<ol>
<li>Create a connection to this server from our application.</li>
<li>Set up JCache to use the Redisson client as the implementation.</li>
</ol>
<p><a target="_blank" href="https://github.com/redisson/redisson/wiki/14.-Integration-with-frameworks/#144-jcache-api-jsr-107-implementation">Redisson's documentation</a> provides concise steps to implement this in a regular Java application. We're going to implement the same steps, but in Spring Boot.</p>
<p>Let's look at the code first. We need to create a Configuration class to create the required beans.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RedisConfig</span>  </span>{

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Config <span class="hljs-title">config</span><span class="hljs-params">()</span> </span>{
        Config config = <span class="hljs-keyword">new</span> Config();
        config.useSingleServer().setAddress(<span class="hljs-string">"redis://localhost:6379"</span>);
        <span class="hljs-keyword">return</span> config;
    }

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> CacheManager <span class="hljs-title">cacheManager</span><span class="hljs-params">(Config config)</span> </span>{
        CacheManager manager = Caching.getCachingProvider().getCacheManager();
        cacheManager.createCache(<span class="hljs-string">"cache"</span>, RedissonConfiguration.fromConfig(config));
        <span class="hljs-keyword">return</span> cacheManager;
    }

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function">ProxyManager&lt;String&gt; <span class="hljs-title">proxyManager</span><span class="hljs-params">(CacheManager cacheManager)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> JCacheProxyManager&lt;&gt;(cacheManager.getCache(<span class="hljs-string">"cache"</span>));
    }
}
</code></pre>
<p><strong>What does this do?</strong></p>
<ol>
<li>Creates a configuration object that we can use to create a connection.</li>
<li>Creates a cache manager using the configuration object. This will internally create a connection to the Redis instance and create a hash called "cache" on it.</li>
<li>Creates a proxy manager that will be used to access the cache. Whatever our application tries to cache using the JCache API, it will be cached on the Redis instance inside the hash named "cache".</li>
</ol>
<h3 id="heading-build-the-api">Build the API</h3>
<p>Let's create a simple REST API.</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RateLimitController</span> </span>{
    <span class="hljs-meta">@GetMapping("/user/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getInfo</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable("id")</span> String id)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello "</span> + id;
    }
}
</code></pre>
<p>If I hit the API with the URL <code>http://localhost:8080/user/1</code>, I will get the response <code>Hello 1</code>.</p>
<h3 id="heading-bucket4j-configuration">Bucket4J Configuration</h3>
<p>To implement the rate limiting, we need to configure Bucket4J. Thankfully, we do not need to write any boilerplate code due to the starter library.</p>
<p>It also <strong>automatically detects the ProxyManager bean</strong> we created in the previous step and uses it to cache the buckets.</p>
<p>What we do need to do is configure this library around the API we created.<br>Again there are multiple ways to do this.</p>
<p>We can go for <a target="_blank" href="https://github.com/MarcGiffing/bucket4j-spring-boot-starter#configuration-via-properties">property-based configuration</a> which is defined in the starter library.<br>This is the most convenient way for simple cases like rate-limiting for all users or all guest users.</p>
<p>However, if we want to implement something more complex like a rate limit for each user, it's better to write custom code for it.</p>
<p>We are going to implement rate limiting per user. Let's assume we have the rate limit for each user stored in a database, and we can query it using the user id.</p>
<p>Let's write the code for it step by step.</p>
<h4 id="heading-create-a-bucket">Create a Bucket</h4>
<p>Before we start, let's look at how a bucket is created.</p>
<pre><code class="lang-java">Refill refill = Refill.intervally(<span class="hljs-number">10</span>, Duration.ofMinutes(<span class="hljs-number">1</span>));
Bandwidth limit = Bandwidth.classic(<span class="hljs-number">10</span>, refill);
Bucket bucket = Bucket4j.builder()
        .addLimit(limit)
        .build();
</code></pre>
<ul>
<li><strong>Refill</strong> – After how much time the bucket will be refilled.</li>
<li><strong>Bandwidth</strong> – How much bandwidth the bucket has. Basically, requests per refill period.</li>
<li><strong>Bucket</strong> – An object configured using these two parameters. Additionally, it maintains a token counter to keep track of how many tokens are available in the bucket.</li>
</ul>
<p>Using this as the building block, let's change a few things to make it suitable to our use case.</p>
<h4 id="heading-create-and-cache-buckets-using-proxymanager">Create and Cache Buckets using ProxyManager</h4>
<p>We created the proxy manager for the purpose of storing buckets on Redis. Once a bucket is created, it needs to be cached on Redis and does not need to be created again.</p>
<p>To make this happen, we will replace the <code>Bucket4j.builder()</code> with <code>proxyManager.builder()</code>. ProxyManager will take care of caching the buckets and not creating them again.</p>
<p>ProxyManager's builder takes two parameters – a <strong>key</strong> against which the bucket will be cached and a <strong>configuration object</strong> that it will use to create the bucket.</p>
<p>Let's see how we can implement it:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RateLimiter</span> </span>{
    <span class="hljs-comment">//autowiring dependencies</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> Bucket <span class="hljs-title">resolveBucket</span><span class="hljs-params">(String key)</span> </span>{
        Supplier&lt;BucketConfiguration&gt; configSupplier = getConfigSupplierForUser(key);

        <span class="hljs-comment">// Does not always create a new bucket, but instead returns the existing one if it exists.</span>
        <span class="hljs-keyword">return</span> buckets.builder().build(key, configSupplier);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Supplier&lt;BucketConfiguration&gt; <span class="hljs-title">getConfigSupplierForUser</span><span class="hljs-params">(String key)</span> </span>{
        User user = userRepository.findById(userId);
        Refill refill = Refill.intervally(user.getLimit(), Duration.ofMinutes(<span class="hljs-number">1</span>));
        Bandwidth limit = Bandwidth.classic(user.getLimit(), refill);
        <span class="hljs-keyword">return</span> () -&gt; (BucketConfiguration.builder()
                .addLimit(limit)
                .build());
    }
}
</code></pre>
<p>We have created a method which returns a bucket for a key provided. In the next step, we will see how to use this.</p>
<h4 id="heading-how-to-consume-tokens-and-set-up-rate-limiting">How to Consume Tokens and Set Up Rate Limiting</h4>
<p>When a request comes in, we will try to consume a token from the relevant bucket.<br>We will use the <code>tryConsume()</code> method of the bucket to do this.</p>
<pre><code class="lang-java"><span class="hljs-meta">@GetMapping("/user/{id}")</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getInfo</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable("id")</span> String id)</span> </span>{
    <span class="hljs-comment">// gets the bucket for the user</span>
    Bucket bucket = rateLimiter.resolveBucket(id);

    <span class="hljs-comment">// tries to consume a token from the bucket</span>
    <span class="hljs-keyword">if</span> (bucket.tryConsume(<span class="hljs-number">1</span>)) {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello "</span> + id;
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Rate limit exceeded"</span>;
    }
}
</code></pre>
<p>The <code>tryConsume()</code> method returns <code>true</code> if the token was consumed successfully or <code>false</code> if the token was not consumed.</p>
<h2 id="heading-how-to-test-our-service">How to Test our Service</h2>
<p>We can test this using any automated testing technique. For example, we can use <a target="_blank" href="https://junit.org/">JUnit</a>. Let's write a test case that calls the <code>getInfo()</code> method multiple times and verifies that the response is correct.</p>
<p>Let's assume we have a user with id <code>1</code> and a limit of <code>10</code> requests per minute. Let's assume we also have a user with id <code>2</code> and a limit of <code>20</code> requests per minute.</p>
<p>We will hit 11 requests for both users and verify that the request fails for the user with id <code>1</code> but succeeds for the user with id <code>2</code>.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Test</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testGetInfo</span><span class="hljs-params">()</span> </span>{

    <span class="hljs-comment">// calls the method 10 times for user 1</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10</span>; i++) {
        rateLimiter.getInfo(<span class="hljs-number">1</span>));
        rateLimiter.getInfo(<span class="hljs-number">2</span>));
    }

    <span class="hljs-comment">// verifies that the response is rate limited for user 1</span>
    assertEquals(<span class="hljs-string">"Rate limit exceeded"</span>, rateLimiter.getInfo(<span class="hljs-number">1</span>));

    <span class="hljs-comment">// verifies that the response is successful for user 2</span>
    assertEquals(<span class="hljs-string">"Hello 2"</span>, rateLimiter.getInfo(<span class="hljs-number">2</span>));
}
</code></pre>
<p>When we run the test, we will see that the test passes.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, we have covered how to create a rate limiter using Bucket4j and Redis in a Spring Boot application.We also looked at how to set up a Redisson client with JCache and how to use it to cache buckets.</p>
<p>At the end, we implemented a simple rate limiter which can be used to rate limit requests for specific users.</p>
<p>Hope you enjoyed this tutorial. Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Secure Server with Node.js and Express and Upload Images with Cloudinary ]]>
                </title>
                <description>
                    <![CDATA[ By Njoku Samson Ebere In this tutorial, we will learn how to create a server. We will begin without express and then strengthen the server using express. After that, we will see how to upload images to Cloudinary from the app we have created. I assum... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-secure-server-with-node-and-express/</link>
                <guid isPermaLink="false">66d84f98f6b5e038a1bde7e1</guid>
                
                    <category>
                        <![CDATA[ Express ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ servers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 14 Dec 2021 16:51:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/12/pexels-aleksandar-pasaric-325185.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Njoku Samson Ebere</p>
<p>In this tutorial, we will learn how to create a server. We will begin without <code>express</code> and then strengthen the server using <code>express</code>. After that, we will see how to upload images to Cloudinary from the app we have created.</p>
<p>I assume that you already understand the basics of <code>Node.js</code>, <code>express</code> and <code>nodemon</code> so we will just go straight to the practical parts.</p>
<h2 id="heading-install-nodejs-and-npm">Install Node.js and NPM</h2>
<p>If you haven't yet done so, you'll need to install Node and npm on your machine.</p>
<ol>
<li>Go to the <a target="_blank" href="https://nodejs.org/en/">Node.js website</a></li>
<li>Click on the recommended download button</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/Screenshot-2021-12-13-at-18.52.57.png" alt="Image" width="600" height="400" loading="lazy">
<em>Nodejs home page</em></p>
<p>When the download is complete, install Node using the downloaded <code>.exe</code> file (it follows the normal installation process).</p>
<h3 id="heading-check-if-the-installation-was-successful">Check if the installation was successful</h3>
<ol>
<li>Go to your terminal/command prompt <em>(run as administrator if possible)</em></li>
<li>Type in each of the following commands and hit Enter</li>
</ol>
<pre><code class="lang-javascript">node -v 
npm -v
</code></pre>
<p>Your output should be similar to the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/12/termial-1.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Terminal showing the versions of node and npm</em></p>
<p>The version may be different but that's OK.</p>
<h2 id="heading-how-to-create-a-node-server-without-express">How to Create a Node Server without Express</h2>
<p>For the rest of this tutorial, I will be using VS code as my editor. You can use whatever editor you choose.</p>
<p>Let's start by creating a project directory. Open a terminal and type the following to create a directory and open it:</p>
<pre><code class="lang-javascript">
mkdir server-tutorial cd server-tutorial
</code></pre>
<p>I named my project directory <code>server-tutorial</code>, but you can name yours as you please.</p>
<p>In the terminal, type <code>npm init</code>. Hit the <code>Enter</code> button for all prompts. When completed, you should have a <code>package.json</code> file seated in your project directory.</p>
<p>The <code>package.json</code> file is just a file with all the details of your project. You don't have to open it.</p>
<p>Create a file called <code>index.js</code>.</p>
<p>In the file, require the <code>HTTP</code> module like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);
</code></pre>
<p>Call the <code>createServer()</code> method on it and assign it to a constant like this:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> server = http.createServer();
</code></pre>
<p>Call the <code>listen()</code> method on the server constant like this:</p>
<pre><code class="lang-javascript">  server.listen();
</code></pre>
<p>Give it a port to listen to. Now this could be any free port, but we will be using port <code>3000</code> which is the conventional port. So we have this:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);

  <span class="hljs-keyword">const</span> server = http.createServer();

  server.listen(<span class="hljs-number">3000</span>);
</code></pre>
<p>Basically, that is all you need do to create a server.</p>
<h3 id="heading-how-to-test-the-server">How to Test the Server</h3>
<p>In your terminal (should be in the project directory), type <code>node index.js</code> and hit the <code>Enter</code> button.</p>
<p>Open a new tab in <a target="_blank" href="https://www.getpostman.com/"><code>postman</code></a> or any web <code>browser</code> and in the address bar, type <code>http://localhost:3000/</code>, and hit the <code>Enter</code> button. (I will be using postman because of its extended functionality outside the box.)</p>
<p>You will notice that your browser or postman keeps loading indefinitely like so:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/fp7k6pcfctn0548n0rmx.JPG" alt="Postman Loading Indefinitely" width="801" height="727" loading="lazy"></p>
<p>Yay! That is fine. Our Server is up and running.</p>
<p>But it's boring already. We need to make the server talk to us.</p>
<p>Let's get to it immediately.</p>
<h3 id="heading-how-to-send-back-a-response-from-the-server">How to Send Back a Response from the Server</h3>
<p>Back in the code, add the following to <code>const server = http.createServer();</code>:</p>
<pre><code class="lang-javascript"> (request, response) =&gt; {
    response.end(<span class="hljs-string">'Hey! This is your server response!'</span>);
 }
</code></pre>
<p>So we now have:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);

  <span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
    response.end(<span class="hljs-string">'Hey! This is your server response!'</span>);
  });

server.listen(<span class="hljs-number">3000</span>);
</code></pre>
<p>In basic terms, the <code>request</code> object tells the <code>server</code> that we want something, the <code>response</code> object tells us what the <code>server</code> has to say about our <code>request</code>, and the <code>end()</code> method terminates the communication with the <code>server</code> <code>response</code>.</p>
<p>Hopefully, that makes sense!</p>
<p>Now, test the server again following the steps we outlined above and your server should be talking to you. This is my output:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/b0189qzrdkppbvr57uo8.JPG" alt="Postman returning a response" width="801" height="727" loading="lazy"></p>
<p>Feel free to change the string as you wish.</p>
<p>Use <code>Control/Command + C</code> to terminate the server and run <code>node index</code> to start the server again.</p>
<p>Looking Sharp! Right? All good...</p>
<h2 id="heading-how-to-create-a-node-server-with-express">How to Create a Node Server With Express</h2>
<p>In this section, we want to make our lives easier by using <code>Express</code> and <code>Nodemon</code> (node-mon or no-demon, pronounce it as you wish).</p>
<p>In the terminal, install the following:</p>
<pre><code>npm install express --save 
npm install nodemon --save-dev
</code></pre><p>Create a new file named <code>app.js</code> or whatever suits you</p>
<p>In the file,</p>
<ol>
<li>Require express like so:</li>
</ol>
<p><code>const express = require('express');</code></p>
<ol start="2">
<li>Assign the express method to a constant like this:</li>
</ol>
<p><code>const app = express();</code></p>
<ol start="3">
<li>Export the app constant to make it available for use in other files within the directory like so:</li>
</ol>
<p><code>module.exports = app;</code></p>
<p>So we have:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);

<span class="hljs-keyword">const</span> app = express();



<span class="hljs-built_in">module</span>.exports = app;
</code></pre>
<p>In the <code>index.js</code> file, require the <code>app</code> we exported a while ago:</p>
<p><code>const app = require('./app');</code></p>
<p>Next, set the port using the app like so:</p>
<p><code>app.set('port', 3000);</code></p>
<p>And replace the code in the <code>http.createServer()</code> method with just <code>app</code> like this:</p>
<p><code>const server = http.createServer(app);</code></p>
<p>This directs all API management to the <code>app.js</code> file helping with separation of concerns.</p>
<p>So our <code>index.js</code> file now looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);
<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./app'</span>);

app.set(<span class="hljs-string">'port'</span>, <span class="hljs-number">3000</span>);
<span class="hljs-keyword">const</span> server = http.createServer(app);

server.listen(<span class="hljs-number">3000</span>);
</code></pre>
<p>Back in our <code>app.js</code> file, since we have directed all API management to it, let's create an endpoint to speak to us like before.</p>
<p>So before the <code>module.exports = app</code>, add the following code:</p>
<pre><code class="lang-javascript">app.use(<span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
   response.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Hey! This is your server response!'</span> }); 
});
</code></pre>
<p>We now have:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);

<span class="hljs-keyword">const</span> app = express();

app.use(<span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
   response.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Hey! This is your server response!'</span> }); 
});

<span class="hljs-built_in">module</span>.exports = app;
</code></pre>
<p>Ahaaa... It's time to test our app.</p>
<p>To test our app, we now type <code>nodemon index</code> in our terminal and hit the <code>Enter</code> button. This is my terminal:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/1gy6psmeylb6onbbt18i.JPG" alt="Terminal running nodemon" width="573" height="298" loading="lazy"></p>
<p>Do you notice that nodemon gives us details of execution in the terminal unlike Node? That's the beauty of nodemon.</p>
<p>You can now go to <code>postman</code> or any <code>browser</code> and in the address bar, type <code>http://localhost:3000/</code> and hit <code>Enter</code>. See my output:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/m4yrqaf3d235xo7hjqae.JPG" alt="Postman returning response from express app" width="804" height="727" loading="lazy"></p>
<p><strong>Walah! It's working.</strong></p>
<p>Now more reasons to use nodemon. Go to the <code>app.js</code> file and change the <code>message</code> string to any string on your choice, save, and watch the <code>terminal</code>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/qcslu7vqa746nq5hvjwk.JPG" alt="nodemon restarting after changes" width="586" height="296" loading="lazy"></p>
<p>Wow... It automatically restarts the server. This was impossible with Node. We had to restart the server ourselves.</p>
<h2 id="heading-how-to-secure-the-server-and-make-it-future-proof">How to Secure the Server and Make it Future-Proof</h2>
<p>In the <code>index.js</code> file, replace all the code with the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);
<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./app'</span>);

<span class="hljs-keyword">const</span> normalizePort = <span class="hljs-function"><span class="hljs-params">val</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> port = <span class="hljs-built_in">parseInt</span>(val, <span class="hljs-number">10</span>);

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(port)) {
    <span class="hljs-keyword">return</span> val;
  }
  <span class="hljs-keyword">if</span> (port &gt;= <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">return</span> port;
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
};
<span class="hljs-keyword">const</span> port = normalizePort(process.env.PORT || <span class="hljs-string">'3000'</span>);
app.set(<span class="hljs-string">'port'</span>, port);

<span class="hljs-keyword">const</span> errorHandler = <span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> {
  <span class="hljs-keyword">if</span> (error.syscall !== <span class="hljs-string">'listen'</span>) {
    <span class="hljs-keyword">throw</span> error;
  }
  <span class="hljs-keyword">const</span> address = server.address();
  <span class="hljs-keyword">const</span> bind = <span class="hljs-keyword">typeof</span> address === <span class="hljs-string">'string'</span> ? <span class="hljs-string">'pipe '</span> + address : <span class="hljs-string">'port: '</span> + port;
  <span class="hljs-keyword">switch</span> (error.code) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'EACCES'</span>:
      <span class="hljs-built_in">console</span>.error(bind + <span class="hljs-string">' requires elevated privileges.'</span>);
      process.exit(<span class="hljs-number">1</span>);
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-string">'EADDRINUSE'</span>:
      <span class="hljs-built_in">console</span>.error(bind + <span class="hljs-string">' is already in use.'</span>);
      process.exit(<span class="hljs-number">1</span>);
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">throw</span> error;
  }
};

<span class="hljs-keyword">const</span> server = http.createServer(app);

server.on(<span class="hljs-string">'error'</span>, errorHandler);
server.on(<span class="hljs-string">'listening'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> address = server.address();
  <span class="hljs-keyword">const</span> bind = <span class="hljs-keyword">typeof</span> address === <span class="hljs-string">'string'</span> ? <span class="hljs-string">'pipe '</span> + address : <span class="hljs-string">'port '</span> + port;
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Listening on '</span> + bind);
});

server.listen(port);
</code></pre>
<p><code>process.env.PORT</code> makes the app dynamic so that it can run any port assigned to it in the future when hosted on a live server.</p>
<p>The <code>normalizePort</code> function returns a valid port, whether it is provided as a number or a string.</p>
<p>The <code>errorHandler</code> function checks for various errors and handles them appropriately — it is then registered to the server.</p>
<p>A <code>listening</code> event listener is also registered, logging the port or named pipe on which the server is running to the console.</p>
<p>YooH! Our server is more secure and robust right now. Notice that nodemon also displays the port we are listening on.</p>
<p>There you have it, a simple, secure and robust Node.js server.</p>
<h2 id="heading-how-to-upload-images-to-cloudinary">How to Upload Images to Cloudinary</h2>
<p>Now that we have a cool server running, let's learn how we can save our images on Cloudinary. This will just be a basic introduction so it should be fun 😊.</p>
<p><a target="_blank" href="https://cloudinary.com/">Cloudinary</a> helps developers across the world manage images with minimal effort.</p>
<h3 id="heading-how-to-create-a-cloudinary-account">How to Create a Cloudinary Account</h3>
<p>To create an account, go to the <a target="_blank" href="https://cloudinary.com/">Cloudinary Website</a>.</p>
<ol>
<li>Click the <code>sign up</code> button on the <code>top right</code>.</li>
<li>Fill the form that shows up accordingly.</li>
<li>Submit the form using the <code>Create Account</code> button.</li>
<li>Check your email to finish up by validating your email</li>
</ol>
<p>You should be able to access your dashboard which looks like mine below:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/qfiw7cobdp7pv3c0fb65.JPG" alt="Cloudinary Dashboard" width="1366" height="628" loading="lazy"></p>
<p>Notice the <code>Account details</code>. You <strong>shouldn't reveal this information to anyone</strong>. I am showing it to you here because this is a temporary account that I'm using only for the purposes of this tutorial.</p>
<p>Checkout the <code>Media Library</code> tab too. This is where the uploaded images will appear.</p>
<p>If you have all these showing, then let's rock and roll...</p>
<h3 id="heading-how-to-install-cloudinary-in-our-project">How to Install Cloudinary in Our Project</h3>
<p>Open your terminal and navigate into the project directory.</p>
<p>Execute the following command to install <code>Cloudinary</code>:</p>
<pre><code class="lang-javascript">  npm install cloudinary --save
</code></pre>
<h3 id="heading-how-to-setup-cloudinary-in-our-project">How to Setup Cloudinary in Our Project</h3>
<p>In the app.js file, require <code>cloudinary</code> below the <code>const app = express();</code> like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> cloudinary = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cloudinary'</span>).v2
</code></pre>
<p>Next, add the configuration details from the account details on your dashboard like this:</p>
<pre><code class="lang-javascript">    cloud_name: <span class="hljs-string">'place your cloud_name here'</span>,
    <span class="hljs-attr">api_key</span>: <span class="hljs-string">'place your api_key here'</span>,
    <span class="hljs-attr">api_secret</span>: <span class="hljs-string">'place your api_secret here'</span>,
</code></pre>
<p>This is what I have:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">// cloudinary configuration</span>
  cloudinary.config({
    <span class="hljs-attr">cloud_name</span>: <span class="hljs-string">"dunksyqjj"</span>,
    <span class="hljs-attr">api_key</span>: <span class="hljs-string">"173989938887513"</span>,
    <span class="hljs-attr">api_secret</span>: <span class="hljs-string">"ZPLqvCzRu55MaM1rt-wxJCmkxqU"</span>
  });
</code></pre>
<h3 id="heading-how-to-create-an-endpoint-to-upload-an-image">How to Create an EndPoint to Upload an Image</h3>
<p>To avoid bugs in our code, first replace the existing API with the following code:</p>
<pre><code class="lang-javascript">  app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
    response.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Hey! This is your server response!"</span> });
  });
</code></pre>
<p>It is basically the same but this time, we are using the <code>get</code> verb in place of the <code>use</code> verb and we added a root end-point (<code>/</code>).</p>
<p>Next, just before the <code>module.exports = app;</code> line, we will be creating our <code>image-upload</code> API.</p>
<p>Let's start by placing this code there:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// image upload API</span>
app.post(<span class="hljs-string">"/upload-image"</span>, <span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {});
</code></pre>
<p>Basically, this is how we set up an API. The API makes a <code>POST</code> <code>request</code> to the <code>server</code> telling the <code>server</code> that the <code>request</code> should be handled with a degree of security. It uses two parameters to make this request: an <code>end-point</code> (/upload-image) and a <code>callback function</code> ((request, response) =&gt; {}).</p>
<p>Let's breathe life into the API by building out the <code>callback function</code>.</p>
<h3 id="heading-how-to-build-the-callback-function">How to Build the Callback Function</h3>
<h4 id="heading-install-body-parserhttpswwwnpmjscompackagebody-parser">Install <a target="_blank" href="https://www.npmjs.com/package/body-parser">body-parser</a></h4>
<p>This npm package enables us to handle incoming requests using <code>req.body</code> or <code>request.body</code> as the case may be. We will be installing <code>body-parser</code> using the following code:</p>
<pre><code class="lang-javascript">  npm install --save body-parser
</code></pre>
<h4 id="heading-configure-body-paser-for-our-project">Configure body-paser for our project</h4>
<p>Require body-parse in the app.js like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'body-parser'</span>);
</code></pre>
<p>Next, add the following code to set its <code>json</code> function as global middleware for our app like so:</p>
<pre><code class="lang-javascript">  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ <span class="hljs-attr">extended</span>: <span class="hljs-literal">true</span> }));
</code></pre>
<p>We can now handle our request body appropriately.</p>
<h3 id="heading-back-to-building-our-function">Back to Building Our Function</h3>
<p>In the function, add the following code to collect any data (images) entered by a user:</p>
<pre><code class="lang-javascript">    <span class="hljs-comment">// collected image from a user</span>
    <span class="hljs-keyword">const</span> data = {
        <span class="hljs-attr">image</span>: request.body.image,
    };
</code></pre>
<p>Next, upload the image to <code>cloudinary</code> using the following code:</p>
<pre><code class="lang-javascript">cloudinary.uploader.upload(data.image);
</code></pre>
<p>Basically, this is all we need to upload our image. So our <code>app.js</code> looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> cloudinary = <span class="hljs-built_in">require</span>(<span class="hljs-string">"cloudinary"</span>).v2;
<span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'body-parser'</span>);

<span class="hljs-comment">// body parser configuration</span>
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ <span class="hljs-attr">extended</span>: <span class="hljs-literal">true</span> }));

<span class="hljs-comment">// cloudinary configuration</span>
cloudinary.config({
  <span class="hljs-attr">cloud_name</span>: <span class="hljs-string">"dunksyqjj"</span>,
  <span class="hljs-attr">api_key</span>: <span class="hljs-string">"173989938887513"</span>,
  <span class="hljs-attr">api_secret</span>: <span class="hljs-string">"ZPLqvCzRu55MaM1rt-wxJCmkxqU"</span>
});

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
  response.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Hey! This is your server response!"</span> });
});

<span class="hljs-comment">// image upload API</span>
app.post(<span class="hljs-string">"/image-upload"</span>, <span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
    <span class="hljs-comment">// collected image from a user</span>
    <span class="hljs-keyword">const</span> data = {
      <span class="hljs-attr">image</span>: request.body.image,
    }

    <span class="hljs-comment">// upload image here</span>
    cloudinary.uploader.upload(data.image);

});

<span class="hljs-built_in">module</span>.exports = app;
</code></pre>
<p>Now this looks good and it works perfectly. You can test it out using <code>postman</code>. But it's would be awesome if our app could give us feedback when it's done handling our requests, right?</p>
<p>To make this happen, we will add the following <code>then...catch...</code> block to the cloudinary upload like so:</p>
<pre><code class="lang-javascript">    <span class="hljs-comment">// upload image here</span>
    cloudinary.uploader.upload(data.image)
    .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
      response.status(<span class="hljs-number">200</span>).send({
        <span class="hljs-attr">message</span>: <span class="hljs-string">"success"</span>,
        result,
      });
    }).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
      response.status(<span class="hljs-number">500</span>).send({
        <span class="hljs-attr">message</span>: <span class="hljs-string">"failure"</span>,
        error,
      });
    });
</code></pre>
<p>So our final code will be:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> cloudinary = <span class="hljs-built_in">require</span>(<span class="hljs-string">"cloudinary"</span>).v2;
<span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'body-parser'</span>);

<span class="hljs-comment">// body parser configuration</span>
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ <span class="hljs-attr">extended</span>: <span class="hljs-literal">true</span> }));

<span class="hljs-comment">// cloudinary configuration</span>
cloudinary.config({
  <span class="hljs-attr">cloud_name</span>: <span class="hljs-string">"dunksyqjj"</span>,
  <span class="hljs-attr">api_key</span>: <span class="hljs-string">"173989938887513"</span>,
  <span class="hljs-attr">api_secret</span>: <span class="hljs-string">"ZPLqvCzRu55MaM1rt-wxJCmkxqU"</span>
});

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
  response.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Hey! This is your server response!"</span> });
});

<span class="hljs-comment">// image upload API</span>
app.post(<span class="hljs-string">"/image-upload"</span>, <span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
    <span class="hljs-comment">// collected image from a user</span>
    <span class="hljs-keyword">const</span> data = {
      <span class="hljs-attr">image</span>: request.body.image,
    }

    <span class="hljs-comment">// upload image here</span>
    cloudinary.uploader.upload(data.image)
    .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
      response.status(<span class="hljs-number">200</span>).send({
        <span class="hljs-attr">message</span>: <span class="hljs-string">"success"</span>,
        result,
      });
    }).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
      response.status(<span class="hljs-number">500</span>).send({
        <span class="hljs-attr">message</span>: <span class="hljs-string">"failure"</span>,
        error,
      });
    });

});

<span class="hljs-built_in">module</span>.exports = app;
</code></pre>
<h3 id="heading-how-to-test-our-api">How to Test our API</h3>
<p>Create a folder/directory in the root directory and name it <code>images</code> like so:</p>
<pre><code class="lang-javascript">  mkdir images
</code></pre>
<p>Copy an image of your choice to this folder. (Now, the path to your image relative to the app.js file should look like this: <code>"images/&lt;your-image.jpg"&gt;</code>.)</p>
<p>Now let's proceed to <code>postman</code>.</p>
<ol>
<li>In the address bar, enter this: <code>http://localhost:3000/image-upload</code></li>
<li>Set the <code>Header</code> Key to <code>Content-Type</code> and value to <code>application/json</code></li>
<li>Set the <code>body</code> to the <code>json</code> data we declared in our code like so:</li>
</ol>
<pre><code class="lang-javascript">       {
       <span class="hljs-string">"image"</span>: <span class="hljs-string">"images/oskar-yildiz-gy08FXeM2L4-unsplash.jpg"</span>
       }
</code></pre>
<p>Hit the <code>Send</code> button and wait for the upload to complete and get your response:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/ate77jhmka2agj3nxip2.JPG" alt="Postman setup to upload image" width="1366" height="729" loading="lazy"></p>
<p>Now, this is the result. The image now has a unique <code>public_id</code> which is randomly generated by Cloudinary and a <code>secure_url</code> which is globally accessible (you can load it in your browser to see).</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/wys21hgc58nl4rfmq63i.JPG" alt="Postman showing result of upload" width="1366" height="730" loading="lazy"></p>
<p>Finally, checking the <code>Media Library</code> tab on your Cloudinary dashboard, you should have a new image with a <code>new</code> badge on it. This will have a unique id that matches the <code>public_id</code> we saw in the postman result above just like in the image below:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/vkvevngtumyfdd105suu.JPG" alt="Cloudinary Media Files" width="1366" height="627" loading="lazy"></p>
<p>Walah! We are persisting images without stress...That feels good.</p>
<p>Well, one more thing – SECURITY!</p>
<p>Our Cloudinary configuration details rea exposed in our app.js file. If we push our project to GitHub, it becomes publicly available to anyone who cares to check it out. And that becomes a problem if it gets into the wrong hands.</p>
<p>But don't worry about a thing here, there is a fix for almost everything in this space. We will be using the <code>dotenv</code> npm package to hid our configurations from the public.</p>
<h2 id="heading-how-to-secure-our-configurations-with-dotenv">How to Secure Our Configurations with <code>dotenv</code></h2>
<p>First, you'll need to install <a target="_blank" href="https://www.npmjs.com/package/dotenv">dotenv</a> if you haven't already:</p>
<pre><code class="lang-javascript">npm install dotenv --save
</code></pre>
<p>Then require <code>dotenv</code> in <code>app.js</code> like so:</p>
<pre><code class="lang-javascript">  <span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config()
</code></pre>
<p>Create a new file in the root directory and name it <code>.env</code>.</p>
<p>In the file, enter your Cloudinary configuration details like so:</p>
<pre><code class="lang-javascript">  CLOUD_NAME=dunksyqjj
  API_KEY=<span class="hljs-number">173989938887513</span>
  API_SECRET=ZPLqvCzRu55MaM1rt-wxJCmkxqU
</code></pre>
<p>In the app.js file, we will access the configurations in the <code>.env</code> file via the <code>process.env</code> property like so:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// cloudinary configuration</span>
cloudinary.config({
  <span class="hljs-attr">cloud_name</span>: process.env.CLOUD_NAME,
  <span class="hljs-attr">api_key</span>: process.env.API_KEY,
  <span class="hljs-attr">api_secret</span>: process.env.API_SECRET
});
</code></pre>
<p>This is my <code>app.js</code> code at the moment:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> cloudinary = <span class="hljs-built_in">require</span>(<span class="hljs-string">"cloudinary"</span>).v2;
<span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'body-parser'</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config()

<span class="hljs-comment">// body parser configuration</span>
app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ <span class="hljs-attr">extended</span>: <span class="hljs-literal">true</span> }));

<span class="hljs-comment">// cloudinary configuration</span>
cloudinary.config({
  <span class="hljs-attr">cloud_name</span>: process.env.CLOUD_NAME,
  <span class="hljs-attr">api_key</span>: process.env.API_KEY,
  <span class="hljs-attr">api_secret</span>: process.env.API_SECRET
});

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">request, response, next</span>) =&gt;</span> {
  response.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Hey! This is your server response!"</span> });
  next();
});

<span class="hljs-comment">// image upload API</span>
app.post(<span class="hljs-string">"/image-upload"</span>, <span class="hljs-function">(<span class="hljs-params">request, response</span>) =&gt;</span> {
    <span class="hljs-comment">// collected image from a user</span>
    <span class="hljs-keyword">const</span> data = {
      <span class="hljs-attr">image</span>: request.body.image,
    }

    <span class="hljs-comment">// upload image here</span>
    cloudinary.uploader.upload(data.image)
    .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
      response.status(<span class="hljs-number">200</span>).send({
        <span class="hljs-attr">message</span>: <span class="hljs-string">"success"</span>,
        result,
      });
    }).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
      response.status(<span class="hljs-number">500</span>).send({
        <span class="hljs-attr">message</span>: <span class="hljs-string">"failure"</span>,
        error,
      });
    });
});

<span class="hljs-built_in">module</span>.exports = app;
</code></pre>
<p>Let's test our app again to make sure that nothing is broken. Here is my result:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/i/d3a2b47shxlmext6o40j.JPG" alt="Cloudinary media library" width="1366" height="627" loading="lazy"></p>
<p>I now have two of the same image but with different <code>public_id</code>s.</p>
<p>And that is it!</p>
<p>Yeeeh! Our application is more secure than it was when we started.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, we went through the steps involved in creating a server using just Node.js. And after that, we improved our server using Express and nodemon.</p>
<p>Finally, we saw how to upload an image to Cloudinary through our Express application and how our configuration details are secured using the <code>dotenv</code> package.</p>
<p>This is just an introduction. You can do a whole lot more if you play around with this application.</p>
<p>You can find the server creation code <a target="_blank" href="https://github.com/EBEREGIT/server-tutorial/tree/create-server">here</a>.</p>
<p>And the image upload codes are available <a target="_blank" href="https://github.com/EBEREGIT/server-tutorial/tree/cloudinary-upload">here</a>.</p>
<p>Thank you for your time. 😊</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up reCAPTCHA v3 in a Laravel Project ]]>
                </title>
                <description>
                    <![CDATA[ In this article, you'll learn how to set up reCAPTCHA v3 in your Laravel project. This can be a bit tricky, so I'll help you simplify the process here.  What is reCaptcha? reCaptcha is a Google service provided for free that helps you protect your we... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-setup-recaptcha-v3-in-laravel/</link>
                <guid isPermaLink="false">66ba2fbac346e93df556afff</guid>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sule-Balogun Olanrewaju ]]>
                </dc:creator>
                <pubDate>Mon, 20 Sep 2021 22:26:01 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/pexels-davis-sanchez-1727004.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, you'll learn how to set up reCAPTCHA v3 in your Laravel project. This can be a bit tricky, so I'll help you simplify the process here. </p>
<h2 id="heading-what-is-recaptcha">What is reCaptcha?</h2>
<p><a target="_blank" href="https://developers.google.com/recaptcha/">reCaptcha</a> is a Google service provided for free that helps you protect your websites from spam and malicious attacks. </p>
<p>The new version, V3, has many improvements over previous versions thanks to the new captcha challenges. It returns a score and analytics you can use to take appropriate action for your website.</p>
<p>Here's what the previous version of reCaptcha looks like – but as of the latest release (v3), reCaptcha has changed a lot and has a better user experience.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/newCaptchaAnchor.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Previous reCaptcha Version</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/11/Screenshot-2020-11-26-at-04.11.28.png" alt="Image" width="600" height="400" loading="lazy">
<em>Previous reCaptcha Version</em></p>
<h2 id="heading-what-youll-learn">What you'll learn</h2>
<p>By the end of this article, you'll have learned the following:</p>
<ol>
<li>How to integrate the reCaptcha v3 into your Laravel project</li>
<li>How to setup a Google reCaptcha admin dashboard</li>
<li>How to view your website reCaptcha scores and analytics to help you make better security decisions</li>
</ol>
<h2 id="heading-how-to-setup-recaptcha-in-a-laravel-project">How to Setup reCaptcha in a Laravel Project</h2>
<p>You can follow these simple steps to get reCaptcha set up on your project.</p>
<ol>
<li>Install this <a target="_blank" href="https://laravel.com/docs/8.x/installation">laravel project</a> if you haven't done so yet</li>
<li>In the terminal, pull the open-source package into your project with composer.</li>
</ol>
<pre><code>composer <span class="hljs-built_in">require</span> biscolab/laravel-recaptcha
</code></pre><ol start="3">
<li>Publish the <code>recaptcha.php</code> with this command:</li>
</ol>
<pre><code class="lang-php">php artisan vendor:publish --provider=<span class="hljs-string">"Biscolab\ReCaptcha\ReCaptchaServiceProvider"</span>
</code></pre>
<p>This will create a file in the config directory, called <code>config\recaptcha.php</code>, where we will add more reCaptcha configurations.</p>
<ol start="4">
<li><a target="_blank" href="https://www.google.com/recaptcha/admin/create">Visit this link</a> to create a reCaptcha admin account for yourself.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/reCAPTCHA-2021-07-23-10-59-07.png" alt="Image" width="600" height="400" loading="lazy">
<em>Register reCaptcha v3</em></p>
<p>To create the reCaptcha admin, you can do the following:</p>
<ul>
<li>Add your site name to the label – <code>localhost</code>  or <code>examplesite.com</code></li>
<li>Select v3 as the reCaptcha type</li>
<li>Include domains in the domain section (<code>localhost</code> or <code>examplesite.com</code>)</li>
<li>Add the owner's email address to the owner's section</li>
<li>Check the "accept terms and service" box </li>
</ul>
<p>Just a note – the localhost is for the sole purpose of developing locally. As such, it should be updated before moving to a production environment.</p>
<ol start="5">
<li>Add the reCaptcha to your site</li>
</ol>
<p>Click the submit button and save your secret keys. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/reCAPTCHA-2021-07-23-11-16-17.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding reCaptcha to your site within the .env</em></p>
<ol start="6">
<li>Add the site keys to the <code>.env</code> file of your project:</li>
</ol>
<pre><code class="lang-php">RECAPTCHA_SITE_KEY=ADD_YOUR_SITE_KEY
RECAPTCHA_SECRET_KEY=ADD_YOUR_SECRET_KEY
RECAPTCHA_SITE=https:<span class="hljs-comment">//www.google.com/recaptcha/admin/</span>
</code></pre>
<p>Since you have made changes to the <code>.env</code>, it's best to clear all cached configurations so that the new changes take effect. Use <code>php artisan optimize:clear</code> in your terminal.</p>
<ol start="7">
<li>Within the <code>config &gt; recaptcha.php</code> file, update the property of the version to V3. It's also important to note that the <code>api_site_key</code> and <code>api_secret_key</code> generated via the admin dashboard will be referenced from what we set in the .env file of the project.</li>
</ol>
<pre><code class="lang-php"><span class="hljs-keyword">return</span> [
    <span class="hljs-string">'version'</span>                      =&gt; <span class="hljs-string">'v3'</span>
]
</code></pre>
<p>You can now head over to the analytics page of the reCaptcha admin to view how well your site is performing, view your scores, and make decisions when you're in a production environment.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/reCAPTCHA-2021-07-24-10-27-04-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>reCaptcha analytics page</em></p>
<p>The below image shows that reCaptcha has been implemented.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screenshot-2021-09-19-at-15.37.00.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>At the end of this article, I hope you'll find it easier to set up reCaptcha and that you'll have a better understanding of what it's all about. Now you should be able to set up the most recent version within your Laravel project.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li>What is <a target="_blank" href="https://developers.google.com/recaptcha/">reCaptcha</a>?</li>
<li>Laravel reCaptcha <a target="_blank" href="https://github.com/biscolab/laravel-recaptcha">repo</a></li>
<li>Laravel reCaptcha <a target="_blank" href="https://laravel-recaptcha-docs.biscolab.com/docs/configuration">docs</a> </li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
