<?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: Parveen Kumari</title>
    <description>The latest articles on DEV Community by Parveen Kumari (@pku_bd13f856f0).</description>
    <link>https://dev.to/pku_bd13f856f0</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%2F3934879%2Fef41f426-097b-4578-b558-0bf4377be89b.jpg</url>
      <title>DEV Community: Parveen Kumari</title>
      <link>https://dev.to/pku_bd13f856f0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pku_bd13f856f0"/>
    <language>en</language>
    <item>
      <title>Postman Alternatives in 2026: 5 API Testing Tools Compared</title>
      <dc:creator>Parveen Kumari</dc:creator>
      <pubDate>Sun, 28 Jun 2026 17:51:47 +0000</pubDate>
      <link>https://dev.to/pku_bd13f856f0/postman-alternatives-in-2026-5-api-testing-tools-compared-15ic</link>
      <guid>https://dev.to/pku_bd13f856f0/postman-alternatives-in-2026-5-api-testing-tools-compared-15ic</guid>
      <description>&lt;p&gt;Postman has been the default API tool for developers for years. It's excellent for API exploration, debugging requests, and collaboration. But in 2026, software teams are looking beyond request collections.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Modern engineering teams want:&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AI-generated test cases&lt;/li&gt;
&lt;li&gt;Spec-driven automation&lt;/li&gt;
&lt;li&gt;CI/CD integration&lt;/li&gt;
&lt;li&gt;Contract testing&lt;/li&gt;
&lt;li&gt;Self-hosted deployments&lt;/li&gt;
&lt;li&gt;Better support for enterprise governance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're evaluating alternatives, here are five of the best API testing tools available today.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Shift Left API
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; AI-powered API test automation and enterprise DevOps teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://totalshiftleft.ai/platform" rel="noopener noreferrer"&gt;Shift Left API&lt;/a&gt; is designed for teams that want to move beyond manually maintaining Postman collections. Instead of creating requests one by one, you import your OpenAPI, Swagger, or WSDL specification and automatically generate comprehensive API test suites.&lt;/p&gt;

&lt;p&gt;Unlike traditional API clients, it focuses on complete API lifecycle automation.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;AI-generated API test cases&lt;/li&gt;
&lt;li&gt;Import OpenAPI, Swagger and WSDL&lt;/li&gt;
&lt;li&gt;REST, SOAP and GraphQL support&lt;/li&gt;
&lt;li&gt;Self-hosted LLM support (Ollama, vLLM, LM Studio)&lt;/li&gt;
&lt;li&gt;Cloud AI provider integrations&lt;/li&gt;
&lt;li&gt;Endpoint management&lt;/li&gt;
&lt;li&gt;API mocking&lt;/li&gt;
&lt;li&gt;Test data generation&lt;/li&gt;
&lt;li&gt;Test execution scheduling&lt;/li&gt;
&lt;li&gt;CI/CD integrations&lt;/li&gt;
&lt;li&gt;Coverage analytics&lt;/li&gt;
&lt;li&gt;Contract validation&lt;/li&gt;
&lt;li&gt;Enterprise security and compliance&lt;/li&gt;
&lt;li&gt;Native GitHub Actions, Jenkins, Azure DevOps, GitLab, CircleCI &lt;/li&gt;
&lt;li&gt;No-code test creation&lt;/li&gt;
&lt;li&gt;AI-assisted maintenance&lt;/li&gt;
&lt;li&gt;Detailed execution reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very little manual scripting&lt;/li&gt;
&lt;li&gt;Excellent for large API portfolios&lt;/li&gt;
&lt;li&gt;Enterprise-ready&lt;/li&gt;
&lt;li&gt;Strong CI/CD integration&lt;/li&gt;
&lt;li&gt;Self-hosted AI support for regulated industries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More automation-focused than manual API exploration&lt;/li&gt;
&lt;li&gt;Best experience comes from having an OpenAPI specification available.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Insomnia
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Developers who want a lightweight API client&lt;br&gt;
Insomnia has become one of the most popular Postman alternatives because of its clean interface and Git-based workflow.&lt;/p&gt;

