<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joyce Foster</title>
    <description>The latest articles on DEV Community by Joyce Foster (@joycefosterr).</description>
    <link>https://dev.to/joycefosterr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4071196%2F7529a0a0-2e89-42bc-a4f0-c952aaba0ecf.jpeg</url>
      <title>DEV Community: Joyce Foster</title>
      <link>https://dev.to/joycefosterr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joycefosterr"/>
    <language>en</language>
    <item>
      <title>How to Use the OpenWeatherMap API — A Practical Guide.</title>
      <dc:creator>Joyce Foster</dc:creator>
      <pubDate>Fri, 11 Sep 2026 13:12:20 +0000</pubDate>
      <link>https://dev.to/joycefosterr/how-to-use-the-openweathermap-api-a-practical-guide-57i2</link>
      <guid>https://dev.to/joycefosterr/how-to-use-the-openweathermap-api-a-practical-guide-57i2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The OpenWeatherMap API provides current weather data for any location in the world, including temperature, humidity, wind speed, and general conditions (e.g., clear skies, clouds, rain). Data is returned in JSON format and can be requested by city name or geographic coordinates. This guide covers how to authenticate, make a request, and handle both successful responses and errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This API requires a free API key to make requests. Without a valid key, all requests will return an error.&lt;/p&gt;

&lt;p&gt;How to get your API key:&lt;br&gt;
1.) Sign up for a free account at &lt;a href="https://home.openweathermap.org/users/sign_up" rel="noopener noreferrer"&gt;https://home.openweathermap.org/users/sign_up&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.)Verify your email address via the confirmation link sent to your inbox.&lt;/p&gt;

&lt;p&gt;3.)Log in and navigate to the API keys tab in your account.&lt;/p&gt;

&lt;p&gt;4.)Copy your default key (or generate a new one).&lt;/p&gt;

&lt;p&gt;Note: New API keys can take up to 2 hours to activate. If you receive an "Invalid API key" error immediately after signing up, this is expected — simply wait and try again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using your key:&lt;/strong&gt;&lt;br&gt;
Your API key must be included in every request as a query parameter called appid. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://api.openweathermap.org/data/2.5/weather?q=Lagos&amp;amp;appid=YOUR_API_KEY" rel="noopener noreferrer"&gt;https://api.openweathermap.org/data/2.5/weather?q=Lagos&amp;amp;appid=YOUR_API_KEY&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Base URL &amp;amp; Endpoint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All requests to the current weather data endpoint use this base URL:&lt;br&gt;
&lt;a href="https://api.openweathermap.org/data/2.5/weather" rel="noopener noreferrer"&gt;https://api.openweathermap.org/data/2.5/weather&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You send a GET request to this URL, along with the parameters below, to retrieve current weather data for a location.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Required?&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;q&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;City name (e.g., Lagos, London). Can also include country code (e.g., Lagos,NG) for more precise results.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;appid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Required&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Your unique API key, used to authenticate the request.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;units&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Sets the unit format for temperature. Options: standard (Kelvin, default if omitted), metric (Celsius), imperial (Fahrenheit).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example Requests &amp;amp; Responses&lt;/strong&gt;&lt;br&gt;
1.) Basic request (default units — Kelvin)&lt;br&gt;
Request:&lt;br&gt;
&lt;a href="https://api.openweathermap.org/data/2.5/weather?q=Lagos&amp;amp;appid=YOUR_API_KEY" rel="noopener noreferrer"&gt;https://api.openweathermap.org/data/2.5/weather?q=Lagos&amp;amp;appid=YOUR_API_KEY&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "coord": {"lon": 3.75, "lat": 6.5833},&lt;br&gt;
  "weather": [{"main": "Clouds", "description": "overcast clouds"}],&lt;br&gt;
  "main": {&lt;br&gt;
    "temp": 302.18,&lt;br&gt;
    "feels_like": 305.94,&lt;br&gt;
    "humidity": 70&lt;br&gt;
  },&lt;br&gt;
  "wind": {"speed": 4.15},&lt;br&gt;
  "sys": {"country": "NG"},&lt;br&gt;
  "name": "Lagos",&lt;br&gt;
  "cod": 200&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Note: temperature is returned in Kelvin since no units parameter was set.&lt;/p&gt;

