<?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: Angela Choi</title>
    <description>The latest articles on DEV Community by Angela Choi (@angelamchoi).</description>
    <link>https://dev.to/angelamchoi</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F623965%2Fe9921df4-47e6-420e-904e-fac404040dc2.png</url>
      <title>DEV Community: Angela Choi</title>
      <link>https://dev.to/angelamchoi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/angelamchoi"/>
    <language>en</language>
    <item>
      <title>How I Approach Debugging API Issues with Customers</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Mon, 15 Dec 2025 20:33:00 +0000</pubDate>
      <link>https://dev.to/angelamchoi/how-i-approach-debugging-api-issues-with-customers-oan</link>
      <guid>https://dev.to/angelamchoi/how-i-approach-debugging-api-issues-with-customers-oan</guid>
      <description>&lt;p&gt;Debugging API issues with customers is one of my favorite aspects of implementation work. It's technical, but it's also very human. Often, customers join the meeting stressed because something that should be functioning isn’t. My role is to help them slow down, understand what is happening, and move forward with confidence.&lt;/p&gt;

&lt;p&gt;Over time, I have developed a straightforward way to approach these conversations. This method keeps the problem manageable and helps customers feel supported rather than overwhelmed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start with Their Expectations
&lt;/h3&gt;

&lt;p&gt;Most calls begin with someone claiming that something is broken. Before I examine an error message or a log, I always ask one question: "What were you expecting to happen?" &lt;/p&gt;

&lt;p&gt;This question reveals a wealth of information. It helps me understand their goal, why they chose a specific endpoint, how their workflow is set up, and where things might have gone awry. Many API issues aren’t actual bugs; they are mismatches between the customer's expectations and the API’s behavior. Once we align on the goal, the rest of the conversation becomes much smoother.&lt;/p&gt;

&lt;h3&gt;
  
  
  Walk Through the Request Step by Step
&lt;/h3&gt;

&lt;p&gt;Next, I ask them to walk me through the request they sent. I want to see the parameters, the environment, and the response they received. &lt;/p&gt;

&lt;p&gt;Slowing down often surfaces the issue quickly. Sometimes it's due to using a staging token in production, a missing required field, or a small typo hidden within an otherwise perfect JSON body. These mistakes are easy to overlook when you're under pressure, so taking it step by step helps both of us to see what’s really happening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplify the Request
&lt;/h3&gt;

&lt;p&gt;If the request is complex, I help the customer simplify it. We strip it down to the smallest version that should work. &lt;/p&gt;

&lt;p&gt;If there’s a large payload, we test with a minimal one. If multiple actions are chained together, we test just one. This approach makes it easier to isolate the problem and provides customers with a troubleshooting method they can reuse later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the Basics First
&lt;/h3&gt;

&lt;p&gt;Most API issues stem from simple matters, so I always start there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the token valid?&lt;/li&gt;
&lt;li&gt;Is the correct endpoint being used?&lt;/li&gt;
&lt;li&gt;Are field names spelled correctly?&lt;/li&gt;
&lt;li&gt;Is the content type appropriate?&lt;/li&gt;
&lt;li&gt;Are the correct environments in use?&lt;/li&gt;
&lt;li&gt;Are test and production credentials mixed up?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These details can cause significant frustration, but it’s never due to carelessness. APIs are strict, and documentation doesn’t always reflect real-world behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explain the System’s Response
&lt;/h3&gt;

&lt;p&gt;I never want to simply provide a fix. I always explain why the error is happening and how the system is interpreting their request. &lt;/p&gt;

&lt;p&gt;When customers understand the "why," not just the "how," they feel more confident and less dependent when something goes wrong in the future. Debugging turns into a learning opportunity instead of a setback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collaborate Rather Than Take Over
&lt;/h3&gt;

&lt;p&gt;Even when I know the answer, I refrain from taking control. I explain what I’m checking and why, then allow the customer to try the next step themselves. &lt;/p&gt;

&lt;p&gt;This keeps the process collaborative and helps customers develop their own troubleshooting skills. Over time, I have seen individuals transform from feeling anxious about APIs to becoming comfortable debugging on their own.&lt;/p&gt;

&lt;h3&gt;
  
  
  End with Clear Next Steps
&lt;/h3&gt;