&lt;p&gt;It supports REST, GraphQL and gRPC while keeping the user experience simple.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;REST&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;gRPC&lt;/li&gt;
&lt;li&gt;Git Sync&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;Plugin ecosystem&lt;/li&gt;
&lt;li&gt;Collection runner&lt;/li&gt;
&lt;li&gt;Open-source core&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;li&gt;Clean UI&lt;/li&gt;
&lt;li&gt;Great developer experience&lt;/li&gt;
&lt;li&gt;Git integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less focused on enterprise-scale automation&lt;/li&gt;
&lt;li&gt;Limited AI capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Bruno
&lt;/h2&gt;

&lt;p&gt;**Best for: **Developers who want Git-first API collections&lt;/p&gt;

&lt;p&gt;Bruno stores API collections directly on your filesystem instead of a cloud workspace.&lt;/p&gt;

&lt;p&gt;This makes version control much easier and removes vendor lock-in.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Offline-first&lt;/li&gt;
&lt;li&gt;Git friendly&lt;/li&gt;
&lt;li&gt;Plain text collections&lt;/li&gt;
&lt;li&gt;REST support&lt;/li&gt;
&lt;li&gt;Scripting&lt;/li&gt;
&lt;li&gt;Collection runner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;br&gt;
Open source&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight&lt;/li&gt;
&lt;li&gt;Excellent for Git workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller ecosystem&lt;/li&gt;
&lt;li&gt;Limited enterprise features&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;4. Hoppscotch&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Free browser-based API testing&lt;/p&gt;

&lt;p&gt;Hoppscotch is an open-source API client that runs directly in your browser.&lt;/p&gt;

&lt;p&gt;It's ideal when you need a quick API request without installing desktop software.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Browser-based&lt;/li&gt;
&lt;li&gt;REST&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;WebSocket&lt;/li&gt;
&lt;li&gt;Realtime collaboration&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment management&lt;br&gt;
&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Free&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fast&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easy to start&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less suited for enterprise automation&lt;/li&gt;
&lt;li&gt;Smaller plugin ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. ReadyAPI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Large QA organizations with existing SmartBear investments&lt;/p&gt;

&lt;p&gt;ReadyAPI remains one of the strongest enterprise testing platforms, especially where SOAP services still play a significant role.&lt;/p&gt;

&lt;p&gt;It includes functional testing, mocking, virtualization and performance testing.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;REST&lt;/li&gt;
&lt;li&gt;SOAP&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;li&gt;Load testing&lt;/li&gt;
&lt;li&gt;Service virtualization&lt;/li&gt;
&lt;li&gt;Security testing&lt;/li&gt;
&lt;li&gt;Data-driven testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mature platform&lt;/li&gt;
&lt;li&gt;Enterprise capabilities&lt;/li&gt;
&lt;li&gt;Excellent SOAP support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commercial licensing&lt;/li&gt;
&lt;li&gt;Steeper learning curve&lt;/li&gt;
&lt;li&gt;Manual test maintenance compared to newer AI-driven platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Shift Left API&lt;/th&gt;
&lt;th&gt;Insomnia&lt;/th&gt;
&lt;th&gt;Bruno&lt;/th&gt;
&lt;th&gt;Hoppscotch&lt;/th&gt;
&lt;th&gt;ReadyAPI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;REST&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SOAP&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GraphQL&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Test Generation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAPI Import&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Mocking&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD Integration&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosted AI&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise Compliance&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No-code Automation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Which Tool Should You Choose?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose Shift Left API if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want AI to generate API tests&lt;/li&gt;
&lt;li&gt;Your APIs are defined using OpenAPI or Swagger&lt;/li&gt;
&lt;li&gt;You need enterprise automation&lt;/li&gt;
&lt;li&gt;You work with REST, SOAP and GraphQL&lt;/li&gt;
&lt;li&gt;You need CI/CD-ready automation&lt;/li&gt;
&lt;li&gt;Your organization requires self-hosted AI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;Choose Insomnia if *&lt;/em&gt; you primarily need a developer-friendly API client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Bruno if&lt;/strong&gt; Git-first workflows are your priority.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Hoppscotch if&lt;/strong&gt; you want a lightweight browser-based tool.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Choose ReadyAPI if *&lt;/em&gt; your organization already relies on the SmartBear ecosystem and extensive SOAP testing.&lt;/p&gt;