&lt;p&gt;2.) Request with metric units&lt;br&gt;
Request:&lt;br&gt;
&lt;a href="https://api.openweathermap.org/data/2.5/weather?q=Lagos&amp;amp;appid=YOUR_API_KEY&amp;amp;units=metric" rel="noopener noreferrer"&gt;https://api.openweathermap.org/data/2.5/weather?q=Lagos&amp;amp;appid=YOUR_API_KEY&amp;amp;units=metric&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Response (partial):&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "main": {&lt;br&gt;
    "temp": 29.03,&lt;br&gt;
    "feels_like": 32.79,&lt;br&gt;
    "humidity": 70&lt;br&gt;
  },&lt;br&gt;
  "name": "Lagos"&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Same location, now readable in Celsius.&lt;/p&gt;

&lt;p&gt;3.) Request for a different city&lt;br&gt;
Request:&lt;br&gt;
&lt;a href="https://api.openweathermap.org/data/2.5/weather?q=London&amp;amp;appid=YOUR_API_KEY&amp;amp;units=metric" rel="noopener noreferrer"&gt;https://api.openweathermap.org/data/2.5/weather?q=London&amp;amp;appid=YOUR_API_KEY&amp;amp;units=metric&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Response (partial):&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "weather": [{"main": "Clear", "description": "clear sky"}],&lt;br&gt;
  "main": {&lt;br&gt;
    "temp": 19.94,&lt;br&gt;
    "feels_like": 19.3,&lt;br&gt;
    "humidity": 50&lt;br&gt;
  },&lt;br&gt;
  "name": "London"&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Demonstrates the same endpoint working for any valid city name.&lt;/p&gt;

&lt;p&gt;4.) Error response — invalid city name&lt;br&gt;
Request:&lt;br&gt;
&lt;a href="https://api.openweathermap.org/data/2.5/weather?q=asdkjasnd&amp;amp;appid=YOUR_API_KEY" rel="noopener noreferrer"&gt;https://api.openweathermap.org/data/2.5/weather?q=asdkjasnd&amp;amp;appid=YOUR_API_KEY&lt;/a&gt;&lt;br&gt;
Response:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "cod": "404",&lt;br&gt;
  "message": "city not found"&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;401 Unauthorized&lt;/code&gt; — "Invalid API key"&lt;/td&gt;
&lt;td&gt;Your API key is incorrect, or was very recently generated and hasn't activated yet.&lt;/td&gt;
&lt;td&gt;Double-check your key for typos. If it was just generated, wait up to 2 hours and try again.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;404 Not Found&lt;/code&gt; — "city not found"&lt;/td&gt;
&lt;td&gt;The city name in the &lt;code&gt;q&lt;/code&gt; parameter is misspelled or doesn't exist.&lt;/td&gt;
&lt;td&gt;Check the spelling, or add a country code for precision (e.g., q=Lagos,NG).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;429 Too Many Requests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;You've exceeded your plan's rate limit (calls per minute/day).&lt;/td&gt;
&lt;td&gt;Wait before making more requests, or check your usage on your OpenWeatherMap dashboard.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Quick Start&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1.) Sign up for a free account at &lt;a href="https://home.openweathermap.org/users/sign_up" rel="noopener noreferrer"&gt;https://home.openweathermap.org/users/sign_up&lt;/a&gt; and verify your email.&lt;/p&gt;

&lt;p&gt;2.) Copy your API key from the API keys tab (allow up to 2 hours for it to activate).&lt;/p&gt;

&lt;p&gt;3.) Build a request using the base URL, your key, and a city name:&lt;br&gt;
&lt;a href="https://api.openweathermap.org/data/2.5/weather?q=YOUR_CITY&amp;amp;appid=YOUR_API_KEY&amp;amp;units=metric" rel="noopener noreferrer"&gt;https://api.openweathermap.org/data/2.5/weather?q=YOUR_CITY&amp;amp;appid=YOUR_API_KEY&amp;amp;units=metric&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4.) Paste the URL into your browser or an API tool (e.g., Postman).&lt;/p&gt;

