<?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[ Juan Cruz Martinez - 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[ Juan Cruz Martinez - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:29:53 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/bajcmartinez/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ More Secure Authentication: From Passwords to Passkeys ]]>
                </title>
                <description>
                    <![CDATA[ In the ever-evolving world of cybersecurity, authentication remains a cornerstone. Traditional methods, like passwords and social logins, are increasingly vulnerable to attacks. Enter passkeys—a revolutionary approach promising enhanced security and ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/more-secure-authentication-from-passwords-to-passkeys/</link>
                <guid isPermaLink="false">66d039dddaf2a38a6b1e1d02</guid>
                
                    <category>
                        <![CDATA[ Application Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ information security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Juan Cruz Martinez ]]>
                </dc:creator>
                <pubDate>Thu, 11 Jul 2024 13:38:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/passkeys-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In the ever-evolving world of cybersecurity, authentication remains a cornerstone. Traditional methods, like passwords and social logins, are increasingly vulnerable to attacks. Enter passkeys—a revolutionary approach promising enhanced security and user convenience. </p>
<p>This guide will explore the current state of authentication, delve into what passkeys are, how they work, and discuss the challenges and future of this technology.</p>
<h2 id="heading-the-current-state-of-authentication">The Current State of Authentication</h2>
<p>Authentication is a critical component of digital security, serving as the gateway to systems and data. Despite numerous advancements, traditional authentication methods, such as passwords and social logins, remain prevalent. But these methods are increasingly proving to be inadequate in addressing modern security challenges.</p>
<p>Passwords, once considered the gold standard, are now recognized as a significant weak link in cybersecurity. The rise in sophisticated cyberattacks, coupled with poor password practices, has highlighted the urgent need for more robust authentication mechanisms. </p>
<p>Passwords are susceptible to various attacks, including phishing, brute force, and credential stuffing. Many users also recycle passwords across multiple sites, exacerbating the risk. Managing multiple passwords can be cumbersome, leading to weak password practices and forgotten credentials.</p>
<p>Social logins, while convenient, bring their own set of issues, including privacy concerns and dependency on third-party platforms. Users are often wary of sharing their social media credentials with third-party sites, fearing data misuse. </p>
<p>Also, social logins tie users to specific platforms, which can be problematic if a user decides to leave a social network or if the platform experiences an outage.</p>
<p>Magic links, an alternative authentication method, also have their limitations. Magic links are sent via email, which is not always secure. If an email account is compromised, so is the authentication. </p>
<p>The process of checking email and clicking a link can be cumbersome, particularly for users on mobile devices or with poor internet connectivity. Emails can also be delayed, end up in spam folders, or fail to deliver, causing frustration and potential access issues for users.</p>
<p>As the digital landscape continues to evolve, the need for more secure, user-friendly, and scalable authentication solutions becomes paramount. This exploration of the inherent problems with passwords, social logins, and magic links sets the stage for understanding why passkeys are a vital innovation in the field of authentication.</p>
<h2 id="heading-what-are-passkeys">What are Passkeys?</h2>
<p>Passkeys represent a modern authentication solution designed to address the shortcomings of traditional methods. Essentially, passkeys eliminate the need for passwords by utilizing a pair of cryptographic keys to authenticate users securely.</p>
<p>At the core of passkeys is public-private key cryptography. Each user has a unique pair of keys: a public key, which is stored on the server, and a private key, which remains securely on the user's device. </p>
<p>When a user attempts to authenticate, they use a method like biometric verification (fingerprint or facial recognition) or a device-specific security feature to access their private key. </p>
<p>This private key generates a cryptographic signature that the server verifies using the corresponding public key, ensuring a secure and seamless authentication process.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/passkeys.png" alt="Image" width="600" height="400" loading="lazy">
<em>Diagram showing the passkey authentication process</em></p>
<p>Passkeys are built on the <a target="_blank" href="https://fidoalliance.org/fido2/">FIDO2 standard</a>, which promotes interoperability and security across different devices and platforms. Major tech companies, including Google, Microsoft, Okta, and Apple, support this standard, making it a robust and widely adopted solution.</p>
<p>The use of biometrics and device-based authentication enhances security by ensuring that the private key never leaves the user's device and is never exposed to potential attackers. </p>
<p>This approach significantly reduces the risk of phishing attacks, as there are no passwords to be stolen or guessed. Passkeys also help streamline the user experience by eliminating the need to remember and manage multiple passwords.</p>
<p>Implementing passkeys involves a few key steps:</p>
<ol>
<li><strong>Registration</strong>: During account creation or passkey setup, the user's device generates a new key pair. The public key is sent to the server and stored with the user's account information.</li>
<li><strong>Authentication</strong>: When the user logs in, they use their private key to generate a cryptographic signature. The server verifies this signature using the stored public key, ensuring that the user is who they claim to be.</li>
</ol>
<blockquote>
<p>Visit <a target="_blank" href="https://learnpasskeys.io/">learnpasskeys.io</a> to learn in detail how each of these processes work.</p>
</blockquote>
<p>By leveraging these principles, passkeys offer a secure, user-friendly, and scalable solution for modern authentication needs. As developers, understanding how passkeys work and how to implement them is crucial in staying ahead in the realm of digital security.</p>
<h2 id="heading-challenges-with-passkeys">Challenges with Passkeys</h2>
<p>While passkeys offer numerous advantages over traditional authentication methods, they are not without their challenges. Understanding these challenges is crucial for developers and organizations considering adopting this technology.</p>
<h3 id="heading-adoption-and-integration">Adoption and Integration</h3>
<p>One of the primary challenges with passkeys is the integration with existing systems. </p>
<p>Many organizations rely on legacy systems that are not compatible with passkey technology, requiring significant overhauls to implement. Migrating to a passkey-based system involves not only technical adjustments but also changes in infrastructure, which can be resource-intensive and time-consuming.</p>
<h3 id="heading-user-education-and-trust">User Education and Trust</h3>
<p>Introducing a new authentication method requires educating users about how it works and why it's beneficial. </p>
<p>Users need to understand and trust the new system, which can be a hurdle given the novelty of passkeys. Ensuring that users feel comfortable and secure with the transition from passwords to passkeys is essential for widespread adoption.</p>
<h3 id="heading-technical-considerations">Technical Considerations</h3>
<p>Passkeys rely heavily on device capabilities. Not all devices support biometric authentication or the FIDO2 standard, potentially limiting the adoption of passkeys. </p>
<p>Developers need to ensure that fallback mechanisms are in place for users with unsupported devices, which can complicate the implementation process.</p>
<h3 id="heading-compatibility-and-interoperability">Compatibility and Interoperability</h3>
<p>While the FIDO2 standard promotes interoperability, ensuring compatibility across different devices, operating systems, and browsers can still be challenging. Developers need to thoroughly test their implementations to ensure a seamless user experience across all platforms.</p>
<p>Despite these challenges, the benefits of passkeys in terms of security and user experience make them a compelling option for modern authentication. By addressing these challenges proactively, developers and organizations can pave the way for a more secure and user-friendly authentication future.</p>
<h2 id="heading-the-future-of-authentication">The Future of Authentication</h2>
<p>The evolution of authentication is a testament to our ongoing quest for balance between security and convenience. From the simplicity of passwords to the robust security of passkeys, each step forward has been driven by the need to protect our digital lives against increasingly sophisticated threats.</p>
<p>Passkeys represent a significant leap in this journey, offering a secure, user-friendly alternative to traditional methods. By leveraging cryptographic keys and biometric verification, passkeys address many of the vulnerabilities that plague passwords and social logins. </p>
<p>The path to widespread adoption is not without its challenges, though, from integration hurdles to user education. But despite these obstacles, the benefits of passkeys make them a compelling option for modern authentication. </p>
<p>As developers and organizations navigate these challenges, the future of authentication looks promising. By embracing innovations like passkeys, we can move towards a more secure, seamless digital experience for all users.</p>
<p>The story of authentication is ongoing, and as we continue to innovate, the lessons from our past and the potential of our future guide us towards a safer digital world. Stay ahead of the curve, keep learning, and together, we can build a more secure digital landscape.</p>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Choose a Tech Stack for Your SaaS Product – Lessons from a Developer ]]>
                </title>
                <description>
                    <![CDATA[ As a developer, I've seen how choosing the "right" tech stack can be a double-edged sword. I often fell into the trap of chasing shiny new technologies, thinking they were the key to building the next great product. But experience has taught me that ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/choose-a-tech-stack-for-your-saas-product/</link>
                <guid isPermaLink="false">66d039d6daf2a38a6b1e1cfd</guid>
                
                    <category>
                        <![CDATA[ career advice ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SaaS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Juan Cruz Martinez ]]>
                </dc:creator>
                <pubDate>Fri, 24 May 2024 08:52:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/Live-Stream-Post.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a developer, I've seen how choosing the "right" tech stack can be a double-edged sword. I often fell into the trap of chasing shiny new technologies, thinking they were the key to building the next great product. But experience has taught me that prioritizing speed to market trends often trumps the pursuit of technological ideals.</p>
<p>In the early stages of a SaaS product, it's easy to get caught up in the excitement of designing elaborate architectures, experimenting with bleeding-edge frameworks, and optimizing every line of code. While these things are important, they can also become significant roadblocks if taken too far.</p>
<p>I've seen projects stall for months as developers (myself) debated the merits of different databases or attempted to master a complex framework before writing a single line of product code. This kind of overengineering can drain resources, delay launches, and ultimately put the entire project at risk.</p>
<p>One of the most valuable lessons I've learned is the power of leveraging familiar technologies. When you and your team know a toolset inside and out, you can build features faster, troubleshoot more efficiently, and deliver a more stable product.</p>
<p>This doesn't mean you should never learn new things. But in the early stages of a product, where speed is crucial, it's often more beneficial to focus on building something that works, rather than something that's technically impressive but takes forever to complete.</p>
<p>As your product matures and gains traction, there will be opportunities to experiment with new technologies and optimize your tech stack. But in the beginning, the most important thing is to get your product in front of users and start gathering feedback.</p>
<h2 id="heading-what-tech-stack-should-i-use">What Tech Stack Should I Use?</h2>
<p>There's no one-size-fits-all answer when it comes to the perfect tech stack. The best choice for you will depend on several factors:</p>
<ul>
<li><strong>Your Use Case:</strong> What kind of SaaS product are you building? Different types of applications may benefit from different technologies. For example, a real-time collaboration tool might prioritize WebSocket and reactive frameworks, while a data-heavy analytics platform might favor a robust database and powerful server-side processing.</li>
<li><strong>Your Team's Expertise:</strong> Don't underestimate the value of familiarity. If your team is already proficient in a particular language or framework, leverage that expertise. It'll save you valuable time and reduce the risk of running into unexpected issues.</li>
<li><strong>Scalability and Performance Requirements:</strong> Do you anticipate rapid growth? If so, choose a tech stack that can scale with your user base and traffic. Consider cloud-based solutions and technologies that are known for their performance and reliability.</li>
</ul>
<h2 id="heading-general-recommendations">General Recommendations</h2>
<p>While there's no magic formula, here are some general recommendations for SaaS tech stacks (for web apps) that have proven successful:</p>
<h3 id="heading-front-end">Front-End</h3>
<ul>
<li><strong>React/NextJS:</strong> A popular JavaScript library for building user interfaces. It's known for its flexibility, component-based architecture, and large community.</li>
<li><strong>Vue.js:</strong> Another popular JavaScript framework that's easy to learn and integrate into existing projects.</li>
<li><strong>Angular:</strong> A full-featured framework developed by Google, offering a structured approach to building complex applications.</li>
</ul>
<h3 id="heading-back-end">Back-End</h3>
<ul>
<li><strong>Node.js:</strong> A JavaScript runtime environment that allows you to use JavaScript for server-side development. It's known for its speed, scalability, and large ecosystem of libraries and frameworks.</li>
<li><strong>Python (with Django or FastAPI):</strong> A versatile language that's great for rapid development and data-intensive applications. Django and Flask are popular frameworks that provide structure and simplify common tasks.</li>
<li><strong>Ruby (with Rails):</strong> Known for its convention-over-configuration approach and developer-friendly tools, Rails can help you build web applications quickly and efficiently.</li>
</ul>
<h3 id="heading-database">Database</h3>
<ul>
<li><strong>PostgreSQL:</strong> A powerful and reliable open-source relational database that offers strong support for complex queries, data integrity, and scalability.</li>
<li><strong>MongoDB/DynamoDB:</strong> A NoSQL database that's flexible and scalable, making it a good choice for applications with evolving data models or unstructured data.</li>
</ul>
<h3 id="heading-additional-considerations">Additional Considerations</h3>
<ul>
<li><strong>Authentication:</strong> Authentication is one of those systems you don’t want to build, so use third party services like <a target="_blank" href="https://auth0.com/">Auth0</a> to get you started quickly and that would scale as you grow.</li>
<li><strong>Caching:</strong> Consider using a caching layer like <a target="_blank" href="https://redis.io/">Redis</a> to improve performance and reduce database load.</li>
<li><strong>Queueing:</strong> For background tasks and asynchronous processing, message queues like <a target="_blank" href="https://www.rabbitmq.com/">RabbitMQ</a>, <a target="_blank" href="https://kafka.apache.org/">Kafka</a>, or <a target="_blank" href="https://aws.amazon.com/sqs/">Amazon SQS</a> can be valuable.</li>
<li><strong>Monitoring and Logging:</strong> Implement tools like <a target="_blank" href="https://www.datadoghq.com/">Datadog</a>, <a target="_blank" href="https://sentry.io/welcome/">Sentry</a> to monitor your application's performance and track errors.</li>
</ul>
<h3 id="heading-why-this-stack">Why this Stack?</h3>
<ul>
<li><strong>Speed to Market:</strong> This stack combines familiar technologies (JavaScript, Python) with modern frameworks (React, Django/Flask, Express/NestJS) that facilitate rapid development.</li>
<li><strong>Scalability:</strong> AWS, Azure, and GCP offer auto-scaling and other features that allow your application to grow with your user base. PostgreSQL and MongoDB are known for their scalability.</li>
<li><strong>Flexibility:</strong> This stack supports both relational and NoSQL databases, giving you flexibility to choose the right data model for your application. The three major cloud providers offer a variety of services to meet your evolving needs.</li>
<li><strong>Community and Support:</strong> All of these technologies have large, active communities and extensive documentation, making it easier to find help and resources when you need them.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Choosing the right tech stack for your SaaS product is a critical decision, but it's important to remember that technology is just one ingredient in the recipe for success. A well-validated idea, a strong team, and a relentless focus on delivering value to customers are all equally important.</p>
<p>Throughout my journey as a developer, I've learned a few key lessons:</p>
<ul>
<li><strong>Prioritize Speed to Market:</strong> Don't let the pursuit of technological perfection delay your launch. Get your product in front of users as quickly as possible to gather feedback and iterate.</li>
<li><strong>Embrace Familiarity:</strong> Leverage the technologies you know and love to minimize the learning curve and maximize productivity.</li>
<li><strong>Start Simple, Then Scale:</strong> Begin with a minimum viable product (MVP) and the simplest tech stack that meets your needs. You can always evolve and optimize as you grow.</li>
<li><strong>Don't Be Afraid to Pivot:</strong> Be open to changing your tech stack if it no longer serves your needs. The right tools at one stage of your product's lifecycle may not be the right tools later on.</li>
<li><strong>Focus on the User:</strong> Ultimately, your tech stack is just a means to an end. The most important thing is to build a product that solves a real problem for your users and delivers exceptional value.</li>
</ul>
<p>By prioritizing speed to market, leveraging your team's strengths, and remaining adaptable, you'll be well on your way to building a successful SaaS product. Remember, the best tech stack is the one that empowers you to create something truly meaningful for your customers.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Python Use Cases – What is Python Best For? ]]>
                </title>
                <description>
                    <![CDATA[ Developers are often very passionate about their tech stack, and they'll likely recommend it for anything.  It is very common to see devs on social media sharing how you can build anything with JavaScript or how Python is great for data scientists. A... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-python-best-for/</link>
                <guid isPermaLink="false">66d039dfa30d09f91d49b784</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Juan Cruz Martinez ]]>
                </dc:creator>
                <pubDate>Tue, 05 Dec 2023 21:22:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/python-best-for.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Developers are often very passionate about their tech stack, and they'll likely recommend it for anything. </p>