&lt;p&gt;Before concluding the call, I always provide a recap. I want them to leave knowing exactly what to do next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The correct request to send&lt;/li&gt;
&lt;li&gt;The appropriate permissions to use&lt;/li&gt;
&lt;li&gt;How to test the endpoint&lt;/li&gt;
&lt;li&gt;What to watch for next time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A clear wrap-up turns a frustrating experience into something beneficial. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why I Enjoy This Work
&lt;/h3&gt;

&lt;p&gt;The best part of debugging with customers is the moment everything finally works. You can hear the relief in their voices. It feels like a shared victory because we solved the problem together. &lt;/p&gt;

&lt;p&gt;I take something that feels stressful and make it manageable. Helping someone understand what’s happening and regain their confidence is what makes this part of the job so rewarding for me.&lt;/p&gt;

</description>
      <category>api</category>
      <category>debugging</category>
      <category>integration</category>
    </item>
    <item>
      <title>Why I Fell in Love With Implementation Work</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Mon, 15 Dec 2025 20:05:44 +0000</pubDate>
      <link>https://dev.to/angelamchoi/why-i-fell-in-love-with-implementation-work-i0f</link>
      <guid>https://dev.to/angelamchoi/why-i-fell-in-love-with-implementation-work-i0f</guid>
      <description>&lt;p&gt;A few years ago, if you had told me that I would love implementation work, I wouldn't have believed you. Coming from a teaching background, I had experience working with students, but I never envisioned myself teaching adults how to use software or assisting developers with API integration. This role has surprised me in the best possible way. While implementation is technical, at its core, it is profoundly human.&lt;/p&gt;

&lt;p&gt;People often perceive implementation as merely checklists, administrative tasks, and onboarding calls. And while there is a fair amount of that, the real work occurs in the moments when you guide people through change. Change brings habits, emotions, and fears that are often unrelated to the software itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  It Is Not Really About the Tech
&lt;/h3&gt;

&lt;p&gt;After helping thousands of users transition from our legacy platform to a new one, I began to notice patterns. Most people weren't afraid of new features. They were afraid of losing what they already understood. The old platform was familiar. Even if it was clunky, they knew how to navigate it.&lt;/p&gt;

&lt;p&gt;What I learned is people do not fear new systems. They fear losing confidence. Being the person who helps them through that moment has become the most rewarding part of my job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Tech Meets Empathy
&lt;/h3&gt;

&lt;p&gt;Implementation exists at the intersection of technical knowledge and human understanding. One moment, I'm explaining an authentication flow or reviewing API logs; the next, I'm reassuring someone who worries that one wrong click could break everything. &lt;/p&gt;

&lt;p&gt;There is something meaningful about being the calm voice on the call. When someone is stressed or stuck, I can slow things down and help them feel capable again. You can almost hear it when things finally click. The moment a workflow makes sense or when resistance transforms into curiosity. These moments never get old.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Wins Feel Personal
&lt;/h3&gt;

&lt;p&gt;As a former developer, I loved shipping new features. However, the wins in implementation feel different. When a customer finally sends their first successful API call after weeks of struggle, it feels like a shared victory. When a team that initially dreaded migration begins teaching each other, it marks a genuine turning point.&lt;/p&gt;

&lt;p&gt;These wins are not about solving problems. They involve watching people regain confidence. That sense of impact is what makes the work so rewarding.&lt;/p&gt;

&lt;h3&gt;
  
  
  You Become a Translator
&lt;/h3&gt;

&lt;p&gt;A significant aspect of this job is translation: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I translate technical concepts into actionable steps. &lt;/li&gt;
&lt;li&gt;I translate old workflows into new ones. &lt;/li&gt;
&lt;li&gt;I translate customer frustration into valuable product feedback. &lt;/li&gt;
&lt;li&gt;I translate complex API processes into clear paths forward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I still get to utilize my technical skills, but I also help people understand what they are doing. That balance is rare, and I value it more than I initially expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Implementation Taught Me
&lt;/h3&gt;

&lt;p&gt;Implementation has taught me patience. It has taught me to listen for the real question behind each inquiry. I’ve realized that most users believe they are the only ones struggling, when, in reality, almost everyone experiences difficulty during periods of change.&lt;/p&gt;

&lt;p&gt;Migrations have shown me that success isn't about feature parity. Instead, it's about guiding people through the uncomfortable space between what they used to know and what they are learning now. Along the way, I discovered that this type of work allows me to connect genuinely with the people I am helping.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why I Love It Now
&lt;/h3&gt;