&lt;p&gt;5.) You'll receive a JSON response with current weather data for that city.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This documentation covers everything needed to start making requests to the OpenWeatherMap current weather API — from generating an API key to handling common errors. All examples in this guide were tested directly against the live API to ensure accuracy.&lt;br&gt;
For more advanced use cases, such as extended forecasts or historical weather data, refer to OpenWeatherMap's official documentation at &lt;a href="https://openweathermap.org/api" rel="noopener noreferrer"&gt;https://openweathermap.org/api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>documentation</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>AWS IAM for Beginners: Understanding Users, Groups, Roles, and Policies.</title>
      <dc:creator>Joyce Foster</dc:creator>
      <pubDate>Mon, 07 Sep 2026 15:11:39 +0000</pubDate>
      <link>https://dev.to/joycefosterr/aws-iam-for-beginners-understanding-users-groups-roles-and-policies-4jbi</link>
      <guid>https://dev.to/joycefosterr/aws-iam-for-beginners-understanding-users-groups-roles-and-policies-4jbi</guid>
      <description>&lt;p&gt;&lt;strong&gt;INTRODUCTION&lt;br&gt;
Brief overview of AWS IAM.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;IAM, which stands for ‘Identity and  Access Management,’ is an essential feature of Amazon Web Services (AWS). It is the foundation upon which AWS infrastructure is built. With IAM, users and groups can be created, policies can be assigned through JSON, security can be enforced through multi-factor authentication(MFA), command-line interface(CLI) can be explored, and more. &lt;br&gt;
As I dug deeper into IAM, I discovered that it provides the mechanism needed for authentication and authorization. When a user creates an AWS account, they usually start out using the root account. As time progressed, I learnt that I would need to create an IAM user for everyday tasks because it provides better security and accountability. These users can eventually be organized into groups, with one user belonging to multiple groups at once.&lt;br&gt;
Generally, IAM provides an adequate structure to control access to your AWS resources and how it can be used. This structure manifests itself in the AWS community through key entities. Users represent individuals seeking access to AWS resources. Groups are typically made up of users and a user can belong to more than one group at a time.                        Roles are necessary to grant permission in the AWS environment, without the need to create a dedicated user.&lt;br&gt;
By providing a systematic method for AWS components to communicate, IAM improves operational efficiency while strengthening security and simplifying cloud management. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why IAM is important in cloud security.&lt;/strong&gt;&lt;br&gt;
The more I explored AWS, the clearer it became that IAM sits at the heart of cloud security rather than being just another feature to configure. Unlike traditional systems where physical access limits who can reach a server, cloud resources are reachable from anywhere with an internet connection. This means that without a strong access control system, anyone with the right credentials could potentially access critical resources, regardless of their location. IAM closes this gap by ensuring that every request to an AWS resource is first authenticated and then authorized, so that only the right people, or systems, get to perform the right actions. I came to see this as the difference between simply having a lock on the door and actually deciding who gets a key, when they can use it, and what rooms it opens.&lt;br&gt;
What really drove the importance of IAM home for me was realizing how much damage a single misconfigured permission could cause. A developer with more access than they need, or an application with unrestricted permissions, becomes a much bigger risk the moment their credentials are compromised. IAM addresses this through the principle of least privilege, which I learned means giving users and services only the permissions they need to do their specific job, nothing more. By combining this with tools like MFA, granular policies, and temporary role-based access, IAM allows me to reduce the attack surface significantly while still keeping the environment flexible enough for daily operations. In this sense, I began to understand IAM not just as an access tool but as a core layer of defense that shapes how secure an entire AWS environment can be. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHAT IS AWS IAM?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Definition and purpose&lt;/strong&gt;&lt;br&gt;
To me, IAM is a central system that oversees the basics of access in the cloud. It is the service provided by AWS to manage access to an account and the activities carried out therein. Fundamentally, IAM handles authentication, which confirms the identity of the user, and authorization, which allows for permissions granted afterward. When I first came across IAM, I realized it wasn't just a login system; it was more like a gatekeeper that decides both entry and movement within the AWS environment. &lt;br&gt;
The purpose of IAM became clearer to me once I understood that AWS accounts are not meant to be operated solely through the root user. IAM exists so that access can be distributed safely, and it allows various persons and applications to interact with AWS resources without complete or permanent control over the account. Through IAM, I'm able to create individual identities, assign specific permissions, and revoke or adjust access at any time, all without compromising the security of the environment. This made me appreciate IAM not as an optional add-on, but as the foundation that every other AWS service depends on to stay secure. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key benefits of IAM:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Centralized Access Control&lt;/strong&gt; — Essentially, IAM lets me manage all user and system access from one place, instead of having to configure permissions separately across every AWS service I use. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Granular Permissions&lt;/strong&gt; — Rather than giving broad access, IAM allows me to define exactly what each user, group, or role can do, right down to specific actions on specific resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced Security&lt;/strong&gt; — With features like MFA, I'm able to reduce the risk of unauthorized access and limit the damage a compromised account could cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt; — As my AWS environment grows, IAM makes it easy for me to add new users, adjust group memberships, or update policies without having to rebuild my entire access structure from scratch. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Components Of IAM&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;IAM Users&lt;/strong&gt;- An IAM user represents a single identity within an AWS account, which could be an actual person or an application that interacts with AWS resources. A user is granted unique credentials, consisting of a username and password for console access, or access keys for programmatic access through the CLI or SDKs. What stood out to me is that every user starts out with no permissions at all by default, so nothing is accessible until permissions are explicitly granted. Generally, the concept of IAM users taught me the importance of granting each person or application separate identities across a team. This way, I'm able to track exactly who did what within the account, and if one user's credentials are ever compromised, I can disable or delete that specific user without affecting anyone else. It also made me appreciate how IAM users form the base layer that groups and policies eventually build on top of. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IAM Groups&lt;/strong&gt;- An IAM group is simply a collection of IAM users that share a common set of permissions. Instead of assigning policies to each user individually, I can attach a policy to a group, and every user in that group automatically inherits those permissions. This became especially useful to me when thinking about teams within an organization, for example, grouping all developers together so they share the same access to development resources, while a separate group for administrators holds broader permissions. To me, the most valuable detail about IAM groups is how much easier they make managing permissions. I also grasped that a user isn’t limited to one group and can belong to multiple groups at once, which gives me more flexibility in combining different sets of permissions depending on what a person's role actually requires. This taught me that groups aren't just a convenience, they're a key part of keeping permission management organized as an environment grows. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IAM Roles&lt;/strong&gt;- IAM Roles has a different function from users and groups. They are synonymous with a temporary identity that can be assumed by whoever needs it at that moment, whether that's an IAM user, an application, or even another AWS service. It also gives users temporary security credentials that expire after a set period. This means I don't have to worry about long-term access keys sitting around and potentially getting exposed. I found roles particularly useful when an EC2 instance needs to talk to another AWS service, like S3, without hardcoding credentials into the application. I could easily attach a role to the instance and let it assume the permissions it needs, only for as long as it needs them. This taught me that roles aren't just an alternative to users, they're actually a safer way to handle access for anything temporary or cross-account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IAM Policies&lt;/strong&gt;- A policy, written in JSON, essentially spells out exactly what actions are allowed or denied on which resources. At first, the JSON format looked intimidating to me, but once I broke it down, I realized it's really just a structured way of saying "this identity can" or "this identity cannot" do a specific thing. What I appreciated most about policies is how much control they give me over granularity. I'm not stuck choosing between "full access" or "no access." I can be as specific as allowing someone to only read from one particular S3 bucket, without touching anything else in the account. Learning to write and attach policies made me realize that this is really where the principle of least privilege comes to life. It's one thing to talk about giving minimal permissions, but policies are the actual tool that makes it possible. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How IAM Controls Access&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;- This is AWS confirming I am who I say I am, whether through a console login or access keys via the CLI. It doesn't grant permissions on its own, it just verifies identity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization&lt;/strong&gt;- Once I'm authenticated, IAM checks the permissions tied to my user, group, or role to decide what I'm actually allowed to do. This is where policies come in. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of access management in AWS&lt;/strong&gt;- Say I create a new IAM user with no permissions attached. They can log in, but every action is denied until I grant access, like read access to an S3 bucket. Try anything outside that, like deleting an EC2 instance, and authorization blocks it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IAM Best Practices&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Principle of least privilege&lt;/strong&gt;- This was a recurring phenomenon as I read through IAM documentation, and it's essentially the idea of giving users only the permissions they need, nothing more. I learned that it's easier to grant additional access later than to try and undo the damage from over-permissioned accounts. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable Multi-Factor Authentication (MFA)&lt;/strong&gt;- Even strong passwords can be compromised, so I picked up that adding MFA gives an extra layer of protection, requiring a second form of verification before access is granted. It's a small step that significantly reduces the risk of unauthorized access. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avoid using the root account&lt;/strong&gt;- the root account has unrestricted access to everything, which makes it a major security risk if used for everyday tasks. I learned that it's best practice to lock it away, enable MFA on it specifically, and rely on IAM users and roles for daily operations instead. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-World Use Case&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Simple example of assigning permissions to a user&lt;/strong&gt;- To bring everything together, say I onboard a new team member who only needs to view files in a specific S3 bucket. I'd start by creating an IAM user for them, then attach a policy granting read-only access to that particular bucket. Instead of assigning this directly to the user, I'd add them to a group I've already set up for that permission level, say, "S3-ReadOnly", so if another team member needs the same access later, I just add them to the group instead of repeating the process. This small example reflects exactly what I learned throughout: start with no access, grant only what's needed, and use groups to keep things scalable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONCLUSION&lt;/strong&gt;&lt;br&gt;
Looking back, IAM turned out to be more than just a checkbox in AWS setup, it's the layer that decides who gets in, what they can touch, and how much damage a single mistake can cause. Getting comfortable with users, groups, roles, and policies changed how I think about security altogether, not as something to configure once and forget, but as an ongoing responsibility. &lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>The Smallest Fix With The Biggest Impact [Skips VS Technology Edition]</title>
      <dc:creator>Joyce Foster</dc:creator>
      <pubDate>Thu, 20 Aug 2026 09:11:15 +0000</pubDate>
      <link>https://dev.to/joycefosterr/the-smallest-fix-with-the-biggest-impactskips-vs-technology-edition-2id6</link>
      <guid>https://dev.to/joycefosterr/the-smallest-fix-with-the-biggest-impactskips-vs-technology-edition-2id6</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Remember that one Regular Show episode where Skips tried to destroy the park's computer because it caught the &lt;em&gt;Error 220&lt;/em&gt; bug? He took one look at it, picked up a sledgehammer and said the line we’ve all felt as devs: “ &lt;em&gt;There’s something evil in that computer. We gotta smash it&lt;/em&gt;”. In the cartoon, they literally smash the computer and this works to fix the bug. In real life? We don’t get sledgehammers. We get Github PRs.&lt;/p&gt;