<p>It is very common to see devs on social media sharing how you can build anything with JavaScript or how Python is great for data scientists.</p>
<p>As a Python fanatic myself, I actually don't always use Python for my projects because Python doesn't excel at everything. So today, I want to share my thoughts about the main use cases in which Python shines.</p>
<h2 id="heading-scripting-and-automation">Scripting and Automation</h2>
<p>It's never been easier to script and automate tasks thanks to the rise of no-code and tools like Apple's Shortcuts app. But even after integrating those into my day-to-day routine, there are many times when I still rely on Python to get things done.</p>
<p>I use Python in part because I'm already familiar with the language. Plus its simplicity and extensive library ecosystem help me get results quicker than with other programming languages.</p>
<p>Here are some of the tasks you can automate with Python along with some personal examples:</p>
<h3 id="heading-file-management">File management</h3>
<p>You can automate tasks like file organization, renaming, copying, and deletion using Python. </p>
<p>I personally use Obsidian as my note-taking tool, where all my notes land in a dedicated "inbox" folder for processing. A Python script then reads the notes and moves each one to the appropriate folder based on their contents. </p>
<p>The script sounds fancy, but it is pretty simple, as I already have a system in place.</p>
<p>Here is what my script for organizing notes looks like:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> shutil
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> frontmatter

<span class="hljs-comment"># List of frontmatter properties with folder destinations</span>
frontmatter_to_dir = {
    <span class="hljs-string">'project'</span>: <span class="hljs-string">'1. Projects'</span>,
    <span class="hljs-string">'area'</span>: <span class="hljs-string">'2. Areas'</span>,
    <span class="hljs-string">'resource'</span>: <span class="hljs-string">'3. Resources'</span>,
}

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">try_move_file</span>(<span class="hljs-params">file, destination</span>):</span>
    print(<span class="hljs-string">'- Moving file'</span>, file, <span class="hljs-string">"to"</span>, destination)
    <span class="hljs-keyword">try</span>:
        shutil.move(file, destination)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> err:
        print(<span class="hljs-string">'-  - Project not found'</span>, err)


<span class="hljs-comment"># Read all the files inside the "!inbox" directory</span>
notes = os.listdir(<span class="hljs-string">'!inbox'</span>)
<span class="hljs-keyword">for</span> note <span class="hljs-keyword">in</span> notes:
    note_path =  <span class="hljs-string">f"!inbox/<span class="hljs-subst">{note}</span>"</span>
    <span class="hljs-comment"># Read the file's frontmatter</span>
    note_metadata = frontmatter.load(note_path)

    <span class="hljs-comment"># Check if the file has a property to categorize this note,</span>
    <span class="hljs-comment"># for example: project, area, or resource</span>
    <span class="hljs-keyword">for</span> group, group_destination <span class="hljs-keyword">in</span> frontmatter_to_dir.items():
        <span class="hljs-keyword">if</span> group <span class="hljs-keyword">in</span> note_metadata:
            <span class="hljs-comment"># Try moving the file, it can be the case the project is</span>
            <span class="hljs-comment"># for example mispelled, in that case it won't do anything with the note</span>
            try_move_file(note_path, <span class="hljs-string">f"<span class="hljs-subst">{group_destination}</span>/<span class="hljs-subst">{note_metadata[group]}</span>/<span class="hljs-subst">{note}</span>"</span>)
</code></pre>
<h3 id="heading-data-processing">Data processing</h3>
<p>Python is in a unique position when it comes to data processing. Whether you are trying to process text, images, large data sets, or perform complex calculations, there are excellent Python libraries for all use cases. </p>
<p>I usually create Python scripts to understand information. For example, I run a company with multiple SaaS products, and I have Python scripts to process statements and help me with the accounting.</p>
<h3 id="heading-extracting-data-from-text-files-or-web-pages">Extracting data from text files or web pages</h3>
<p>You can use Python to extract data from websites, analyze web content, and gather information to send summaries or others. I used this until very recently to download RSS feeds from my favorite blogs and websites and create a one-email summary that I would then use to read the most interesting articles. I'm now using Readwise Reader for this purpose.</p>
<p>To showcase how to extract data from web pages using Python, I created a small script that would visit a site, parse it’s HTML and return information from elements in the DOM. In particular, it will visit a newspaper, find information about the exchange rate for the pair ARS/USD of the day, and print it on the screen. Great script for those living in Argentina.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> bs4 <span class="hljs-keyword">import</span> BeautifulSoup

<span class="hljs-comment"># Load the newspapaer website to scrap information about the current exchange rate for USD/ARS</span>
URL = <span class="hljs-string">'https://www.lanacion.com.ar/'</span>
page = requests.get(URL)

<span class="hljs-comment"># Parse the HTML data</span>
soup = BeautifulSoup(page.content, <span class="hljs-string">"html.parser"</span>)
<span class="hljs-comment"># Use select to find an element in the DOM</span>
<span class="hljs-comment"># In our case, we need a span inside a link with a specific title</span>
span = soup.select(<span class="hljs-string">'a[title="Dólar blue"] span'</span>)[<span class="hljs-number">0</span>]
price = span.get_text()
<span class="hljs-comment"># In a real scenario, instead of simply printing the price,</span>
<span class="hljs-comment"># I'd for example, email me the results or do some other processing</span>
print(price) <span class="hljs-comment"># e.g. $930,00</span>
</code></pre>
<h3 id="heading-sending-emails">Sending emails</h3>
<p>This is how my newsletter started: sending emails to subscribers through a Python script. Now, that's not scaling very well as I wanted fancier features, and I moved on to ConvertKit – but the Python script was good for being a free, smaller-scale solution.</p>
<p>Sending emails require access to an SMTP server, or similar service, in my case I was using a proprietary API to send those, Amazon SES, because when it comes to emailing in bulk, there are certain measures you want to take not to damage the score of your domain, or your emails will end up on the spam folder.</p>
<p>Here is how I was doing that:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">import</span> json

<span class="hljs-comment"># All email addresses where store in s3</span>
s3_bucket = <span class="hljs-string">''</span>
<span class="hljs-comment"># Provide the path to your file in the S3 bucket</span>
s3_key = <span class="hljs-string">'mail_list/addresses.txt'</span>

s3_client = boto3.client(<span class="hljs-string">'s3'</span>)
<span class="hljs-comment"># Retrieve the email ids from the file</span>
s3_object = s3_client.get_object(Bucket=s3_bucket, Key=s3_key)
email_ids = s3_object[<span class="hljs-string">'Body'</span>].read().decode(<span class="hljs-string">'utf-8'</span>).split(<span class="hljs-string">'\n'</span>)

<span class="hljs-comment"># Send email for each email ID</span>
ses_client = boto3.client(<span class="hljs-string">'ses'</span>)
<span class="hljs-keyword">for</span> email_id <span class="hljs-keyword">in</span> email_ids:
    email_id = email_id.strip() <span class="hljs-comment"># Remove leading/trailing whitespace</span>

    <span class="hljs-comment"># Perform email sending operations using SES client</span>
    response = ses_client.send_email(
        Source=<span class="hljs-string">'&lt;FromAddress&gt;'</span>,
        Destination={<span class="hljs-string">'ToAddresses'</span>: [email_id]},
        Message={
            <span class="hljs-string">'Subject'</span>: {<span class="hljs-string">'Data'</span>: <span class="hljs-string">'Your Subject'</span>},
            <span class="hljs-string">'Body'</span>: {<span class="hljs-string">'Text'</span>: {<span class="hljs-string">'Data'</span>: <span class="hljs-string">'Your Email Body'</span>}}
        }
    )

print(<span class="hljs-string">f"Email sent to <span class="hljs-subst">{email_id}</span>. Message ID: <span class="hljs-subst">{response[<span class="hljs-string">'MessageId'</span>]}</span>"</span>)
</code></pre>
<h2 id="heading-web-applications-and-apis">Web Applications and APIs</h2>
<p>It's true – you can't do web development just with Python. You'll still need HTML, CSS, and JavaScript. But when it comes to building backends for web applications, Python is a fantastic option. </p>
<p>Thanks to popular Python frameworks like <a target="_blank" href="https://www.notion.so/Draft-Script-1d2f649493b04a0f84acc9dcc91f0c7a?pvs=21">Django</a>, <a target="_blank" href="https://flask.palletsprojects.com/en/3.0.x/">Flask</a>, and <a target="_blank" href="https://fastapi.tiangolo.com/">FastAPI</a>, it's very easy to start building your web applications and APIs.</p>
<p>In most products and applications I build, I use a combination of <a target="_blank" href="https://nextjs.org/">NextJS</a> for the frontend, powered by a Python backend using FastAPI, and it's a killer combo. </p>
<p>But I'm not alone in choosing Python to build web backends. Companies like Microsoft, Instagram, Pinterest, and the Washington Post use Python to serve millions of users.</p>
<h2 id="heading-data-analysis-data-science-ai">Data Analysis / Data Science / AI</h2>
<p>Python is the undeniable leader in data science, artificial intelligence, and machine learning. This is in part thanks to its vast ecosystem of open-source libraries, like <a target="_blank" href="https://pandas.pydata.org/">Pandas</a>, <a target="_blank" href="https://numpy.org/">Numpy</a>, <a target="_blank" href="https://www.tensorflow.org/">Tensorflow</a>, and <a target="_blank" href="https://techcommunity.microsoft.com/t5/excel-blog/announcing-python-in-excel-combining-the-power-of-python-and-the/ba-p/3893439">Python in Excel</a> among others. This extensive toolkit empowers you to tackle virtually any challenge within these domains.</p>
<p>Are you performing complex statistical analysis? No problem, there's a library for that. Are you eager to start using state-of-the-art machine learning models? Python has you covered! Do you need a complex neural network? Of course, you can do that!</p>
<p>Python's vast ecosystem of libraries allows you to build what you need quickly, with libraries that are production-ready, fast, and efficient and that have high-quality APIs.</p>
<p>Here are some examples of related applications of Python for data science and AI:</p>
<ul>
<li>Time series analysis</li>
<li>Data Visualization</li>
<li>Sales predictions</li>
<li>Language processing</li>
<li>Sentiment analysis</li>
<li>Recommendation systems (like music, videos, and so on)</li>
<li>Classification</li>
<li>Computer vision</li>
<li>Self-driving cars</li>
<li>and many more...</li>
</ul>
<h2 id="heading-application-testing">Application Testing</h2>
<p>Python's user-friendly syntax and readability make it an excellent choice for QA testers of all skill levels. Its straightforward structure and clear code organization facilitate rapid prototyping and implementation of test scripts.</p>
<p>Again, it's thanks to Python's rich ecosystem with libraries like Playwright and Selenium that Python is a great option for this category.</p>
<p>For web applications, QA engineers write test scripts that load the application in a headless browser, normally a QA or test environment, and perform a series of validations to determine that the application is correctly working.</p>
<p>For example, if you want to test a user’s list page, you can load the page, and querying DOM elements, you can validate that effectively the app is rendering results. Even more so, you can simulate keyboard strokes, clicks, complete forms, and much more with these tools.</p>
<p>Here is a same script that loads the <a target="_blank" href="http://python.org/">python.org</a> website, performs a search, and validates that the result by comparing the resulting page against the <code>No results found</code> message.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> selenium <span class="hljs-keyword">import</span> webdriver
<span class="hljs-keyword">from</span> selenium.webdriver.common.keys <span class="hljs-keyword">import</span> Keys
<span class="hljs-keyword">from</span> selenium.webdriver.common.by <span class="hljs-keyword">import</span> By