&lt;p&gt;I love implementation work because it combines the aspects of technology and human connection that matter most to me. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I help people feel confident. &lt;/li&gt;
&lt;li&gt;I simplify complex ideas into manageable steps. &lt;/li&gt;
&lt;li&gt;I support customers through real technical challenges. &lt;/li&gt;
&lt;li&gt;I balance patience with technical knowledge. &lt;/li&gt;
&lt;li&gt;I see the immediate impact of my work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It never feels like I’m just rolling out an updated software. It feels like I'm assisting people in moving forward through one workflow at a time, one conversation at a time, one API integration at a time.&lt;/p&gt;

&lt;p&gt;That is why I have fallen in love with this work, and honestly, I’m glad I did.&lt;/p&gt;

</description>
      <category>implementation</category>
      <category>migration</category>
    </item>
    <item>
      <title>What Platform Migrations Taught Me About Customer Behavior</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Wed, 10 Dec 2025 20:22:41 +0000</pubDate>
      <link>https://dev.to/angelamchoi/what-platform-migrations-taught-me-about-customer-behavior-17h3</link>
      <guid>https://dev.to/angelamchoi/what-platform-migrations-taught-me-about-customer-behavior-17h3</guid>
      <description>&lt;p&gt;As a Technical Implementation Manager, my primary responsibility is overseeing software migrations, guiding our users as they transition from our legacy platform to the new one. My goal is to make this process smooth and manageable. After assisting thousands of individuals with this transition, I've come to understand that migrations are less about the software and more about the people involved.&lt;/p&gt;

&lt;p&gt;While there are technical considerations, such as importing data, rebuilding workflows, reconnecting integrations, and answering questions like "Where did this feature go?" or "How do I do XYZ?", the core issues are fundamentally human. Change brings uncertainty, shakes confidence, and triggers a mix of emotions, including frustration, hesitation, excitement, and ultimately, relief.&lt;/p&gt;

&lt;p&gt;These emotional milestones have taught me a great deal about customer behavior and their true needs. Here’s what I’ve learned:&lt;/p&gt;

&lt;h3&gt;
  
  
  Customers Don’t Fear Change — They Fear Losing What They Know
&lt;/h3&gt;

&lt;p&gt;Initially, I believed that resistance to migration stemmed from a lack of understanding of the new platform. Over time, I realized that users were not clinging to the old system. They were protecting their comfort zones. For many, migrating feels like losing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiar workflows&lt;/li&gt;
&lt;li&gt;Muscle memory&lt;/li&gt;
&lt;li&gt;Confidence&lt;/li&gt;
&lt;li&gt;A sense of being the "expert"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even the most advanced power users can suddenly feel like beginners, which can be uncomfortable. Once I started acknowledging these feelings of loss rather than pushing past them, conversations shifted. People became more open and collaborative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Empathy helps move people forward faster than any amount of documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Training Isn’t Just Teaching — It’s Reassurance
&lt;/h3&gt;

&lt;p&gt;When someone logs into a new platform for the first time, they don’t just want a comprehensive product tour. They want reassurance that they won’t break anything. I learned to slow down my demos, explaining why I was clicking certain things and showing what happens if a mistake is made. My go-to phrase became: “It’s okay if you make a mistake. You can’t break anything here—feel free to explore.”Once users feel safe to explore, their learning curve shortens dramatically and their confidence increases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Great training alleviates anxiety as much as it fills knowledge gaps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customers Want to Know Why, Not Just How
&lt;/h3&gt;

&lt;p&gt;Simply walking someone through new workflows step-by-step won’t resonate unless they understand why the changes are important. Instead of just saying, “We moved this feature,” I provide context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“We redesigned this to reduce the number of steps.”&lt;/li&gt;
&lt;li&gt;“This is automated now to help teams save time.”&lt;/li&gt;
&lt;li&gt;“We split these settings to avoid configuration errors.”
This approach makes everything feel more intentional and less arbitrary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Providing context accelerates adoption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Small Frictions Turn Into Big Emotions During Migration
&lt;/h3&gt;