&lt;p&gt;Read more comparsions &lt;a href="https://totalshiftleft.ai/compare" rel="noopener noreferrer"&gt;here &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Postman is still an excellent API client, but modern API testing increasingly demands automation, AI assistance, and seamless integration into CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;If your workflow still revolves around manually maintaining collections and scripts, it may be time to evaluate platforms that automate much of that work.&lt;/p&gt;

&lt;p&gt;For teams adopting shift-left testing practices, AI-generated tests, contract validation, and spec-driven automation can significantly reduce maintenance effort while improving API quality.&lt;/p&gt;

&lt;p&gt;What API testing tool are you using in 2026? Share your experience in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>backend</category>
      <category>testing</category>
    </item>
    <item>
      <title>JWT Authentication, Explained by Actually Running One (No Setup)</title>
      <dc:creator>Parveen Kumari</dc:creator>
      <pubDate>Sat, 16 May 2026 13:08:14 +0000</pubDate>
      <link>https://dev.to/pku_bd13f856f0/jwt-authentication-explained-by-actually-running-one-no-setup-3l70</link>
      <guid>https://dev.to/pku_bd13f856f0/jwt-authentication-explained-by-actually-running-one-no-setup-3l70</guid>
      <description>&lt;p&gt;Decode a real JWT, exploit alg:none in 30 seconds, and learn exactly what to test in your own auth — all in your browser against a live sandbox&lt;/p&gt;

&lt;p&gt;Most JWT tutorials show you a diagram and call it a day. This one is different: every example runs against a real sandbox API in your browser, so you can decode tokens, exploit &lt;code&gt;alg: none&lt;/code&gt;, and watch a server actually reject (or accept) what you throw at it.&lt;/p&gt;

&lt;p&gt;If you've ever signed off on a JWT implementation without being 100% sure what the library is doing under the hood — this is for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What a JWT actually is&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A JWT (JSON Web Token, pronounced "jot") is a signed, self-contained string that carries claims about a user, used to authenticate requests.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Self-contained&lt;/em&gt; is the magic word. The server doesn't need to look up a session — the token itself has the user info plus a signature proving it hasn't been tampered with. The server just verifies the signature and trusts the claims.&lt;/p&gt;

&lt;p&gt;** The three parts&lt;/p&gt;