<span class="hljs-comment"># Set the driver to use Firefox, can also be Chrome, IE, and Remote</span>
driver = webdriver.Firefox()
<span class="hljs-comment"># Load the target website</span>
driver.get(<span class="hljs-string">"http://www.python.org"</span>)
<span class="hljs-comment"># Validate that the page loaded by comparing the page title</span>
<span class="hljs-keyword">assert</span> <span class="hljs-string">"Python"</span> <span class="hljs-keyword">in</span> driver.title
<span class="hljs-comment"># Find the search input element by name</span>
elem = driver.find_element(By.NAME, <span class="hljs-string">"q"</span>)
<span class="hljs-comment"># Empty it</span>
elem.clear()
<span class="hljs-comment"># Type `pycon`</span>
elem.send_keys(<span class="hljs-string">"pycon"</span>)
<span class="hljs-comment"># Press an enter to trigger the search form</span>
elem.send_keys(Keys.RETURN)
<span class="hljs-comment"># Validate that the text `No results found.` is not present in the page</span>
<span class="hljs-keyword">assert</span> <span class="hljs-string">"No results found."</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> driver.page_source
<span class="hljs-comment"># Close the browser</span>
driver.close()
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Python's versatility and extensive library ecosystem make it an excellent choice for various projects. Whether you need to automate tasks, process data, build web applications and APIs, perform data analysis and AI, or conduct application testing, Python has you covered.</p>
<p>Its simplicity, readability, and powerful libraries allow you to achieve results quickly and efficiently. So, next time you're considering a programming language for your project, consider Python's strengths in these areas.</p>
<p>Thanks for reading!</p>
<p>You can follow me (<a target="_blank" href="https://twitter.com/bajcmartinez">@bajcmartinez</a>) along with <a target="_blank" href="https://twitter.com/jesstemporal">@jesstemporal</a> on Twitter/X to learn more about Python and how to build secure Python applications. We're developer advocates at <a target="_blank" href="https://auth0.com/">Auth0 by Okta</a> and regularly post content and live streams about Python.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Secure APIs with Flask and Auth0 ]]>
                </title>
                <description>
                    <![CDATA[ APIs are at the heart of modern development. They support all kinds of systems, from mobile, web, and desktop applications, to IoT devices and self-driving cars. They are a bridge between your clients and your application logic and storage.  This cen... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-secure-apis-with-flask-and-auth0/</link>
                <guid isPermaLink="false">66d039d433e91331eb22953b</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Auth0 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Flask Framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Juan Cruz Martinez ]]>
                </dc:creator>
                <pubDate>Wed, 08 Feb 2023 00:32:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/01/3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>APIs are at the heart of modern development. They support all kinds of systems, from mobile, web, and desktop applications, to IoT devices and self-driving cars. They are a bridge between your clients and your application logic and storage. </p>
<p>This central access point to your application’s data raises the question: how can you provide access to the information to those who need it while denying access to unauthorized requests?</p>
<p>The industry has provided several protocols and best practices for securing APIs. Today we will focus on <a target="_blank" href="https://auth0.com/docs/authorization/protocols/protocol-oauth2?utm_source=freecodecamp?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">OAuth2</a>, one of the most popular options for authorizing clients into our APIs.</p>
<p>But how do we implement OAuth2? There are two ways to go about it:</p>
<ol>
<li>Do it yourself approach</li>
<li>Work with a safe 3rd party like <a target="_blank" href="https://auth0.com/?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">Auth0</a></li>
</ol>
<p>In this article, I will walk you through an implementation of OAuth2 for Python and <a target="_blank" href="https://flask.palletsprojects.com/">Flask</a> using Auth0 as our identity provider. But first, we are going to discuss the do-it-yourself approach.</p>
<h2 id="heading-why-not-build-your-own-authentication-and-authorization">Why Not Build Your Own Authentication and Authorization?</h2>
<p>For a few years now, I wanted to give back to the community that helped me so much by teaching me programming and helping me progress in my search for knowledge. I always thought that a great way to contribute was by having my own blog, a thing that I tried more than a few times and failed. </p>
<p>But where did I fail? Instead of focusing on writing, I tried to build my own blog engine because it’s in my nature. It’s what developers do. They love to build.</p>
<p>But why do I mention that here? Because many fall into the same trap when building APIs. Let me explain with an example.</p>
<p>Bob is a great developer, and he has this great idea for a ToDo app that can be the next big thing. Bob is very aware that for a successful implementation, users can only access their own data.</p>
<p>Here is bob’s application timeline:</p>
<ul>
<li>Sprint 0: Research ideas and start prototyping</li>
<li>Sprint 1: Build user table and login screen with API</li>
<li>Sprint 2: Add password reset screens and build all email templates</li>
<li>Sprint 3: Build, create and list ToDos screens</li>
<li>Sprint 4: MVP goes live</li>
<li>User feedback:<ul>
<li>Some users can’t log in due to a bug</li>
<li>Some users feel unsafe without 2-factor authentication</li>
<li>Some users don’t want to get yet another password. They prefer single sign-on with Google or Facebook.</li>
<li>…</li>
</ul>
</li>
</ul>
<p>Let’s talk about what happened. Bob spent the first few sprints not building his app but building the basic blocks, like logging in and out functionality, email notifications, and so on. This valuable time could have been spent differently, but what happens next is more concerning.</p>
<p>Bob’s backlog starts to fill in. Now, he needs to improvise a 2-factor authentication method, add single sign-on, and more non-product-related functions that could potentially delay his product.</p>
<p>And there’s still a big question to be answered: did Bob implement all the security mechanisms correctly? A critical error could expose all the user’s information to outsiders.</p>
<p>What Bob did is what I did with my blog many times. Sometimes, it's helpful to rely on 3rd parties if we want to get things done right.</p>
<p>Today, hackers and attacks have become so sophisticated that security is not a trivial factor anymore. It is a complicated system on its own, and it is often best to leave its implementation to experts – not only so it’s done right, but also so we can focus on what matters: building our applications and APIs.</p>
<h2 id="heading-how-to-set-up-a-free-auth0-identity-management-account">How to Set Up a Free Auth0 Identity Management Account</h2>
<p><a target="_blank" href="https://auth0.com/?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">Auth0</a> is a leading authentication and authorization provider, but let’s see how it can help Bob (or you) build a better app:</p>
<ol>
<li>It <a target="_blank" href="https://auth0.com/learn/finn-ai-saves-10-5-ongoing-engineering-time-auth0/?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">saves time</a></li>
<li>It’s <a target="_blank" href="https://auth0.com/security?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">secure</a></li>
<li>It has a <a target="_blank" href="https://auth0.com/pricing?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">free plan</a></li>
</ol>
<p>Time to get practical. First, make sure you have an Auth0 account. If not, you can create one <a target="_blank" href="https://auth0.com/signup/?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">here for free</a>.</p>
<h3 id="heading-create-a-new-auth0-api">Create a New Auth0 API</h3>
<p>There is still one more thing we have to do before we start coding. Head over to the <a target="_blank" href="https://manage.auth0.com/#/apis?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">APIs</a> section of your Auth0 dashboard and click on the “Create API” button. After that, fill in the form with your details. However, make sure you select <code>RS256</code> as the <code>Signing Algorithm</code>.</p>
<p>Your form should look like the following:</p>
<p><img src="https://lh5.googleusercontent.com/XccGez21ClEDsCECuKwiF_1AF5gj2OXXaJKEXVUOBFmxQ7Ci11a1g1O3cu_io185YbdnSJkAlu3dmP0pt6Ww-N6cPqQLTIeweSi2hNv4ototIkuSZhfiprjqcMrFhcMLaGkKfedkm8D0PR2IcjdLPGUChKS27wsiPMvqCsysQRJyGANVYc5Q5EbFdaFo" alt="Image" width="1298" height="1252" loading="lazy">
<em>Creating the API – image showing fields to fill out</em></p>
<p>The API details page opens after successfully creating an API. Keep that tab open, as it contains information we need to set up our application. If you close it, don’t worry, you can always access it again.</p>
<h2 id="heading-how-to-bootstrap-our-application">How to Bootstrap our Application</h2>
<p>Because we will focus on the security aspects only, we will take a few shortcuts when building our demo API. However, when developing <a target="_blank" href="https://livecodestream.dev/post/python-flask-api-starter-kit-and-project-layout/?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">actual APIs</a>, please follow <a target="_blank" href="https://auth0.com/blog/best-practices-for-flask-api-development/?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">best practices for Flask APIs</a>.</p>
<h3 id="heading-install-the-dependencies">Install the dependencies</h3>
<p>First, install the following dependencies for setting up Flask and authenticating users.</p>
<pre><code class="lang-shell">pipenv install flask python-dotenv python-jose flask-cors six
</code></pre>
<h3 id="heading-build-the-endpoints">Build the endpoints</h3>
<p>Our API will be straightforward. It will consist of only three endpoints, all of which, for now, will be publicly accessible. However, we will fix that soon. Here are our endpoints:</p>
<ul>
<li><code>/</code> (public endpoint)</li>
<li><code>/user</code> (requires a logged in user)</li>
<li><code>/admin</code> (only users of admin role)</li>
</ul>
<p>Let’s get to it:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask

app = Flask(__name__)