&lt;p&gt;Minor issues, like a missing button, a renamed setting, or an extra click, can trigger disproportionately strong reactions during migrations. While these would usually be minor annoyances, during a migration—when users feel overwhelmed—these moments can become “proof” that the new platform is inferior. Once I understood this, I proactively addressed those frictions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Here’s where that feature moved.”&lt;/li&gt;
&lt;li&gt;“This workflow has changed, but here’s what you gain.”&lt;/li&gt;
&lt;li&gt;“It may be different, but it’s not broken.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to mitigate frustration before it escalates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Anticipate friction and address it early.&lt;/p&gt;

&lt;h3&gt;
  
  
  People Don’t Adopt Systems — They Adopt Stories
&lt;/h3&gt;

&lt;p&gt;Features alone do not convince people; outcomes do. The pivotal moment in most migrations occurs when I illustrate how the new platform can help users achieve their goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“This will cut your reporting time in half.”&lt;/li&gt;
&lt;li&gt;“You’ll have much more control over your data.”&lt;/li&gt;
&lt;li&gt;“This sets you up for the improvements you’ve been requesting.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The narrative must connect to their daily reality, not just our roadmap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Adoption is driven by emotions, not just logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migration Success Depends on Understanding Your Champions and Skeptics
&lt;/h3&gt;

&lt;p&gt;Every migration involves two groups:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Champions: Excited, curious, vocal, early adopters&lt;/li&gt;
&lt;li&gt;Skeptics: Quiet, hesitant, sometimes frustrated and often very influential&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Champions help build momentum, while skeptics can make or break the rollout. I learned to support both groups in different ways:&lt;/p&gt;

&lt;p&gt;Champions received sneak peeks, early access, and advanced sessions.&lt;/p&gt;

&lt;p&gt;Skeptics were given one on one feedback sessions with our Product Designer to better understand their frustrations and gather honest input about the new platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Support your champions, but listen closely to your skeptics. Both groups shape the success of a migration, and giving each what they need leads to a smoother, more balanced rollout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;After supporting so many people through these migrations, what stays with me most is that this work is really about the humans behind the screens. Every rebuild, every “where did that go,” every moment of confusion or relief has shown me that change is personal long before it is technical.&lt;/p&gt;

&lt;p&gt;Once I started approaching migrations with that mindset everything shifted. Conversations became easier. People opened up. They trusted the process more because they felt understood instead of rushed. And in those moments I realized that my job is not just to move users to a new platform, it is to help them feel confident in a new environment.&lt;/p&gt;

&lt;p&gt;Looking back, the biggest thing I have learned is that successful migrations happen when people feel supported, not pushed. When they feel like they can ask anything. When they understand the why behind the changes. And when they know they are not alone while they figure it all out.&lt;/p&gt;

&lt;p&gt;That is the part of implementation work I enjoy the most. It is not just about upgrading a system. It is about helping people navigate a transition with a little more clarity, a little more confidence, and a lot less stress. Every migration is an opportunity not just to move data, but to move people forward.&lt;/p&gt;

</description>
      <category>migrations</category>
      <category>customerbehavior</category>
      <category>data</category>
    </item>
    <item>
      <title>What Hogwarts Can Teach Us About Security</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Mon, 24 Mar 2025 20:46:12 +0000</pubDate>
      <link>https://dev.to/angelamchoi/what-hogwarts-can-teach-us-about-security-5bme</link>
      <guid>https://dev.to/angelamchoi/what-hogwarts-can-teach-us-about-security-5bme</guid>
      <description>&lt;p&gt;How does Hogwarts keep its magical secrets safe? Enter the world of Identity and Access Management (IAM), the digital equivalent of Hogwarts' security system. Let's break it down using a little wizarding magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 What is Identity and Access Management?
&lt;/h2&gt;

&lt;p&gt;IAM is like the enchanted portraits guarding the entrances to Hogwarts common rooms. It’s a system that ensures only the right people (or wizards) can access specific areas, information, or perform certain tasks. It helps keep everything safe and organized.&lt;/p&gt;

&lt;p&gt;To make it simple, let's see how Hogwarts uses IAM every day!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 🔑Authentication: Proving You’re a Wizard&lt;/strong&gt;&lt;br&gt;
When Harry arrives at Hogwarts, he has to show his student ID (like the Hogwarts letter) to enter the castle. This is just like logging in with a username and password.&lt;/p&gt;