&lt;p&gt;Last week, I almost felt like Skips. I found a one-line bug in an open source repo that could’ve broken Instagram webhook security. No hammer, no explosion, just one misindented ‘if’ statement and a missing test. This is the story of how the smallest fix had the biggest impact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-The Challenge&lt;/strong&gt;&lt;br&gt;
So what was my &lt;em&gt;Error 220&lt;/em&gt;? &lt;br&gt;
While contributing to the corsair open-source repo, I found a security breach in the Instagram webhook handler. Something about the verification flow felt off, so I started tracing it line by line. The code called &lt;code&gt;timingSafeEqual&lt;/code&gt; but the result was indecisive. I took an extensive look at it and that's when I saw it- The &lt;code&gt;if&lt;/code&gt; statement meant to guard the check was there, but &lt;code&gt;timingSafeEqual&lt;/code&gt; was indented wrong. It was meant to return the result of &lt;code&gt;timingSafeEqual&lt;/code&gt; to accept or reject the request, but it fell through instead. Although it was running, its return value wasn’t being used to control the flow. &lt;br&gt;
This bug was tiny-one mis-indented line- but it had a great impact. In JS, it is not considered an error and so it’s easy to miss. Webhook security relies on a signature check to prove a request. If timingSafeEqual isn’t actually enforcing it, an attacker could forge a webhook and it would be accepted. The entire protection could fall apart over one tab.&lt;br&gt;
&lt;a href="https://github.com/corsairdev/corsair/pull/759" rel="noopener noreferrer"&gt;View PR #759&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-The Fix&lt;/strong&gt;&lt;br&gt;
In fixing it, I opened &lt;code&gt;PR#759&lt;/code&gt; to correct the indentation so &lt;code&gt;crypto.timingSafeEqual&lt;/code&gt; would be inside the &lt;code&gt;if&lt;/code&gt; block and its boolean result would decide whether to return &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. Prior to the fix, the function was calling &lt;code&gt;timingSafeEqual&lt;/code&gt; but then ignoring what it returned and continuing to execute anyway. The update makes it return instantly based on that result. If a signature doesn’t match, the request is rejected. In the same vein, it is accepted where it matches.&lt;/p&gt;