<span class="hljs-meta">@app.route("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index_view</span>():</span>
    <span class="hljs-string">"""
    Default endpoint, it is public and can be accessed by anyone
    """</span>
    <span class="hljs-keyword">return</span> jsonify(msg=<span class="hljs-string">"Hello world!"</span>)

<span class="hljs-meta">@app.route("/user")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_view</span>():</span>
    <span class="hljs-string">"""
    User endpoint, can only be accessed by an authorized user
    """</span>
    <span class="hljs-keyword">return</span> jsonify(msg=<span class="hljs-string">"Hello user!"</span>)

<span class="hljs-meta">@app.route("/admin")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">admin_view</span>():</span>
    <span class="hljs-string">"""
    Admin endpoint, can only be accessed by an admin
    """</span>
    <span class="hljs-keyword">return</span> jsonify(msg=<span class="hljs-string">"Hello admin!"</span>)
</code></pre>
<p>Very simple right? Let’s run it:</p>
<pre><code class="lang-shell">~ pipenv run flask run
* Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
</code></pre>
<p>And if we access our endpoint:</p>
<pre><code class="lang-shell">~ curl -i http://localhost:5000
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 23
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 21:24:57 GMT

{"msg":"Hello world!"}

~ curl -i http://localhost:5000/user
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 22
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 21:25:42 GMT

{"msg":"Hello user!"}

~ curl -i http://localhost:5000/admin
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 23
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 21:26:18 GMT

{"msg":"Hello admin!"}
</code></pre>
<h2 id="heading-how-to-secure-the-endpoints">How to Secure the Endpoints</h2>
<p>As we are using OAuth, we will authenticate requests by validating an access token in <a target="_blank" href="https://auth0.com/learn/json-web-tokens/?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">JWT format</a>. We'll send it to the API on each request as part of the HTTP headers.</p>
<h3 id="heading-auth0-configuration-variables">Auth0 configuration variables</h3>
<p>As mentioned in the previous section, our API needs to be aware and will require information from our Auth0 dashboard. So head back to your <a target="_blank" href="https://manage.auth0.com/#/apis?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">API details page</a>, and grab two different values.</p>
<p><strong>First, the API Identifier:</strong></p>
<p>This is the value required when the API is created. You can also get it from your API details page:</p>
<p><img src="https://lh5.googleusercontent.com/UffKcasZXNZmXldeB8nhDEjzmOPVao3PR6EUVPbtWzXStuDzcCw2kr5ztEnr0VlWCkBLbhleAM-D11Cv5Cv8fcII8m24D6TfEe4XfxWe8HXN1aNrF-dHeN05zeVeoNfQISWh-VPf0__x8uVfJPL3GGHYIC87utfrr6734Z9Wdk-9eJUApslcdUKOyoSh" alt="Image" width="1600" height="699" loading="lazy">
<em>How to find the API identifier on the API details page</em></p>
<p><strong>Next, Auth0 domain:</strong></p>
<p>Unless you're using a custom domain, this value will be <a target="_blank"><code>[TENANT_NAME].auth0.com</code></a>, and you can grab it from the <code>Test</code> tab (make sure not to include <code>https://</code> and the last forward slash <code>/</code>).</p>
<p><img src="https://lh4.googleusercontent.com/cA63NdLr4AWOz2O3jTWBXTTqc7DrGOr1aPOIpNDRYl97-o84I_lX8KtotCm6hRWF06ai0RjiJzgTjS_zRlySKFAB-XO1w737N05i7-bC2-GZioOpcWuS5gaRoEnDL63gXnm5CyP6JOEQusRLQMF1sY_1vjfXtdMVIr5uCW1PMIpokH76lpMq2VFZSIyf" alt="Image" width="1600" height="1037" loading="lazy">
<em>Getting the Auth0 domain</em></p>
<p>Next, pass those values into variables so they can be used in the validation functions.</p>
<pre><code class="lang-python">AUTH0_DOMAIN = <span class="hljs-string">'YOUR-AUTH0-DOMAIN'</span>
API_IDENTIFIER = <span class="hljs-string">'API-IDENTIFIER'</span>
ALGORITHMS = [<span class="hljs-string">"RS256"</span>]
</code></pre>
<h3 id="heading-error-methods">Error methods</h3>
<p>During this implementation, we will need a way to throw errors when authentication fails. So we will use the following helpers for those needs:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AuthError</span>(<span class="hljs-params">Exception</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, error, status_code</span>):</span>
        self.error = error
        self.status_code = status_code

<span class="hljs-meta">@app.errorhandler(AuthError)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handle_auth_error</span>(<span class="hljs-params">ex</span>):</span>
    response = jsonify(ex.error)
    response.status_code = ex.status_code
    <span class="hljs-keyword">return</span> response
</code></pre>
<h3 id="heading-how-to-capture-the-jwt-token">How to capture the JWT token</h3>
<p>The first step to validate a user is to retrieve the JWT token from the HTTP headers. This is very simple, but there are a few things to keep in mind. Here is an example of it:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_token_auth_header</span>():</span>
    <span class="hljs-string">"""
    Obtains the Access Token from the Authorization Header
    """</span>
    auth = request.headers.get(<span class="hljs-string">"Authorization"</span>, <span class="hljs-literal">None</span>)
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> auth:
        <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"authorization_header_missing"</span>,
                        <span class="hljs-string">"description"</span>:
                            <span class="hljs-string">"Authorization header is expected"</span>}, <span class="hljs-number">401</span>)

    parts = auth.split()

    <span class="hljs-keyword">if</span> parts[<span class="hljs-number">0</span>].lower() != <span class="hljs-string">"bearer"</span>:
        <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"invalid_header"</span>,
                        <span class="hljs-string">"description"</span>:
                            <span class="hljs-string">"Authorization header must start with"</span>
                            <span class="hljs-string">" Bearer"</span>}, <span class="hljs-number">401</span>)
    <span class="hljs-keyword">elif</span> len(parts) == <span class="hljs-number">1</span>:
        <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"invalid_header"</span>,
                        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Token not found"</span>}, <span class="hljs-number">401</span>)
    <span class="hljs-keyword">elif</span> len(parts) &gt; <span class="hljs-number">2</span>:
        <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"invalid_header"</span>,
                        <span class="hljs-string">"description"</span>:
                            <span class="hljs-string">"Authorization header must be"</span>
                            <span class="hljs-string">" Bearer token"</span>}, <span class="hljs-number">401</span>)

    token = parts[<span class="hljs-number">1</span>]
    <span class="hljs-keyword">return</span> token
</code></pre>
<h3 id="heading-how-to-validate-the-token">How to validate the token</h3>
<p>Having a token passed to our API is a good sign, but it doesn’t mean that it is a valid client. We need to check the token signature.</p>
<p>Since the logic to require authentication can be used for more than one endpoint, it would be important to abstract it and make it easily accessible for developers to implement. The best way to do this is by using <a target="_blank" href="https://book.pythontips.com/en/latest/decorators.html">decorators</a>.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">requires_auth</span>(<span class="hljs-params">f</span>):</span>
    <span class="hljs-string">"""
    Determines if the Access Token is valid
    """</span>