&lt;p&gt;In the real world: You authenticate by entering your credentials (username and password) to prove who you are.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. 🚪Authorization: Knowing Where You Belong&lt;/strong&gt;&lt;br&gt;
Once inside, Harry’s student ID determines where he can go. He can visit the Great Hall for meals but needs special permission to enter the Restricted Section of the library.&lt;/p&gt;

&lt;p&gt;In the real world: After logging in, authorization defines what data or systems you can access. You might view emails but not confidential financial reports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.🦄Single Sign-On (SSO): One Spell, Many Doors&lt;/strong&gt;&lt;br&gt;
After Harry enters Hogwarts, he doesn’t need to show his ID every time he enters a classroom. Similarly, Single Sign-On (SSO) lets you log in once and access multiple applications without typing your password repeatedly.&lt;/p&gt;

&lt;p&gt;In the real world: Using Google or Facebook to log into multiple websites without creating new passwords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.🔎Tracking Activity: The Marauder’s Map of Security&lt;/strong&gt;&lt;br&gt;
The Marauder’s Map tracks everyone's location at Hogwarts. IAM systems do something similar by keeping logs of who accessed what and when. If someone sneaks into the Restricted Section, the system will know!&lt;/p&gt;

&lt;p&gt;In the real world: IAM logs help companies monitor for suspicious activity and respond quickly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧙‍♂️ Why is IAM Important?
&lt;/h2&gt;

&lt;p&gt;Think of IAM as the Hogwarts security spells that:&lt;/p&gt;

&lt;p&gt;🔒&lt;strong&gt;Secure Data&lt;/strong&gt;: Only the right people can access sensitive information, like how only professors can enter their offices.&lt;/p&gt;

&lt;p&gt;🚫 &lt;strong&gt;Prevent Unauthorized Access&lt;/strong&gt;: Keeps the digital Dark Wizards (hackers!) out of systems.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Enhance User Experience&lt;/strong&gt;: Single Sign-On makes logging in easy, like using a Portkey instead of walking.&lt;/p&gt;

&lt;p&gt;📜&lt;strong&gt;Support Compliance&lt;/strong&gt;: Helps organizations follow security rules, just like Hogwarts students follow school rules.&lt;/p&gt;

&lt;p&gt;IAM is like the enchanted guardian of the digital world. It ensures only the right people have access, keeps systems secure, and makes navigating online spaces as magical as a day at Hogwarts. So, the next time you log in to an app or website, remember - you're stepping into your own digital Hogwarts, protected by the powerful magic of IAM.&lt;/p&gt;

&lt;p&gt;Accio Security!🔮✨&lt;/p&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>From Pizza Orders to Party Crashers: Understanding Web Security Threats</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Tue, 11 Mar 2025 01:40:07 +0000</pubDate>
      <link>https://dev.to/angelamchoi/from-pizza-orders-to-party-crashers-understanding-web-security-threats-3eg8</link>
      <guid>https://dev.to/angelamchoi/from-pizza-orders-to-party-crashers-understanding-web-security-threats-3eg8</guid>
      <description>&lt;p&gt;Understanding web security threats is crucial for everyone, even those without a technical background. To make these concepts easier to grasp, here are four common web security threats explained using relatable, everyday scenarios:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 🍕The Sneaky Pizza Order (SQL Injection)&lt;/strong&gt;&lt;br&gt;
Imagine you're at a pizza restaurant where you write down your order. Normally, you'd jot down something like, "One pepperoni pizza, please." But what if someone wrote, "One pepperoni pizza; and also give me the secret sauce recipe"? If the chef blindly follows the instructions, they might accidentally reveal their secret recipe.&lt;br&gt;
This is exactly how SQL injection works—hackers insert malicious commands into input fields (like login forms) to trick a website into revealing or modifying sensitive data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. 🥠The Fortune Cookie Prank (Cross-Site Scripting)&lt;/strong&gt; &lt;br&gt;
Picture this: You crack open a fortune cookie expecting a cheesy prediction, but instead, it says, "Warning: Your bank account has been hacked!" Even though it's just a harmless message on paper, it would still give you a scare.&lt;br&gt;
This is similar to cross-site scripting (XSS). Hackers inject malicious scripts into websites that unsuspecting users visit. When the user’s browser processes the code, it could display fake alerts or even steal sensitive information like login credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. 📝The Gullible Assistant (Cross-Site Request Forgery)&lt;/strong&gt;&lt;br&gt;
Imagine you have an assistant who follows your instructions without question. Now suppose someone pretending to be you sends them an email saying, "Transfer $5,000 to this account immediately!" Without verifying the sender’s identity, your assistant might unknowingly send the money.&lt;br&gt;
This is how cross-site request forgery (CSRF) works. It tricks authenticated users into performing unintended actions on trusted websites, such as transferring funds or changing account details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. 🎉The Party Crasher Nightmare (Distributed Denial of Service)&lt;/strong&gt;&lt;br&gt;
Imagine hosting a small dinner party for 10 friends. But someone spreads a fake invitation online saying you're hosting an all-you-can-eat buffet. Suddenly, hundreds of strangers show up at your door, overwhelming your space and preventing your actual guests from entering.&lt;br&gt;
This is similar to a distributed denial-of-service (DDoS) attack. Hackers flood a website with so much fake traffic that legitimate users can’t access it, effectively crashing the system.&lt;/p&gt;