&lt;p&gt;A JWT is three Base64URL-encoded segments separated by dots:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiQWxpY2UifQ.sig_bytes_here
↑ header              ↑ payload                              ↑ signature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Decode the first two and you get JSON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Header:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Payload (claims):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user-123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alice@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1712345678&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1712349278&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Signature:&lt;/strong&gt; &lt;code&gt;HMAC-SHA256(header.payload, secret)&lt;/code&gt; — or an RSA/ECDSA signature for asymmetric algorithms.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Anyone can decode a JWT. The payload is &lt;em&gt;signed&lt;/em&gt;, not &lt;em&gt;encrypted&lt;/em&gt;. Never put secrets (passwords, credit-card numbers, anything you'd be sad to see in a log) in a JWT.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Standard claims (RFC 7519)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Claim&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iss&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Issuer — who created the token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sub&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Subject — who the token is about (user ID)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aud&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Audience — who the token is for&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;exp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Expiration — Unix timestamp after which the token is invalid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nbf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Not Before — Unix timestamp before which it's invalid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Issued At — when it was created&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jti&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JWT ID — unique identifier for revocation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plus any custom claims your app needs: &lt;code&gt;role&lt;/code&gt;, &lt;code&gt;tenant_id&lt;/code&gt;, &lt;code&gt;permissions&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run a login and get a real token
&lt;/h2&gt;

&lt;p&gt;Here's the login request — &lt;code&gt;POST /auth/login&lt;/code&gt; against the public sandbox:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST https://demo.totalshiftleft.ai/auth/login
Content-Type: application/json

{
  "email": "demo@totalshiftleft.ai",
  "password": "demo123"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"access_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOi..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"refresh_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOi..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to actually run it and see the real token come back?&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://totalshiftleft.ai/learn/authentication/jwt-authentication" rel="noopener noreferrer"&gt;Run this live in your browser — no signup&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then call a protected endpoint with the token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://demo.totalshiftleft.ai/api/v1/me
Authorization: Bearer eyJhbGciOi...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drop the &lt;code&gt;Authorization&lt;/code&gt; header and you get a 401. That's the whole flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the server verifies a token
&lt;/h2&gt;

&lt;p&gt;On every request, the server runs through this checklist:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;Split the token into header, payload, signature.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check &lt;code&gt;alg&lt;/code&gt; matches the expected algorithm — reject &lt;code&gt;none&lt;/code&gt; explicitly.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recompute the signature&lt;/strong&gt; over &lt;code&gt;header.payload&lt;/code&gt; using the secret/public key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare&lt;/strong&gt; the computed signature to the provided one — in constant time.&lt;/li&gt;
&lt;li&gt;Parse the payload. Check &lt;code&gt;exp&lt;/code&gt; is in the future and &lt;code&gt;nbf&lt;/code&gt; is in the past.&lt;/li&gt;
&lt;li&gt;Optionally check &lt;code&gt;iss&lt;/code&gt;, &lt;code&gt;aud&lt;/code&gt;, &lt;code&gt;jti&lt;/code&gt; against a revocation list.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Only now&lt;/em&gt; treat the claims as trusted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Skipping step 3 or 4 is the classic vulnerability — and several major libraries have shipped it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seven JWT vulnerabilities you should be able to test for
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;alg: none&lt;/code&gt;.&lt;/strong&gt; Attacker changes the header to &lt;code&gt;{"alg":"none"}&lt;/code&gt;, drops the signature, and forges any payload. Only works if the library accepts &lt;code&gt;none&lt;/code&gt;. Reject it explicitly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. &lt;code&gt;alg&lt;/code&gt; confusion (RS256 → HS256).&lt;/strong&gt; Attacker flips &lt;code&gt;alg&lt;/code&gt; from &lt;code&gt;RS256&lt;/code&gt; to &lt;code&gt;HS256&lt;/code&gt; and signs with the server's &lt;em&gt;public&lt;/em&gt; key as if it were the HMAC secret. Naive libraries verify it as HMAC against the public key (which is, well, public) and accept it. Always pin the algorithm server-side. Never trust the header's &lt;code&gt;alg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Weak HMAC secrets.&lt;/strong&gt; 8-character secrets can be brute-forced offline from a single valid token. Use ≥256 bits of entropy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Long expirations.&lt;/strong&gt; &lt;code&gt;exp&lt;/code&gt; 30 days out means a stolen token is usable for 30 days. Access tokens should live ~15 minutes; long-lived refresh tokens do the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. No revocation.&lt;/strong&gt; JWTs are stateless by design — which makes revocation hard. Mitigations: short expiry + refresh tokens, &lt;code&gt;jti&lt;/code&gt; blacklist, or per-user "tokens issued before X are invalid" timestamps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Storing JWTs in &lt;code&gt;localStorage&lt;/code&gt;.&lt;/strong&gt; Vulnerable to XSS. Use &lt;code&gt;httpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt;, &lt;code&gt;SameSite&lt;/code&gt; cookies for browser clients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Generous clock skew.&lt;/strong&gt; A 5-minute window is fine. A 24-hour window is a vulnerability.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually test
&lt;/h2&gt;

&lt;p&gt;If you're writing tests for a JWT-protected API — or QA-ing one — here's the checklist I actually use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Happy paths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Login with valid creds → 200 with &lt;code&gt;access_token&lt;/code&gt;, &lt;code&gt;refresh_token&lt;/code&gt;, &lt;code&gt;expires_in&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Protected endpoint with valid token → 200.&lt;/li&gt;
&lt;li&gt;Token includes expected claims (&lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;role&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Authentication negatives
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;Authorization&lt;/code&gt; header → 401.&lt;/li&gt;
&lt;li&gt;Wrong scheme (&lt;code&gt;Basic&lt;/code&gt; instead of &lt;code&gt;Bearer&lt;/code&gt;) → 401.&lt;/li&gt;
&lt;li&gt;Malformed token (missing a segment) → 401.&lt;/li&gt;
&lt;li&gt;Expired token (&lt;code&gt;exp&lt;/code&gt; in the past) → 401 with a distinguishable code (e.g., &lt;code&gt;TOKEN_EXPIRED&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Not-yet-valid token (&lt;code&gt;nbf&lt;/code&gt; in the future) → 401.&lt;/li&gt;
&lt;li&gt;Token signed with the wrong secret → 401.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alg: none&lt;/code&gt; token → 401. &lt;strong&gt;This is a security-critical test — most JWT libraries have shipped this bug at some point.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Tampered payload (modify a claim, keep the old signature) → 401.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Authorization negatives
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Valid token with &lt;code&gt;role: user&lt;/code&gt; hitting an admin endpoint → 403.&lt;/li&gt;
&lt;li&gt;Valid token but &lt;code&gt;tenant_id&lt;/code&gt; doesn't own the resource → 403 or 404 (document which — both are defensible).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Edge cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Token issued by a different &lt;code&gt;iss&lt;/code&gt; → 401.&lt;/li&gt;
&lt;li&gt;Token with &lt;code&gt;aud&lt;/code&gt; not matching this API → 401.&lt;/li&gt;
&lt;li&gt;Token with a huge payload (10 KB of custom claims) → should work or 413.&lt;/li&gt;
&lt;li&gt;Multiple &lt;code&gt;Authorization&lt;/code&gt; headers → document the behavior (most stacks take the first).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Refresh flow
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Valid refresh token → new access + refresh pair; old refresh token now invalid.&lt;/li&gt;
&lt;li&gt;Re-using an old refresh token → 401 (detects token theft).&lt;/li&gt;
&lt;li&gt;Refresh token after the user changes their password → 401. A password change should invalidate tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pen-tester checklist (steal this)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Copy the JWT, change &lt;code&gt;alg&lt;/code&gt; to &lt;code&gt;none&lt;/code&gt;, remove the signature — does it still work? If yes: critical bug.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;alg&lt;/code&gt; is &lt;code&gt;RS256&lt;/code&gt;, try resigning with &lt;code&gt;HS256&lt;/code&gt; using the server's public key — does it work? If yes: critical bug.&lt;/li&gt;
&lt;li&gt;Decode the payload. Anything that shouldn't be there (passwords, PII, internal IDs that leak architecture)? Report as data exposure.&lt;/li&gt;
&lt;li&gt;Does the token include a &lt;code&gt;jti&lt;/code&gt;? If not, revocation is likely not implemented.&lt;/li&gt;
&lt;li&gt;Set the system clock past &lt;code&gt;exp&lt;/code&gt; — does the token still work? Clock-skew vulnerability.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Reading about JWTs is fine. Watching one fail validation in real time is better.&lt;/p&gt;

&lt;p&gt;The full lesson — with a runnable login, a real protected endpoint, and the &lt;code&gt;alg: none&lt;/code&gt; exploit live against a sandbox — is here, free, no signup:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://totalshiftleft.ai/learn/authentication/jwt-authentication" rel="noopener noreferrer"&gt;Learn JWT Authentication — runnable lesson&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's part of a free 32-lesson API testing course covering REST, GraphQL, SOAP, OAuth2, contract testing, and AI-assisted testing. Every lesson has a runnable example against a live sandbox: &lt;a href="https://totalshiftleft.ai/learn" rel="noopener noreferrer"&gt;totalshiftleft.ai/learn&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;What's your favorite JWT footgun in production? Drop it in the comments — I'm collecting them for the next post on refresh-token rotation patterns.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>ai</category>
      <category>api</category>
    </item>
  </channel>
</rss>