<span class="hljs-meta">    @wraps(f)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorated</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        token = get_token_auth_header()
        jsonurl = urlopen(<span class="hljs-string">"https://"</span>+AUTH0_DOMAIN+<span class="hljs-string">"/.well-known/jwks.json"</span>)
        jwks = json.loads(jsonurl.read())
        unverified_header = jwt.get_unverified_header(token)
        rsa_key = {}
        <span class="hljs-keyword">for</span> key <span class="hljs-keyword">in</span> jwks[<span class="hljs-string">"keys"</span>]:
            <span class="hljs-keyword">if</span> key[<span class="hljs-string">"kid"</span>] == unverified_header[<span class="hljs-string">"kid"</span>]:
                rsa_key = {
                    <span class="hljs-string">"kty"</span>: key[<span class="hljs-string">"kty"</span>],
                    <span class="hljs-string">"kid"</span>: key[<span class="hljs-string">"kid"</span>],
                    <span class="hljs-string">"use"</span>: key[<span class="hljs-string">"use"</span>],
                    <span class="hljs-string">"n"</span>: key[<span class="hljs-string">"n"</span>],
                    <span class="hljs-string">"e"</span>: key[<span class="hljs-string">"e"</span>]
                }
        <span class="hljs-keyword">if</span> rsa_key:
            <span class="hljs-keyword">try</span>:
                payload = jwt.decode(
                    token,
                    rsa_key,
                    algorithms=ALGORITHMS,
                    audience=API_IDENTIFIER,
                    issuer=<span class="hljs-string">"https://"</span>+AUTH0_DOMAIN+<span class="hljs-string">"/"</span>
                )
            <span class="hljs-keyword">except</span> jwt.ExpiredSignatureError:
                <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"token_expired"</span>,
                                <span class="hljs-string">"description"</span>: <span class="hljs-string">"token is expired"</span>}, <span class="hljs-number">401</span>)
            <span class="hljs-keyword">except</span> jwt.JWTClaimsError:
                <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"invalid_claims"</span>,
                                <span class="hljs-string">"description"</span>:
                                    <span class="hljs-string">"incorrect claims,"</span>
                                    <span class="hljs-string">"please check the audience and issuer"</span>}, <span class="hljs-number">401</span>)
            <span class="hljs-keyword">except</span> Exception:
                <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"invalid_header"</span>,
                                <span class="hljs-string">"description"</span>:
                                    <span class="hljs-string">"Unable to parse authentication"</span>
                                    <span class="hljs-string">" token."</span>}, <span class="hljs-number">401</span>)

            _request_ctx_stack.top.current_user = payload
            <span class="hljs-keyword">return</span> f(*args, **kwargs)
        <span class="hljs-keyword">raise</span> AuthError({<span class="hljs-string">"code"</span>: <span class="hljs-string">"invalid_header"</span>,
                        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Unable to find appropriate key"</span>}, <span class="hljs-number">401</span>)
    <span class="hljs-keyword">return</span> decorated
</code></pre>
<p>The newly created <code>requires_auth</code> decorator, when applied to an endpoint, will automatically reject the request if no valid user can be authenticated.</p>
<h3 id="heading-how-to-require-an-authenticated-request-for-an-endpoint">How to require an authenticated request for an endpoint</h3>
<p>We are ready to secure our endpoints, let’s update the <code>user</code> and <code>admin</code> endpoints to utilize our decorator.</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route("/user")</span>
<span class="hljs-meta">@requires_auth</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_view</span>():</span>
    <span class="hljs-string">"""
    User endpoint, can only be accessed by an authorized user
    """</span>
    <span class="hljs-keyword">return</span> jsonify(msg=<span class="hljs-string">"Hello user!"</span>)

<span class="hljs-meta">@app.route("/admin")</span>
<span class="hljs-meta">@requires_auth</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">admin_view</span>():</span>
    <span class="hljs-string">"""
    Admin endpoint, can only be accessed by an admin
    """</span>
    <span class="hljs-keyword">return</span> jsonify(msg=<span class="hljs-string">"Hello admin!"</span>)
</code></pre>
<p>Our only change was adding <code>@required_auth</code> at the top of the declaration of each endpoint function, and with that we can test once again:</p>
<pre><code class="lang-shell">~ curl -i http://localhost:5000/user
HTTP/1.0 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 89
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 21:42:26 GMT

{"code":"authorization_header_missing","description":"Authorization header is expected"}

~ curl -i http://localhost:5000/admin
HTTP/1.0 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 89
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 21:42:42 GMT

{"code":"authorization_header_missing","description":"Authorization header is expected"}
</code></pre>
<p>As expected, we can’t access our endpoints as the authorization header is missing. But before we add one, let’s see if our public endpoint still works:</p>
<pre><code class="lang-shell">~ curl -i http://localhost:5000
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 23
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 21:43:55 GMT

{"msg":"Hello world!"}
</code></pre>
<p>Awesome, it works as expected.</p>
<h3 id="heading-how-to-test-it-out">How to test it out</h3>
<p>For testing our newly secured endpoints, we need to get a valid access token that we can pass to the request. We can do that directly on the <code>Test</code> tab on the API details page, and it’s as simple as copying a value from the screen:  </p>
<p><img src="https://lh5.googleusercontent.com/XCAWL5taQUs3_5qcAdukl9FP_aTVLya-jyS_4IivFW6JCAfX5d2hbPPCIV4PB8QgcuceQrzC__YYpWMQB1y8HT9AnKO01XH5rCiofvQJAmiAPnGF42FcJFxaVHTLLQcL9UpzFjYgan0Qasna69DlZ8AIkoATbqAtqtqibWUszhvakHZiytPNduTU7_Hb" alt="Image" width="1600" height="1062" loading="lazy">
<em>Copying the token for testing</em></p>
<p>Once we have the token we can change our curl request accordingly:</p>
<pre><code class="lang-shell">~ curl -i -H "Authorization: bearer [ACCESS_TOKEN]"  http://localhost:5000/user
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 22
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 22:17:06 GMT

{"msg":"Hello user!"}
</code></pre>
<p>Please remember to replace <code>[ACCESS_TOKEN]</code> with the value you copied from the dashboard.</p>
<p>It works! But we still have some work to do. Even though our <code>/admin</code> endpoint is secured, it can be accessed by any user:</p>
<pre><code class="lang-shell">~ curl -i -H "Authorization: bearer [ACCESS_TOKEN]"  http://localhost:5000/admin
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 23
Server: Werkzeug/2.0.1 Python/3.9.1
Date: Tue, 24 Jan 2023 22:21:09 GMT

{"msg":"Hello admin!"}
</code></pre>
<h3 id="heading-role-based-access-control">Role-based access control</h3>
<p>For role-based access control there’s a few things we need to do:</p>
<ol>
<li>Create permissions for the API</li>
<li>Enable adding permissions to the JWT for the API</li>
<li>Update the code</li>
<li>Test with users</li>
</ol>
<p>The first 2 points are very well explained in the <a target="_blank" href="https://auth0.com/docs/authorization/rbac/auth-core-features?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">Auth0 docs</a>, so just make sure you add the corresponding permissions on your API. </p>
<p>Next, we need to update the code. We need a function to check if a given permission exists in the access token and return <code>True</code> if it does and <code>False</code> if it does not:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">requires_scope</span>(<span class="hljs-params">required_scope</span>):</span>
    <span class="hljs-string">"""
    Determines if the required scope is present in the Access Token
    Args:
        required_scope (str): The scope required to access the resource
    """</span>
    token = get_token_auth_header()
    unverified_claims = jwt.get_unverified_claims(token)
    <span class="hljs-keyword">if</span> unverified_claims.get(<span class="hljs-string">"scope"</span>):
            token_scopes = unverified_claims[<span class="hljs-string">"scope"</span>].split()
            <span class="hljs-keyword">for</span> token_scope <span class="hljs-keyword">in</span> token_scopes:
                <span class="hljs-keyword">if</span> token_scope == required_scope:
                    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p>And lastly, it can be used as follows:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route("/admin")</span>
<span class="hljs-meta">@requires_auth</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">admin_view</span>():</span>
    <span class="hljs-string">"""
    Admin endpoint, can only be accessed by an admin
    """</span>
    <span class="hljs-keyword">if</span> requires_scope(<span class="hljs-string">"read:admin"</span>):
        <span class="hljs-keyword">return</span> jsonify(msg=<span class="hljs-string">"Hello admin!"</span>)

    <span class="hljs-keyword">raise</span> AuthError({
        <span class="hljs-string">"code"</span>: <span class="hljs-string">"Unauthorized"</span>,
        <span class="hljs-string">"description"</span>: <span class="hljs-string">"You don't have access to this resource"</span>
    }, <span class="hljs-number">403</span>)
</code></pre>
<p>Now, only users with the permission <code>read:admin</code> can access our admin endpoint.</p>
<p>In order to test your final implementation, you can follow the steps detailed on <a target="_blank" href="https://auth0.com/docs/quickstart/backend/python/02-using#obtaining-an-access-token?utm_source=freecodecamp&amp;utm_medium=sc&amp;utm_campaign=securing_flask">obtaining an access token</a> for a given user. </p>
<p>You can also use the Auth0 Dashboard to test permissions, but that is outside the scope of this article. If you would like to learn more about it, read <a target="_blank" href="https://auth0.com/blog/permission-based-security-aspnet-webapi/#Testing-Permissions">here</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Today we learned how to secure a Flask API. We explored the do-it-yourself path, and we built a secure API with three levels of access – public access, private access and privately-scoped access.</p>
<p>There’s so much more that Auth0 can do for your APIs and also for your client applications. Today we just scratched the surface, and it’s up to you and your team when working with real-life scenarios to explore all the potential of their services.</p>
<p>The full code is available on <a target="_blank" href="https://gist.github.com/bajcmartinez/5062aa41ccbe2df1bbf4f1a9b95bd085">GitHub</a>.</p>
<p>Thanks for reading! If you like my teaching style, you can <a target="_blank" href="https://livecodestream.dev/newsletter/">Subscribe to my weekly newsletter</a> for developers and builders and get a weekly email with relevant content<em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your Personal Brand as a Freelance Developer ]]>
                </title>
                <description>
                    <![CDATA[ You probably didn’t get into freelance development to become a marketer.  You got into freelancing so you could work when you want, make more money, and control your life. But, if you haven’t realized it yet, building a career as a freelancer require... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/branding-for-developer-freelancers/</link>
                <guid isPermaLink="false">66d039d064be048ac359a356</guid>
                
                    <category>
                        <![CDATA[ branding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Freelancing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Juan Cruz Martinez ]]>
                </dc:creator>
                <pubDate>Wed, 12 Oct 2022 13:52:08 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/Standard-Blog-Post.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You probably didn’t get into freelance development to become a marketer. </p>
<p>You got into freelancing so you could work when you want, make more money, and control your life.</p>
<p>But, if you haven’t realized it yet, building a career as a freelancer requires you to embrace more than just writing code.</p>
<p>Part of developing your career is <em>branding</em>.</p>
<p>You recognize something magical about big brands like Apple, Mcdonald's, or Shell.</p>
<p>You see a logo and know instantly what it stands for and what it delivers.</p>
<p>These international companies have huge marketing budgets, so they can spend large amounts of money on branding.</p>
<p>You probably also recognize the <em>personal brands</em> of well-known celebrities who are associated with certain types of movies or who promote popular products.</p>
<p>Yet you feel that pinning down your personal brand is hard. It is!</p>
<p>But don’t worry. I’m going to walk you through a simple process for building a personal brand. </p>
<p>By the time you're done reading this article, you’ll know how to build your brand.</p>
<h2 id="heading-why-building-a-personal-brand-is-important">Why Building a Personal Brand is Important</h2>
<p>As I mentioned in <a target="_blank" href="https://livecodestream.dev/post/how-to-generate-leads-as-a-freelancer/">How to Generate Leads as a Freelancer</a>, it can be tough to stand out from the crowd. So you need to showcase your business and make connections with potential clients.</p>
<p>One way to do this is to harness the power and potential of a <em>personal brand</em>. </p>
<p>Many freelancers think branding is hard, complicated, time-consuming, or unpleasant.</p>
<p>It can be, but only if you approach it the <strong>wrong</strong> way.</p>
<p>Your personal brand is very simple - it’s <em>you</em>.</p>
<p>It’s the picture of you, the essence of how you work, and how you want people to talk about you when they tell others about your work.</p>
<ul>
<li>Daniel is a database engineer who does great work in both SQL and PHP.</li>
<li>Erin is a full-stack web developer who helps small companies create websites ready for Web3.</li>
<li>Juan teaches people how to build a career as a programmer.</li>
</ul>
<p>All three of these are examples of a personal brand that connects what they do and what they want <em>others</em> to think about when they think of their brands.</p>
<p>It all starts here by identifying what you do and how you want other people to talk about and think about you and your work. When you know this, everything else becomes easy.</p>
<h2 id="heading-how-to-start-building-your-personal-brand">How to Start Building Your Personal Brand</h2>
<p>You begin by committing to one essential thing: <em>staying true to yourself.</em></p>
<p>Your brand can’t be some digital costume you wear to get clients. They’ll see through that in a heartbeat.</p>
<p>It needs to come from <strong>who you are.</strong></p>
<p>So, ask yourself three questions:</p>
<h3 id="heading-1-who-am-i">1. Who am I?</h3>
<p>Start by defining yourself as a freelancer with 3 - 4 key words or phrases that you want to define your work, such as:</p>
<ul>
<li>Creative</li>
<li>Easy to work with</li>
<li>Hardworking</li>
<li>Reliable</li>
</ul>
<p>How do you want people to describe what it means to work with you?</p>
<h3 id="heading-2-what-do-i-do">2. What do I do?</h3>
<p>Then, get specific about what you do (and what you don’t do). For example,  </p>
<ul>
<li>I design mobile-responsive websites using Java and PHP.</li>
<li>I write secure apps based on Web3 technology.</li>
<li>I close security gaps in websites and recover business sites that have been hijacked with ransomware.</li>
</ul>
<p>These statements don’t say, “I design websites” or “I write apps.” That’s too generic.</p>
<p>Be <em>specific</em> about what you do.</p>
<p>Getting clear about what you do means you’ll attract the right type of clients.</p>
<h3 id="heading-3-what-makes-me-unique">3. What makes me unique?</h3>
<p>Finally, it’s easy to chase a persona or identity you’ve seen used successfully by someone else. But don’t do something because you’ve seen it be successful <em>for someone else.</em></p>
<p><strong>Stay true to who you are</strong> (refer to your <em>Who Am I?</em> list):</p>
<ul>
<li>Do you love to change your hair color? Embrace that.</li>
<li>Do you have a defining personality trait that makes you different or special? Promote it.</li>
<li>Do you have a particular skill or spread of skills that means you can offer something unique? Don’t hide it – use it as a way to differentiate yourself.</li>
</ul>
<p>For more tips on <a target="_blank" href="https://livecodestream.dev/post/how-to-promote-your-services-as-a-freelancer/">How to Promote Your Services (and yourself) as a Freelancer</a>, read this.</p>
<h2 id="heading-define-your-look">Define Your Look</h2>
<p>This is the hard part, especially for those of us who are not natural designers.</p>
<p>Surprisingly, you want to know the hardest part about defining your look? </p>
<p><em>Keeping it simple.</em></p>
<p>The mistake most people make in developing the visuals for a brand is that they develop things that are far too complicated and detailed.</p>
<p>When you work on defining the “look” for your business, follow three principles:</p>
<ol>
<li>Keep everything related to your brand within 2-3 colors.</li>
<li>Design a <em>simple</em> and <em>timeless</em> logo.</li>
<li>Invest in good photos.</li>
</ol>
<p>Don’t chase trends, “in colors,” or new and exciting things. Find and embrace something that will look good all the time.</p>
<p>The colors you use, the logo on your emails and letterhead, and the images you use for social media will define your brand and will communicate a lot of subtle things about how it is to work with you.</p>
<p>If it’s simple, clear, and easy, YOU will be associated with these things.</p>
<p>There are a lot of books, blogs, and websites that teach you what colors to choose and how to build a visual brand.</p>
<p>But, for most freelancers, the best piece of advice is simple:</p>
<p><strong>Get help from an expert.</strong></p>
<p>I understand the impulse to save money by trying to do it yourself.</p>
<p>But unless you have some design skills (or want to spend a lot of time learning), you lose far more than you win by trying to do it yourself.</p>
<p>It takes more time, you’ll make more mistakes, and the results won’t be nearly as good as they could be.</p>
<p>Someone who knows the principles of design will make you look better than you will. </p>
<p>Remember the importance of first impressions!</p>
<p>Old, fuzzy, outdated photos of yourself are unprofessional and could stop new clients from working with you.</p>
<p>And, just because your friend claims to design logos doesn’t mean they are good at it. </p>
<p>Instead, take the plunge and invest in a professional photographer, or hop onto 99designs and have someone develop a logo for you.</p>
<p>Get expert advice to figure out how your website should flow. </p>
<p>Find someone who specializes in web design to help you improve the look and feel of your site.</p>
<p>Even though it may cost more upfront, these investments will reward you with a brand that attracts clients and genuinely represents you.</p>
<h2 id="heading-tell-your-story">Tell Your Story</h2>
<p>Every freelancer needs to be able to talk about their business fluently and comfortably.</p>
<p>But you’d be surprised how hard it is for many freelancers to answer the question, <em>What do you do?</em></p>
<p>The key is to <strong>prepare ahead of time.</strong></p>
<p>Write out (literally) what you’ll say to people and how you’ll describe your freelancing career <em>before</em> they ask the question.</p>
<p>Your answers will come out clearer, they’ll sound polished, and you’ll feel better delivering them when you aren’t making it up on the spot.</p>
<p>There are four “versions” of your story that you’ll need to develop.</p>
<h3 id="heading-1-the-taglineslogan">1. The tagline/slogan.</h3>
<ul>
<li><em>Bringing websites into the web3 era.</em></li>
<li><em>Web development made simple.</em></li>
<li><em>Integrating your website into everything you do.</em></li>
</ul>
<p>A good tagline is clear, short, and delivers the essential value of what you do in one simple statement. </p>
<p>Notice what a tagline does not have: details, explanations, or descriptions. Instead, it focuses on the <strong>benefits you deliver</strong>.</p>
<p>You use a tagline in a website header, on a business card, or to book-end a promotional video in places where you don’t have time or space to get detailed.</p>
<h3 id="heading-2-the-elevator-pitch">2. The elevator pitch</h3>
<p>This expands on the tagline by giving just a bit more information and <strong>focusing on the service you provide</strong> (instead of simply the benefit).</p>
<ul>
<li>I help small businesses integrate web3 technology into websites before their competitors.</li>
<li>As a full-stack developer, I manage and coordinate website design and updates for businesses.</li>
<li>I help businesses find ways to use their websites to increase sales and cut costs, improving business revenue.</li>
</ul>
<p>The elevator pitch is great for introductions and introducing yourself at a conference. It gives someone just a bit of detail, but not enough to feel overwhelmed or like you are trying to make a sale with them.</p>
<h3 id="heading-3-a-short-bio">3. A short bio</h3>
<p>This is a few sentences or short paragraphs about how you started doing what you do and why you have customers today.</p>
<blockquote>
<p><em>I graduated in 2015 from <strong>__</strong> University with a degree in computer engineering. After several years of honing my skills in a corporate setting, I decided to take what I’d learned and help small businesses achieve the same success.</em>   </p>
<p><em>In 2019, I launched my own freelance career, and by 2020, it grew into a full-time career.</em>   </p>
<p><em>Today, I’ve worked with clients in 3 countries, successfully completing more than 45 different website projects covering everything from website redesigns to integrating new functionality into existing websites.</em></p>
</blockquote>
<p>Everything in this description communicates information relevant to someone who is considering hiring you by answering questions about experience, success, and expertise.</p>
<p>If you are giving a presentation at a local chamber of commerce event or a breakout session at a regional conference, a short bio is a great thing to provide to attendees. It’s also great to have ready-to-go for initial client meetings or sales calls because you can give them important, relevant information to establish your credibility.</p>
<h3 id="heading-4-a-long-bio">4. A long bio</h3>
<p>The difference between a short and long bio is more than length. </p>
<p>In the longer bio, you can add a bit more personality (though you should keep this simple) and more details about your business.</p>
<p>In the example below, you’ll notice where I added some additional detail.</p>
<blockquote>
<p><em>I graduated in 2015 from <strong>__</strong> University with a degree in computer engineering. <strong>This degree focused on programming, giving me expertise in SQL, PHP, Python, and Java.</strong></em>   </p>
<p><em>After several years of honing my skills in a corporate setting **leading increasingly large teams at <em>__</em></em> and <strong>__</strong>**, I decided to take what I’d learned and help small businesses achieve the same success._   </p>
<p><em>In 2019, I launched my own freelance career, and by 2020, it grew into a full-time career. Today, I’ve worked with clients in 3 countries, successfully completing more than 45 different website projects covering everything from website redesigns to integrating new functionality into existing websites.</em>    </p>
<p><em><strong>Over the course of this time, my projects have become increasingly complex. Not only have I gained experience in several additional languages and skills, but I’ve also become a Six Sigma Green Belt.</strong></em></p>
</blockquote>
<p>The long bio is great for the “about” page on your website.</p>
<p>By planning ahead (and literally writing out) these four versions of your story, you’ll feel more confident selling your brand to clients and answering any questions they may have about your business.</p>
<p>Following the steps I’ve laid out so far will help you hone and develop your unique brand to represent your freelance business. But successful marketing doesn’t stop with that.</p>
<h2 id="heading-share-your-work">Share Your Work</h2>
<p>Building your brand is only good if people see it. Once you’ve established your brand identity, it’s time to share it with the world.</p>
<p>As I emphasize in <a target="_blank" href="https://livecodestream.dev/post/how-to-get-better-at-sales/">How to Get Better at Sales</a>, selling and marketing your business requires a long-term mindset. You must actively pursue new connections and opportunities.</p>
<p>When you complete a new project, share it with current and potential clients.</p>
<p>Seek and share client testimonials.</p>
<p>Get active on social media by answering questions, offering your insight on important questions in your field, and building a following.</p>
<p>Interact with people – everywhere.</p>
<p>This could be on social media, tweeting, replying, and re-tweeting your brand and business. </p>
<p>But this could also involve building a blog or speaking at conferences. You could start a podcast or become active at your local Chamber.</p>
<p>And don’t forget to focus on giving back to people in your community.</p>
<p>It’s easy to turn every interaction into a transaction, measuring it by whether or not you’ve gained followers, increased subscribers, or signed a new client. </p>
<p>But, one of the most important elements to developing a real, vibrant, and believable personal brand is to give back to people.</p>
<p>So, be generous with your time, expertise, and knowledge because people will notice.</p>
<h2 id="heading-examples-of-developers-with-a-great-personal-brands">Examples of developers with a great personal brands</h2>
<h3 id="heading-simon-hoiberg">Simon Høiberg</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-47.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://twitter.com/SimonHoiberg">Simon</a> is a great example of a developer who's cultivated his personal brand. Just by looking at his Twitter profile we can easily understand all about his brand. </p>
<p>He makes it very clear from the go what you would expect from him on the platform, what is he working on, his YouTube channel, and his passion to talk about SaaS, tech, and business.</p>
<p>His growth has been exponential everywhere he goes – Twitter, LinkedIn, and YouTube.</p>
<p>If you want get inspiration, definitely check him out.</p>
<h3 id="heading-james-q-quick">James Q. Quick</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-48.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once again, an example of delivering a message directly on his Twitter profile, we have <a target="_blank" href="https://twitter.com/jamesqquick">James</a>. Just with a quick look we can tell he is all about content creation for developers, he does public speaking, online teaching, and he runs a podcast.</p>
<h3 id="heading-ania-kubow">Ania Kubów</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-49.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://twitter.com/ania_kubow">Ania</a> is another great example. She focuses on building games with JavaScript on her YouTube channel and is also a super star here at freeCodeCamp.</p>
<p>Her brand is very clear and distinctive when you look at her social media profiles.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You <em>can</em> build an honest, vibrant, and engaging personal brand, even if marketing isn’t your particular strength.</p>
<p>The keys are simple:</p>
<ul>
<li>Define who you are and what makes your business unique</li>
<li>Invest in a professional to help to design your brand.</li>
<li>Prepare (in advance) to tell your story.</li>
<li>Share your personal brand and your work through genuine connections with people.</li>
</ul>
<p>Follow my advice, and you’ll soon reap the benefits of a successful marketing brand that attracts clients and allows you to pursue the financial and flexible rewards of freelancing.</p>
<p>Before you go, if you want to learn more about web development, how to code, freelancing and making money online as a developer, check out my <a target="_blank" href="https://livecodestream.dev/newsletter/">free newsletter</a>.</p>
<p>Thanks for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Deep Learning Tutorial – How to Use PyTorch and Transfer Learning to Diagnose COVID-19 Patients ]]>
                </title>
                <description>
                    <![CDATA[ Ever since the outbreak of COVID-19 in December 2019, researchers in the field of artificial intelligence and machine learning have been trying to find better ways to diagnose the disease. They've worked on developing algorithms that would detect the... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/deep-learning-with-pytorch/</link>
                <guid isPermaLink="false">66d039da64be048ac359a35b</guid>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ neural networks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ pytorch ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Transfer learning ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Juan Cruz Martinez ]]>
                </dc:creator>
                <pubDate>Wed, 03 Nov 2021 19:49:35 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/11/Featured-Orange.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Ever since the outbreak of COVID-19 in December 2019, researchers in the field of artificial intelligence and machine learning have been trying to find better ways to diagnose the disease.</p>