&lt;p&gt;By using these relatable examples, even non-technical individuals can better understand how these threats work and why implementing cybersecurity measures is so important.&lt;/p&gt;

&lt;p&gt;⚔️Stay Vigilant, Stay Secure!🛡️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>security</category>
    </item>
    <item>
      <title>Implementing Devise Lockable: A Step-by-Step Guide to Account Locking in Rails</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Wed, 05 Mar 2025 18:33:08 +0000</pubDate>
      <link>https://dev.to/angelamchoi/unlocking-the-potential-of-lockable-3pge</link>
      <guid>https://dev.to/angelamchoi/unlocking-the-potential-of-lockable-3pge</guid>
      <description>&lt;p&gt;In October 2024, I presented at the &lt;a href="https://toronto-ruby.com/events/past" rel="noopener noreferrer"&gt;Toronto Ruby Meetup&lt;/a&gt; on discovering the potential of using &lt;a href="https://github.com/heartcombo/devise/blob/main/lib/devise/models/lockable.rb" rel="noopener noreferrer"&gt;Lockable&lt;/a&gt;. Devise is a popular authentication library that provides ready-made solutions for user authentication. One of the features it offers is Lockable, which is used to lock a user account after a certain number of failed login attempts. This feature helps improve security by preventing brute force attacks.&lt;/p&gt;

&lt;p&gt;A few days months ago, as I was logging into my work laptop, I mistyped my password and ended up getting locked out for one minute. After the minute was up, I tried again, but I was locked out for 10 minutes this time. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bnba97xddcjvqevlj2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bnba97xddcjvqevlj2f.png" alt="Image description" width="510" height="290"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;The lockable module locks an account after several failed sign-in attempts. You can unlock by email or after a specified period or it can require manual unlocking by an admin. This helps protect user accounts from unauthorized access. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step-by-step guide&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This guide outlines how to implement lockable functionality in your Rails application using two strategies: 1) unlocking via email or time-based methods, and 2) customizing failure and unlock strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Devise&lt;/strong&gt;&lt;br&gt;
Before we dive into implementing lockable, ensure you have Devise installed.  If you haven't installed it yet, follow the instructions below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypuk2hnnqz5mc1zqwpb2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypuk2hnnqz5mc1zqwpb2.png" alt="Image description" width="448" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Unlock by email and/or time based unlock&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Config file&lt;/strong&gt;&lt;br&gt;
Let’s take a look at how this would look like in your config file. In this example, I am utilizing both email and time-based strategies. Users will have a maximum of five failed login attempts, and a warning will be issued on their final attempt. To regain access, users can either receive an email with a link or wait one hour to unlock their account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwowz3b8ypz7yq96knc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwowz3b8ypz7yq96knc6.png" alt="Image description" width="526" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lockable adds the following options to &lt;code&gt;devise&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;maximum_attempts&lt;/code&gt;: how many attempts should be accepted before blocking the user.&lt;br&gt;
&lt;code&gt;lock_strategy&lt;/code&gt;: lock the user account by &lt;code&gt;:failed_attempts&lt;/code&gt; or &lt;code&gt;:none&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;unlock_strategy&lt;/code&gt;: unlock the user account by &lt;code&gt;:time&lt;/code&gt;, &lt;code&gt;:email&lt;/code&gt;, &lt;code&gt;:both&lt;/code&gt; or &lt;code&gt;:none&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;unlock_in&lt;/code&gt;: the time you want to unlock the user after lock happens. Only available when &lt;code&gt;unlock_strategy&lt;/code&gt; is &lt;code&gt;:time&lt;/code&gt; or &lt;code&gt;:both&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;unlock_keys&lt;/code&gt;: the keys you want to use when locking and unlocking an account&lt;/p&gt;