&lt;p&gt;This change, small but significant, reconnects the verification to the return value.  Consequently, the library actually enforces “only accepts requests signed by Instagram” instead of just running the check. This two-line difference restores the whole security guarantee and &lt;code&gt;PR #759&lt;/code&gt; has since been merged into the corsair repo, closing the gap for good. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-The Technical Breakdown&lt;/strong&gt;&lt;br&gt;
Here, Instagram signs every webhook with a secret key, and sends that signature in the request header. It is then the corsair's job to take the incoming payload, recreate the signature on our side, and compare it to the one Instagram sent. At this stage, &lt;code&gt;crypto.timingSafeEqual&lt;/code&gt; comes in. It is a &lt;code&gt;Node.js&lt;/code&gt; function made particularly for comparing secrets because it requires the same amount of time, whether they match or not. This prevents timing attacks.&lt;/p&gt;

&lt;p&gt;In the process of generating the comparison, the bug broke the last step, and due to the indentation, the results never actually returned. So, the function would always continue, whether the signatures matched or not. After &lt;code&gt;PR#759&lt;/code&gt;, I made the return value matter. If &lt;code&gt;timingSafeEqual&lt;/code&gt; says false, it rejects. If it says true, it accepts. Now the check actually gates the request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-The Lesson&lt;/strong&gt;&lt;br&gt;
What I am proud of: Recalling the Regular Show episode where the computer threw &lt;em&gt;Error 220&lt;/em&gt; and Skips immediately wanted to smash it. With this bug, it would’ve been just as easy to see the bad indentation, ignore it and let the webhook pass through anyway. I am proud that, like Skips, I decided to “smash” the bug by finding and fixing the indentation. This small choice positively restored the security.&lt;/p&gt;