<p>They've worked on developing algorithms that would detect the disease within a matter of seconds – and only by looking at chest X-rays and/or CT scan images. </p>
<p>Some of these techniques have proven to be extremely useful and accurate in diagnosing COVID-19 cases.</p>
<p>There are multiple approaches that use both machine and deep learning to detect and/or classify of the disease. And researches have proposed newly developed architectures along with transfer learning approaches. </p>
<p>In this article, we will look at a transfer learning approach that classifies COVID-19 cases using chest X-ray images. </p>
<p>The model we are going to use is one of the seven variants of the EfficientNet architecture. We will use a pre-trained model on the immense ImageNet dataset. EfficientNet is an advanced and complex convolutional neural network-based architecture. </p>
<p>We will further investigate the details of Convolutional Neural Networks, pre-trained models, and EfficientNet during the course of this article. I've divided it into five parts:</p>
<ol>
<li>What are convolutional neural networks?</li>
<li>A dive into transfer learning.</li>
<li>What is EfficientNet?</li>
<li>An introduction to PyTorch.</li>
<li>Implementation of COVID-19 classifier using EfficientNet with PyTorch.</li>
</ol>
<p>This tutorial assumes that you have prior knowledge of both machine learning and deep learning. If you want to further develop your foundation in these topics, check out this article on <a target="_blank" href="https://livecodestream.dev/post/artificial-intelligence-vs-machine-learning-vs-deep-learning/">Artificial Intelligence vs Machine Learning vs Deep Learning</a>.</p>
<p>Also, although the dataset we'll work with here is COVID-related, you can apply the actual code implementation and analysis to other datasets.</p>
<h2 id="heading-what-is-a-convolutional-neural-network">What is a Convolutional Neural Network?</h2>
<p>Convolutional Neural networks (CNNs) are a type of deep neural network that works on visual data – this is, images. A CNN takes an image as an input and performs two or three-dimensional convolutional operations on the image with several filters, also referred to as kernels. </p>
<p>These convolution operations output a 2D or 3D matrix which contains the learnable weights and biases regarding the spatial information of the input image. This output matrix is referred to as the feature map of the image.</p>
<p>Processing a convolutional neural network in the training process can be, in some cases, extremely slow. This is why it's a good idea to use GPUs and TPUs during training for deep learning techniques, especially convolutional neural networks.</p>
<p>Convolutional neural networks learn spatial and temporal information about the image far better than the basic feed forward neural network. Also, CNNs can reduce the size of the image while retaining the most important information in the image, which is crucial for predictive analysis of images.</p>
<p><img src="https://lh6.googleusercontent.com/vma10ZOrxzyEEbJVvIZuygeDyqlkAKEUxWkJ8of7spwvrA9zktP1FYJQWZC6ZhMqrP2V0gMh04nqb74gNGNM3eO_g1ZwuvI753j-oS7fN_E0Txn4T3TXTW65MG3ubi67pBcX19o" alt="Deep Learning – Introduction to Convolutional Neural Networks - Vinod  Sharma's Blog" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://i0.wp.com/vinodsblog.com/wp-content/uploads/2018/10/CNN-2.png?resize=1300%2C479&amp;ssl=1">Source</a></em></p>
<p>The starting layers of convolutional neural networks learn the abstract and simpler features in an image, such as lines and edges. But as we move deeper into the network, the feature map turns to the more complex structures in the image. </p>
<p>It starts to learn the more specific features of the image, such as a cat, a dog, or a person, the same way we would, as humans, perceive the world around us. This is a core concept in modern deep learning-based computer vision. </p>
<p>Now before we move on to advanced concepts, it is important to learn the basics of 2D convolution.</p>
<h2 id="heading-what-is-2d-convolution">What is 2D Convolution?</h2>
<p>2D convolution is a bit complex to explain, but here it goes: if the convolutional process (which is extensively used in <a target="_blank" href="https://www.tutorialspoint.com/signals_and_systems/convolution_and_correlation.htm">h1-D signal processing</a>) is performed between two signals – but not just along a single dimension, rather along two mutually perpendicular dimensions – it is called 2D convolution. </p>
<p>In the case of images, the two mutually perpendicular dimensions are the rows and columns of a greyscale image. The convolutional operation is mathematically done by multiplying and then accumulating the values of the overlapping samples of the two input signals, where one of the signals is flipped. The output of this multiplication and accumulation gives a single point on the feature map.</p>
<p>In the case of CNNs, the image is one signal and the filter/kernel is the second signal which is flipped. The size of the kernel is always smaller than that of the image. </p>
<p>The flipped kernel is then swept across the whole image both row by row and column by column to output the feature map.</p>
<p><img src="https://lh3.googleusercontent.com/p5ht8HdKUxxCwcNoas2qAusdT8dYq_XzLS2YqVORYqb0cCnXPPAlPu40Z73kVEXerQ5s6epDozQdYRsleeUncnSV4Opx2Q1CNk8wseTdXEPz8eHt5dJ0R2TSFnnhRRZzjO7xH4A" alt="https://miro.medium.com/max/700/1*kOThnLR8Fge_AJcHrkR3dg.gif" width="600" height="400" loading="lazy">
<em>2d convolution</em></p>
<p>Here a 3x3 kernel is swept across a 6x6 image to output a 4x4 feature map. As you can see, the dimensions of the output feature map are smaller than the input image. So there are a few concepts used in convolution to control the dimensions of the output feature map. These include padding, stride, and kernel size.</p>
<p><strong>Padding</strong> is the manual addition of rows and columns around the input to keep the output dimension the same as the input dimension or vary it. </p>
<p><strong>Stride</strong> refers to the jump the kernel takes during the sweep, both in columns and rows. In the example above, the stride of the convolution is 1 as the kernel is moving one unit in both rows and columns. </p>
<p><strong>Kernel size</strong> refers to the dimensions of the kernel used. Changing the dimensions of the kernel to be swept changes the output size of the feature map. </p>
<p>The image below describes the convolution with the same kernel size but with a padding of 1 and stride of 2.</p>
<p><img src="https://lh3.googleusercontent.com/ceNWhzTPHzqGi5wMyUrqCSS2kp6-mF75BHxlNaEnGVwrsIiGamEq4pm_Mndmaz0weJnZfgOnl7L0CPy1OF19lRyRTAkDWZEzREBr8H36_mW_6bqJ-P8XzuJqTbzwNvPKXd_7N9U" alt="https://miro.medium.com/max/395/1*1VJDP6qDY9-ExTuQVEOlVg.gif" width="600" height="400" loading="lazy"></p>
<p>The equation that describes the relationship of stride, padding, and kernel size to input and output dimensions is as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/image-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The concept of 3D convolution is just an extension of 2D convolution where both the input image and the kernel are three-dimensional. </p>
<p>Like 2D convolution, we sweep the three-dimensional kernel across the whole image in two mutually perpendicular dimensions, namely the rows and the columns. </p>
<p>We do not usually sweep the kernel across the color channels because the kernel has the same third dimension, that is the channel length, as the original image. This gives an output feature map that is two-dimensional instead of three. </p>
<p>To learn more about the details of 3D convolution, you can read <a target="_blank" href="https://paperswithcode.com/method/3d-convolution">this article</a>.</p>
<h2 id="heading-what-is-transfer-learning">What is Transfer Learning?</h2>
<p>In transfer learning, you take a machine or deep learning model that is pre-trained on a previous dataset and use it to solve a different problem without needing to re-train the whole model. </p>
<p>Instead, you can just use the weights and biases of the pre-trained model to make a prediction. You transfer the weights from one model to your own model and adjust them to your own dataset without re-training all the previous layers of the architecture.</p>
<p>We use transfer learning in the applications of convolutional neural networks and natural language processing because it decreases the computation time and complexity of the training process. And, in many cases, it performs surprisingly well. </p>
<p>This also helps in cases where we have limited data available – since neural networks demand an extremely large amount of data to achieve good performance.</p>
<p>This means that using transfer learning methods can greatly reduce the demand for data since the weights and biases are pre-adjusted and are able to work better with just a small amount of data by tweaking the weights and biases a little.</p>
<p>But transfer learning models do not always give you great performance (although the newer architectures perform efficiently on almost every problem). Still, sometimes the problem at hand needs an architecture that is pre-trained on data that's similar to what you have. This factor depends upon the complexity of the problem you are trying to solve. </p>
<p>There are a couple ways you can perform transfer learning:</p>
<ol>
<li><strong>Using a pre-trained model.</strong></li>
<li><strong>Developing a new model.</strong></li>
</ol>
<p>You can use a pre-trained model in two ways. First, you can use the pre-trained weights and biases as initial parameters for your own model, and then train a whole convolutional model using those weights. </p>
<p>The other way is to perform feature extraction from the pre-trained model. You use the parameters of the pre-trained model to extract features from your input image and just train a simple classifier on top of it.</p>
<p>Another option is that if you have a problem with a small amount of data, you develop another model for a similar problem that has a large amount of data and train the model. Then you can use the trained weights from the new model to solve the original problem with less data. </p>
<p>In this tutorial, we will be using a pre-trained model as a feature extractor and we'll train a simple classifier on top of it to output the prediction.</p>
<p>There are many well-known architectures in the field of deep learning that are nowadays used for the purpose of transfer learning. Almost all of these are trained on the ImageNet dataset which is the largest open-source dataset available. It contains around 1000 classes and has around fifteen million instances. </p>
<p>Among these pre-trained architectures, LeNet is the first one that was proposed in 1998. Other well-known models include VGG, ResNet, AlexNet, GoogleNet, Inception, and Xception. </p>
<p>EfficientNet is also part of the series that was proposed recently, in 2019.</p>
<h2 id="heading-what-is-efficientnet">What is EfficientNet?</h2>
<p>EfficientNet (or perhaps it's better to say EfficientNets) is a family of convolutional neural network-based image classification models. They perform extremely well on the state-of-the-art ImageNet dataset and other popular datasets such as CIFAR-100 and Flowers. </p>
<p>In addition to performing so well, the architecture is small and computes faster than any of the previous models. The architecture has variants ranging from EfficientNet-B0 up to EffieicntNet-B7.</p>
<p>The variants ranging from B0 to B7 are based on the compound scaling method to scale up the baseline in B0 to obtain B1 to B7. EfficientNet-B7 acquired a Top-1 accuracy of 84.4% on the ImageNet dataset, which is the highest level of Top-1 accuracy ever achieved on ImageNet. </p>
<p>If you want to learn more about how EfficientNets work, you can read this paper ‘<a target="_blank" href="https://arxiv.org/abs/1905.11946v5">Efficientnet: Rethinking Model Scaling for Convolutional Neural Networks.</a>’</p>
<p><img src="https://lh3.googleusercontent.com/FvX6r1u1vR9kfoSb7tJbQ5I7aDgGQNhZCtU_OTGkHpOLTX3ZZnc-zIc-AO1MLaE-eLCsyfaj_grRXAJapYb9pJqhbzwH5R0qcXAxGUWIsHqm9zvDy6h4EQB63GOwaFZP1fV43mk" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet">Source</a></em></p>
<p>In the coding tutorial further along in this article, we'll be using the EfficientNet-B0 as a feature extractor and a classifier on top of it to classify COVID-19 using chest x-ray images.</p>
<h2 id="heading-an-introduction-to-pytorch">An Introduction to PyTorch</h2>
<p>PyTorch is a Python-supported library that helps us build deep learning models. Unlike Keras (another deep learning library), PyTorch is flexible and gives the developer more control. </p>
<p>It is similar to NumPy in processing but has a faster GPU acceleration. To learn more about NumPy and its features, you can check out <a target="_blank" href="https://www.freecodecamp.org/news/the-ultimate-guide-to-the-numpy-scientific-computing-library-for-python/">this in-depth guide</a> along with its <a target="_blank" href="https://numpy.org/doc/stable/user/whatisnumpy.html">documentation</a>.</p>
<p>PyTorch has a data structure known as a ‘Tensor’ that is similar to the NumPy ndarray but it has the option to operate on GPU. </p>
<p>PyTorch provides an uncomplicated way to switch computation between a CPU and a GPU. It also supports processing on NumPy arrays by simply providing a built-in module that can convert NumPy arrays into Tensors and vice versa.</p>
<p>One of the handiest modules in PyTorch is <code>grad()</code>. It allows you to compute the gradient of a tensor as it goes forward into processing without needing to manually compute the gradient and store it. </p>
<p>This gives you greater control of your deep learning operations, specifically back propagation, during the training process. This is helpful when computing the loss function which lets you adjust the parameters of a model. </p>
<p>We can also limit a tensor so that its gradient is not computed during the entire process by making the module's <code>requires_grad</code> equal <code>False</code>. To learn more about tensors and how to perform gradient computations in PyTorch, you can <a target="_blank" href="https://www.freecodecamp.org/news/pytorch-tensor-methods/">check out this tutorial</a> and <a target="_blank" href="https://www.freecodecamp.org/news/pytorch-full-course/">this course</a>.</p>
<h2 id="heading-how-to-implement-a-covid-19-classifier-using-efficientnet-with-pytorch">How to Implement a COVID-19 Classifier using EfficientNet with PyTorch</h2>
<p>Now let's move on to the practical implementation of EfficientNet in PyTorch. We will use the B0 variant of the EfficientNet family.</p>
<p>First, we'll examine the data and preprocess it. <a target="_blank" href="https://www.kaggle.com">Kaggle</a> has an vast library of datasets available for open-source use in projects and research. There are no limits as to what dataset can be used for this project. You can use any dataset containing chest X-ray images of COVID-19 patients and people without COVID. </p>
<p>For the sake of this tutorial, we'll use this dataset <a target="_blank" href="https://www.kaggle.com/asraf047/covid19-pneumonia-normal-chest-xray-pa-dataset">here</a>. But for the code to work on your custom dataset, you must divide your data into three directories: train, test, and valid. </p>
<p>Each directory should contain two more directories with the labels <code>covid</code> and <code>norma</code>l. These covid and normal folders will contain the images corresponding to the specific class of the directory they are present in.</p>
<p><img src="https://lh5.googleusercontent.com/aaZIPn8TEUsfqo3rA7xtJf7T-3PMSRU_jSZZ60DCeloIyadr40u1oguQycDMDeL-puqjdZ40xEGIu8i_PYdpufi_o-8pcGTlarJ37A_KJm_R0lV4mwGFKPAIhQmKd3Lr7b6dNHM" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The original dataset we'll use in this article contains three folders: covid, normal, and pneumonia. We discard the pneumonia folder completely and divide the other data in the same way described above. </p>
<p>We do this to create a logical division between the data used for training and the data used for testing and validation. Also, PyTorch, by default, takes the name of the folder, an instance it is present in, as the label of the class – so we do not have a label file corresponding to the input dataset.</p>
<h3 id="heading-the-data-and-the-architecture">The data and the architecture</h3>
<p>Let's have a look at the data. Below we can see the x-ray images of patients with COVID-19:</p>
<p><img src="https://lh4.googleusercontent.com/cB8kT-qcFsIqly9wi2yHiDZpD3of9wOgr7j9XggMWC0Yehva5H1QHiGmLq1g-qIz5wyk_6Kdy_roJiyTxUNFtPmGr6-0BKLy5KscJesZddQUGpKSDn8ZH5cRqDTWeSXswCxH8W8" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And here we can see the normal category’s x-ray images:</p>
<p><img src="https://lh4.googleusercontent.com/CRu82skVkh6fIaLuSD5ucOyjhjCk9o_j6ZO0zQLw8J4_UKk5nSJhxfiEtdwhmSCFVakoG0RLSwr6IL7b-ij30thBD_S6WYumx6XUYLSMkPdHfjvxzAfuwF_MaoUG89VmFGXUa9Y" alt="Image" width="600" height="400" loading="lazy"></p>
<p>There are 237 total layers in the B-0 architecture. The whole architecture can be condensed into the following diagrams. We provide the x-ray data to the input layer.</p>
<p><img src="https://lh3.googleusercontent.com/de9n3HWqb4kqVLV4VkPiCphCbfSDDSmKFXu826ITg1Z-LkWaB28JCkzfVlHaOVSrBHbSToDe5k45-bSGwUpQLglgoa4ai_YhhYAe9_th6pJIKts64kzbhgNS3GihARgRscJABlw" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://lh5.googleusercontent.com/rCTjM83oPyAi-RddlHJufeDAql0ee_ExJmxqTbL7BgPk6unoZXmL5cabb0zuDrM7EBdDupxE1YXOmRCQt5Ntyn2gZYpzdEDb7kI0ea3BifBZp3q1MBYkVzxV9N4Mwd-882ciO7o" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://lh4.googleusercontent.com/sZ34-xflacMLYBg33trm8RxJypHPxRqAHWtt_dm8fEdwhW1eFV0eEL66g8Yr8GcX8mo_6Sz4N6PkL7M_UbhG7S5n1eU5dpyrKZoJL7ROQ8TQLJjh_Nm4vokmtwi-4pOfCMzFHRk" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://towardsdatascience.com/complete-architectural-details-of-all-efficientnet-models-5fd5b736142">Source</a></em></p>
<p>We will freeze the learning of the weights across all these blocks as we will be using the pre-trained weights to extract the features from our own input. </p>
<p>We'll do the feature extraction after the input passes Module 7. We then transfer the feature map obtained from Module 7 to our own final classification layers (this is why it's called transfer learning). We top the architecture with the following top layers:</p>
<ul>
<li>BatchNorm1d</li>
<li>Linear(output neurons = 512)</li>
<li>ReLU()</li>
<li>BatchNorm1d()</li>
<li>Linear(output neurons = 128)</li>
<li>ReLU()</li>
<li>BatchNorm1d()</li>
<li>Dropout(probability of zeroing the parameters = 0.4)</li>
<li>Linear(output neurons = 2)</li>
</ul>
<h3 id="heading-lets-head-over-to-the-code">Let's head over to the code</h3>
<p>Now before we start the code, there are a couple of dependencies we need to install. First, you'll need to install PyTorch on your local machine. You can do this using the pip install command in your Python environment. Refer <a target="_blank" href="https://pytorch.org/get-started/locally/">here</a> to install it depending on your machine (whether it has GPU available or not).</p>
<p>Before you move on to the code, I strongly recommend that you actually work through the code yourself. This makes it much easier to understand. With that said, you can access the full code in a Jupyter notebook <a target="_blank" href="https://drive.google.com/file/d/1m_ATQIrNN-dVVZwZjux5305yhuseZ58R/view?usp=sharing">here</a>.</p>
<p>You also need to install Efficientnet support for PyTorch into the same Python environment. Run the command below to install it:</p>
<pre><code class="lang-bash">pip install efficientnet_pytorch
</code></pre>
<p>Apart from this you will need to import some other dependencies at the start of the code.</p>
<p>Now we start building the classification model. To start, we import all the necessary modules:</p>
<pre><code class="lang-python"><span class="hljs-comment">#importing required modules</span>
<span class="hljs-keyword">import</span> gdown
<span class="hljs-keyword">import</span> zipfile
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">from</span> glob <span class="hljs-keyword">import</span> glob
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">import</span> torch.nn <span class="hljs-keyword">as</span> nn
<span class="hljs-keyword">from</span> torchsummary <span class="hljs-keyword">import</span> summary
<span class="hljs-keyword">from</span> torchvision <span class="hljs-keyword">import</span> datasets, transforms <span class="hljs-keyword">as</span> T
<span class="hljs-keyword">from</span> efficientnet_pytorch <span class="hljs-keyword">import</span> EfficientNet
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> torch.optim <span class="hljs-keyword">as</span> optim
<span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> ImageFile
<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> accuracy_score
</code></pre>
<p>All these modules are essential to perform multiple functions across the model. You can install all the absent modules using the pip command. </p>
<p>Then we download and extract the data we prepared for the model:</p>
<pre><code class="lang-python"><span class="hljs-comment">#importing data</span>
<span class="hljs-comment">#Dataset address</span>
url = <span class="hljs-string">'https://drive.google.com/uc?export=download&amp;id=1B75cOYH7VCaiqdeQYvMuUuy_Mn_5tPMY'</span>
output = <span class="hljs-string">'data.zip'</span>
gdown.download(url, output, quiet=<span class="hljs-literal">False</span>)
<span class="hljs-comment">#giving zip file name</span>
data_dir=<span class="hljs-string">'./data.zip'</span>
<span class="hljs-comment">#Extracting data from zip file</span>
<span class="hljs-keyword">with</span> zipfile.ZipFile(data_dir, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> zf:
zf.extractall(<span class="hljs-string">'./data/'</span>)
</code></pre>
<p>The <code>gdown.download</code> module downloads the data from the URL provided and the zipfile.extractall extracts the data into the same directory where you currently are (or the same runtime if you are working on Google Colab). </p>
<p>I highly recommend working on Google Colab for this project in case you do not locally have a GPU available. </p>
<p>Next, create a check variable to check the availability of a GPU.</p>
<pre><code class="lang-python"><span class="hljs-comment">#Checking the availability of a GPU</span>
use_cuda = torch.cuda.is_available()
</code></pre>
<p>This module returns ‘True’ if GPU is available and ‘False' if not.</p>
<p>Next, we need to apply pre-processing techniques to the data. Since our data is pre-augmented, we do not need to apply many pre-processing techniques to it. We only resize all the images to a single size of (224,224). We do this because the images in our dataset are all of different dimensions and we need a consistent dimension for the model. </p>
<p>We'll also convert the images to tensors to be processed by PyTorch and then we normalize all the images. This normalize function normalizes all the images with a mean and standard deviation of 0.5. </p>
<p>After that, we create the locations for the train, test and validation sets which will be given as input to the ‘datasets’ module. We do this so that the PyTorch model knows exactly where the data is located and also so that that data can be loaded to the GPU. We keep a batch size of 32.</p>
<pre><code class="lang-python"><span class="hljs-comment">#declaring batch size</span>
batch_size = <span class="hljs-number">32</span>

<span class="hljs-comment">#applying required transformations on the dataset</span>
img_transforms = {
    <span class="hljs-string">'train'</span>:
    T.Compose([
        T.Resize(size=(<span class="hljs-number">224</span>,<span class="hljs-number">224</span>)), 
        T.ToTensor(),
        T.Normalize([<span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>], [<span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>]), 
        ]),

    <span class="hljs-string">'valid'</span>:
    T.Compose([
        T.Resize(size=(<span class="hljs-number">224</span>,<span class="hljs-number">224</span>)),
        T.ToTensor(),
        T.Normalize([<span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>], [<span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>])
        ]),

    <span class="hljs-string">'test'</span>:
    T.Compose([
        T.Resize(size=(<span class="hljs-number">224</span>,<span class="hljs-number">224</span>)),
        T.ToTensor(),
        T.Normalize([<span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>], [<span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>, <span class="hljs-number">0.5</span>])
        ]),
     }

<span class="hljs-comment"># creating Location of data: train, validation, test</span>
data=<span class="hljs-string">'./data/'</span>

train_path=os.path.join(data,<span class="hljs-string">'train'</span>)
valid_path=os.path.join(data,<span class="hljs-string">'test'</span>)
test_path=os.path.join(data,<span class="hljs-string">'valid'</span>)


<span class="hljs-comment"># creating Datasets to each of  folder created in prev</span>
train_file=datasets.ImageFolder(train_path,transform=img_transforms[<span class="hljs-string">'train'</span>])
valid_file=datasets.ImageFolder(valid_path,transform=img_transforms[<span class="hljs-string">'valid'</span>])
test_file=datasets.ImageFolder(test_path,transform=img_transforms[<span class="hljs-string">'test'</span>])


<span class="hljs-comment">#Creating loaders for the dataset</span>
loaders_transfer={
    <span class="hljs-string">'train'</span>:torch.utils.data.DataLoader(train_file,batch_size,shuffle=<span class="hljs-literal">True</span>),
    <span class="hljs-string">'valid'</span>:torch.utils.data.DataLoader(valid_file,batch_size,shuffle=<span class="hljs-literal">True</span>),
    <span class="hljs-string">'test'</span>: torch.utils.data.DataLoader(test_file,batch_size,shuffle=<span class="hljs-literal">True</span>)
}
</code></pre>
<p>After pre-processing, we move on to building the model.</p>
<pre><code class="lang-python"><span class="hljs-comment">#importing the pretrained EfficientNet model</span>

model_transfer = EfficientNet.from_pretrained(<span class="hljs-string">'efficientnet-b0'</span>)

<span class="hljs-comment"># Freeze weights</span>
<span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> model_transfer.parameters():
    param.requires_grad = <span class="hljs-literal">False</span>
in_features = model_transfer._fc.in_features


<span class="hljs-comment"># Defining Dense top layers after the convolutional layers</span>
model_transfer._fc = nn.Sequential(
    nn.BatchNorm1d(num_features=in_features),    
    nn.Linear(in_features, <span class="hljs-number">512</span>),
    nn.ReLU(),
    nn.BatchNorm1d(<span class="hljs-number">512</span>),
    nn.Linear(<span class="hljs-number">512</span>, <span class="hljs-number">128</span>),
    nn.ReLU(),
    nn.BatchNorm1d(num_features=<span class="hljs-number">128</span>),
    nn.Dropout(<span class="hljs-number">0.4</span>),
    nn.Linear(<span class="hljs-number">128</span>, <span class="hljs-number">2</span>),
    )
<span class="hljs-keyword">if</span> use_cuda:
    model_transfer = model_transfer.cuda()
</code></pre>
<p>First, we import the EfficientNet-B0 model with its pre-trained weights. Next, we disable the training of the parameters of the model because we are going to use the pre-trained parameters to extract features from our data. </p>
<p>Then we replace the top fully connected layers of the model with our own classifier. </p>
<p>Batchnorm normalizes the whole batch of data into the number of neurons given as an argument. This reduces the complexity of the model and prevents it from overfitting. Dropout does something similar – it zeroes out some neurons in the model with a probability of the value given as an argument. </p>
<p>The Linear layer is a simple fully-connected neural network layer. </p>
<p>Finally, we transfer our model to the GPU, if available.</p>
<pre><code class="lang-python"><span class="hljs-comment"># selecting loss function</span>
criterion_transfer = nn.CrossEntropyLoss()

<span class="hljs-comment">#using Adam classifier</span>
optimizer_transfer = optim.Adam(model_transfer.parameters(), lr=<span class="hljs-number">0.0005</span>)
</code></pre>
<p>Here, we select the loss function and the optimizer for our training phase. We also define the value of the learning rate for the optimizer. You can change this value to see how different learning rates influence the model in different ways. </p>
<p>Next, we move on to the training of the model.</p>
<pre><code class="lang-python">ImageFile.LOAD_TRUNCATED_IMAGES = <span class="hljs-literal">True</span>

<span class="hljs-comment"># Creating the function for training</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">train</span>(<span class="hljs-params">n_epochs, loaders, model, optimizer, criterion, use_cuda, save_path</span>):</span>
    <span class="hljs-string">"""returns trained model"""</span>
    <span class="hljs-comment"># initialize tracker for minimum validation loss</span>
    valid_loss_min = np.Inf 
    trainingloss = []
    validationloss = []

    <span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, n_epochs+<span class="hljs-number">1</span>):
        <span class="hljs-comment"># initialize the variables to monitor training and validation loss</span>
        train_loss = <span class="hljs-number">0.0</span>
        valid_loss = <span class="hljs-number">0.0</span>

        <span class="hljs-comment">###################</span>
        <span class="hljs-comment"># training the model #</span>
        <span class="hljs-comment">###################</span>
        model.train()
        <span class="hljs-keyword">for</span> batch_idx, (data, target) <span class="hljs-keyword">in</span> enumerate(loaders[<span class="hljs-string">'train'</span>]):
            <span class="hljs-comment"># move to GPU</span>
            <span class="hljs-keyword">if</span> use_cuda:
                data, target = data.cuda(), target.cuda()

            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()

            train_loss = train_loss + ((<span class="hljs-number">1</span> / (batch_idx + <span class="hljs-number">1</span>)) * (loss.data - train_loss))

        <span class="hljs-comment">######################    </span>
        <span class="hljs-comment"># validating the model #</span>
        <span class="hljs-comment">######################</span>
        model.eval()
        <span class="hljs-keyword">for</span> batch_idx, (data, target) <span class="hljs-keyword">in</span> enumerate(loaders[<span class="hljs-string">'valid'</span>]):
            <span class="hljs-keyword">if</span> use_cuda:
                data, target = data.cuda(), target.cuda()

            output = model(data)
            loss = criterion(output, target)
            valid_loss = valid_loss + ((<span class="hljs-number">1</span> / (batch_idx + <span class="hljs-number">1</span>)) * (loss.data - valid_loss))

        train_loss = train_loss/len(train_file)
        valid_loss = valid_loss/len(valid_file)

        trainingloss.append(train_loss)
        validationloss.append(valid_loss)

        <span class="hljs-comment"># printing training/validation statistics </span>
        print(<span class="hljs-string">'Epoch: {} \tTraining Loss: {:.6f} \tValidation Loss: {:.6f}'</span>.format(
            epoch, 
            train_loss,
            valid_loss
            ))

        <span class="hljs-comment">## saving the model if validation loss has decreased</span>
        <span class="hljs-keyword">if</span> valid_loss &lt; valid_loss_min:
            torch.save(model.state_dict(), save_path)

            valid_loss_min = valid_loss

    <span class="hljs-comment"># return trained model</span>
    <span class="hljs-keyword">return</span> model, trainingloss, validationloss