&lt;p&gt;To learn more about lockable options, please refer to this &lt;a href="https://www.rubydoc.info/github/plataformatec/devise/Devise/Models/Lockable" rel="noopener noreferrer"&gt;doc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. User Model&lt;/strong&gt;&lt;br&gt;
Next, we can go to the User model. In my user model, I’ve added a few devise modules already. You can add the &lt;code&gt;lockable&lt;/code&gt; module here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugw0asuh8mfi3dfdqajz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugw0asuh8mfi3dfdqajz.png" alt="Image description" width="605" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Create a migration&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;rails g migration add_lockable_to_devise&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In your migration file, you’ll want to add &lt;code&gt;failed_attempts&lt;/code&gt; and &lt;code&gt;locked_at&lt;/code&gt; to users so that you can keep track of this information in the backend. If your unlock strategy is email or both you can add &lt;code&gt;unlock_token&lt;/code&gt; to your users. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i9d0j2f34gzpjys5k60.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9i9d0j2f34gzpjys5k60.png" alt="Image description" width="663" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Customizable failure and unlock stratgies&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Config file&lt;/strong&gt;&lt;br&gt;
In your config file, you can set the &lt;code&gt;lock_strategy&lt;/code&gt; and &lt;code&gt;unlock_strategy&lt;/code&gt; to &lt;code&gt;none&lt;/code&gt;. You might be wondering how users will unlock their accounts in this case. To address this, you can create a toggle button that allows administrators to lock and unlock user accounts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gu01artl7bk55bj8w18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gu01artl7bk55bj8w18.png" alt="Image description" width="491" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Users controller&lt;/strong&gt;&lt;br&gt;
In the &lt;code&gt;users_controller&lt;/code&gt;, you can create a function to toggle the lock status of a user’s account. The code below first checks whether the user's account is locked. If the account is locked, the function will unlock it; otherwise, it will lock the account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5nqkwfke9xro26bt2a1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5nqkwfke9xro26bt2a1.png" alt="Image description" width="495" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xlx992dw04yzradb79b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xlx992dw04yzradb79b.png" alt="Image description" width="524" height="209"&gt;&lt;/a&gt;&lt;/p&gt;
An example of a toggle unlocked and locked button


        

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Lockable module from Devise adds a critical layer of security to your application&lt;/li&gt;
&lt;li&gt;It is easy to implement the lockable using Devise&lt;/li&gt;
&lt;li&gt;Implementing the lockable feature can enhance user trust and safety by protecting their accounts from unauthorized access&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>security</category>
    </item>
    <item>
      <title>API Webhook Security</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Mon, 03 Mar 2025 21:00:00 +0000</pubDate>
      <link>https://dev.to/angelamchoi/api-webhook-security-ig8</link>
      <guid>https://dev.to/angelamchoi/api-webhook-security-ig8</guid>
      <description>&lt;p&gt;Web security is a crucial aspect of modern development, and it's important for everyone to understand how to protect their web applications and APIs. I've been exploring this field extensively lately, and I'd like to share some insights I've gained, particularly in the realm of webhook security. Let me walk you through some key strategies to keep your webhooks secure and reliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👀Be Vigilant with Webhook URLs&lt;/strong&gt;&lt;br&gt;