&lt;p&gt;What I learnt: I learnt that running a security check isn’t the same as enforcing it. My code was checking the signature but not using the result. Technology is only effective when you act on what it tells you. &lt;code&gt;crypto.timingSafeEqual&lt;/code&gt; only mattered once I made its return value decide whether to accept or reject.&lt;/p&gt;

&lt;p&gt;Challenges I came across: The challenge was that it failed silently. Just like &lt;em&gt;Error 220&lt;/em&gt; didn’t crash the computer in Regular Show, the bug didn’t show any errors. The request still went through whether the signature was valid or not. I had to slow down, read the flow and make one precise fix. This made me pay attention to the tiniest of details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-Before and After Comparison&lt;/strong&gt;&lt;br&gt;
Before: The webhook validation ran &lt;code&gt;timingSafeEqual&lt;/code&gt; but ignored the result, so all requests got through whether the signature matched or not.&lt;/p&gt;

&lt;p&gt;After: &lt;code&gt;PR#759&lt;/code&gt; makes the return value gate the request, so only valid Instagram webhooks are processed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Error 220&lt;/em&gt; taught the Park crew that some problems just need to be smashed. &lt;code&gt;PR #759&lt;/code&gt; taught me that some problems just need to be seen. Not every fix has to be loud to matter. Sometimes the biggest impact comes from the smallest, most precise correction, one misindented line, caught and fixed, restoring an entire security guarantee. That's the smash bug story I'll remember.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