</code></pre>
<p>We create a function for the training and validation phase of the model. We allow the model to accept truncated images also with fewer than three channels. We initialize the values of the train and validation losses and start the training loop. We import the data batch by batch from the data loaders and perform the training operations. </p>
<p>After the training loop, we start the validation loop where we only compute the loss and the output predictions and do not update the parameters as we did in the training loop. We save the model which has the minimum loss for the validation set.</p>
<pre><code class="lang-python"><span class="hljs-comment"># training the model</span>

n_epochs=<span class="hljs-number">10</span>

model_transfer, train_loss, valid_loss = train(n_epochs, loaders_transfer, model_transfer, optimizer_transfer, criterion_transfer, use_cuda, <span class="hljs-string">'model.pt'</span>)
</code></pre>
<p>We run the model for 10 epochs, that is 10 loops. You can change the number of epochs and test out the loss values. The saved model is saved under the name <code>model.pt</code>. Now we load the model and move on to the testing phase.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Defining the test function</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test</span>(<span class="hljs-params">loaders, model, criterion, use_cuda</span>):</span>

    <span class="hljs-comment"># monitoring test loss and accuracy</span>
    test_loss = <span class="hljs-number">0.</span>
    correct = <span class="hljs-number">0.</span>
    total = <span class="hljs-number">0.</span>
    preds = []
    targets = []

    model.eval()
    <span class="hljs-keyword">for</span> batch_idx, (data, target) <span class="hljs-keyword">in</span> enumerate(loaders[<span class="hljs-string">'test'</span>]):
        <span class="hljs-comment"># moving to GPU</span>
        <span class="hljs-keyword">if</span> use_cuda:
            data, target = data.cuda(), target.cuda()
        <span class="hljs-comment"># forward pass</span>
        output = model(data)
        <span class="hljs-comment"># calculate the loss</span>
        loss = criterion(output, target)
        <span class="hljs-comment"># updating average test loss </span>
        test_loss = test_loss + ((<span class="hljs-number">1</span> / (batch_idx + <span class="hljs-number">1</span>)) * (loss.data - test_loss))
        <span class="hljs-comment"># converting the output probabilities to predicted class</span>
        pred = output.data.max(<span class="hljs-number">1</span>, keepdim=<span class="hljs-literal">True</span>)[<span class="hljs-number">1</span>]
        preds.append(pred)
        targets.append(target)
        <span class="hljs-comment"># compare predictions</span>
        correct += np.sum(np.squeeze(pred.eq(target.data.view_as(pred))).cpu().numpy())
        total += data.size(<span class="hljs-number">0</span>)

    <span class="hljs-keyword">return</span> preds, targets