One of the main vulnerabilities in webhook services is server-side request forgery (SSRF). This occurs when an attacker manipulates your service into making unauthorized requests. Webhooks are particularly susceptible because they rely on user-provided URLs. To mitigate this risk, it's crucial to implement strict URL validation. This not only protects your system but also helps users by promptly informing them if their URL doesn't meet your security standards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔐Embrace HMAC for Authentication&lt;/strong&gt;&lt;br&gt;
Ensuring the authenticity of webhook requests is vital. Even encrypted messages can be intercepted, so we need to go a step further. This is where Hash-Based Message Authentication Code (HMAC) comes in handy. The webhook provider sends a message along with an HMAC signature. When the client receives it, they generate their own HMAC signature. If the signatures match, you know the message is authentic. If not, it's best to reject it. For example, Stripe cleverly includes their signature in a header called Stripe-Signature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⏰Implement Timeouts and Retries&lt;/strong&gt;&lt;br&gt;
It's important to set reasonable time limits for webhook requests. If a request is taking too long, you should either terminate it or attempt a retry. Speaking of retries, make sure you have a robust retry mechanism in place for those inevitable hiccups. This ensures you don't lose valuable data due to temporary failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📈Monitor and Log Diligently&lt;/strong&gt;&lt;br&gt;
Keep detailed logs of all incoming webhook requests, including timestamps, IP addresses, and payload content (excluding sensitive information, of course). Set up alerts for unusual patterns, such as sudden spikes in requests. This proactive approach allows you to catch and address potential issues before they escalate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💻Enforce Strict Authorization&lt;/strong&gt;&lt;br&gt;
This one's straightforward but crucial: ensure that only the user who subscribed to a webhook can access and modify that particular subscription. Always verify a user's permissions before allowing them to trigger any webhook actions. This prevents unauthorized access and protects the integrity of your system.&lt;/p&gt;

&lt;p&gt;By following these guidelines, you'll be well on your way to maintaining secure and reliable webhooks. Remember, web security is an ongoing process, and staying informed about the latest best practices is key to keeping your systems safe.&lt;/p&gt;

&lt;p&gt;Cheers to secure development!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>security</category>
    </item>
    <item>
      <title>Coding journey.</title>
      <dc:creator>Angela Choi</dc:creator>
      <pubDate>Fri, 14 May 2021 02:41:22 +0000</pubDate>
      <link>https://dev.to/angelamchoi/coding-journey-3ena</link>
      <guid>https://dev.to/angelamchoi/coding-journey-3ena</guid>
      <description>&lt;p&gt;&lt;strong&gt;2020&lt;/strong&gt;&lt;br&gt;
In 2020, one of my many New Year's resolutions was to learn to code. Of course, I waited until the last minute to try to accomplish this goal. At the end of October 2020, I began my first Web Development course to learn HTML and CSS online. This was my first time learning how to code. As a visual learner, I was particularly drawn to CSS and its capabilities. I love that I can immediately see my changes and there are a plethora of color options :) While taking this course, I was commuting to work as a teacher in NYC and would code before or after work on the subway. I found it therapeutic. It was my escape from reality. I felt like I was disappearing into a different world to solve problems (AKA trying to master all of CSS properties). I slowly began to fall in love with coding. I loved that I could create something powerful and impactful with code and wanted to learn more. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2021&lt;/strong&gt;&lt;br&gt;
In February 2021, I was accepted into General Assembly's Software Engineering Immersive Flex program. It's a 6-month part-time program. For me, this program allows me to keep my job while I learn to code. I also like that it is a bit slower pace so that I have time to process the information.   &lt;/p&gt;

&lt;p&gt;Reasons why I decided to delve deeper into programming:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.⌚Time&lt;/strong&gt; &lt;br&gt;
Every year I've been telling myself that I want to code. Now, that I am working from home I have the flexibility and time to learn. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.🛠️ Going outside of my comfort zone skills&lt;/strong&gt;&lt;br&gt;
I am a pro at soft skills. However, I need to strengthen my technical and analytical skills. Coding allows me to utilize different skills I normally don't get to practice such as technical, analytical, and being extra detail-oriented. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.🐱‍💻Be a student and understand how it's like to learn online&lt;/strong&gt;&lt;br&gt;
As a teacher, I know what it's like to teach online, but I don't know what it's like to be in my students' position- to be taught online. Now, I have a better understanding of how my students learn online.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.❤️📗Create impactful and useful projects related to education to help students, teachers, or both&lt;/strong&gt;&lt;br&gt;
With my new technical skills, I want to help improve the education system and creating an equitable user experience for all learners.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.😃For fun&lt;/strong&gt;&lt;br&gt;
For me, coding is fun and enjoyable. I like that there are various ways to solving a problem, just like a math problem. I've been treating coding like a hobby/sport it's fun to practice and the more I practice the more I get to level up and discover more things along the way. &lt;/p&gt;

&lt;p&gt;With that, this is the beginning phase of my coding journey and I'll be documenting as much as I can.   &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