<span class="hljs-comment"># calling test function</span>
preds, targets = test(loaders_transfer, model_transfer, criterion_transfer, use_cuda)
</code></pre>
<p>We now create a test function to apply our model to our test dataset and evaluate its performance. </p>
<p>We pass the dataset batch by batch as we did in the train and testing phase, but we only do it once here instead of 10 epochs. This is because we just have to test the model and not update the parameters. </p>
<p>The function returns the predictions it computed for the input test set and also the original target values of the test set. </p>
<p>Now we compute the accuracy of the model. First, we need to convert the tensors, that is predictions and targets, into NumPy arrays. We do this by first moving them from the GPU to the CPU and then converting them to NumPy arrays. The following code does this: </p>
<pre><code class="lang-python"><span class="hljs-comment">#converting the tensor object to a list for metric functions</span>

preds2, targets2 = [],[]

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> preds:
  <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(len(i)):
    preds2.append(i.cpu().numpy()[j])
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> targets:
  <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(len(i)):
    targets2.append(i.cpu().numpy()[j])
</code></pre>
<p>Now we compute the accuracy using the accuracy metric of the sklearn library.</p>
<pre><code class="lang-python"><span class="hljs-comment">#Computing the accuracy</span>
acc = accuracy_score(targets2, preds2)
print(<span class="hljs-string">"Accuracy: "</span>, acc)
</code></pre>
<p>Our model had an accuracy of 95.45%.</p>
<p><img src="https://lh3.googleusercontent.com/4_gMnxj_l_xGKOPr0Zg5V8IIA78NJIloxe9FNsKwAAW480WUpojW6PQWWgYzT7k839c27hA7svWPi4m_8XuR0ZSWY6TJ0TIc22xtCqqixeSq9mVBZzDIHW0edaueH1IE3VRW68M" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The next image is the confusion matrix for the test run of the classifier. In it, you can see the visual of the model’s performance. The actual labels indicate whether the person had COVID or not, while the predicted labels indicate how our model classified the images. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/confusion-matrix.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As we can see, our model predicted most of the labels correctly. The small portion of wrongly predicted labels include 7 people who did not have COVID, but our model predicted they did. This is not too alarming. </p>
<p>On the other hand, there were 14 examples where our model predicted that they did not have COVID, but they did. In machine learning, these are called false negatives. This is a very alarming situation because we would've sent home people suffering from COVID-19. This would increase their risk that the disease would get worse. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Convolutional neural networks have proved extremely useful in computer vision techniques, and we can also use them efficiently in medical imaging and diagnosis.</p>
<p>Transfer learning is an effective method for using pre-trained architectures to perform efficiently in other applications. </p>
<p>But as we saw above, using these models depends upon what kind of problem we have and what our objectives are. Just like in the detection of COVID-19, we would prefer to have a model that gives us 0 false negatives. But there's still great potential for deep learning to be useful in COVID diagnosis as well as other medical diagnosis techniques.</p>
<p>Thanks for reading! If you enjoyed the article and would like to read more interesting articles around computer science, Python and JavaScript, please follow me on <a target="_blank" href="https://twitter.com/bajcmartinez">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
