<?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: Savinda</title>
    <description>The latest articles on DEV Community by Savinda (@savinda_premachandra).</description>
    <link>https://dev.to/savinda_premachandra</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%2F2529115%2Fa86d6e21-3133-42d3-a849-899c19f89701.png</url>
      <title>DEV Community: Savinda</title>
      <link>https://dev.to/savinda_premachandra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/savinda_premachandra"/>
    <language>en</language>
    <item>
      <title>From Control Plane to KRO: A Journey Into Kubernetes Extensibility</title>
      <dc:creator>Savinda</dc:creator>
      <pubDate>Wed, 06 Aug 2025 08:18:40 +0000</pubDate>
      <link>https://dev.to/savinda_premachandra/from-control-plane-to-kro-a-journey-into-kubernetes-extensibility-5don</link>
      <guid>https://dev.to/savinda_premachandra/from-control-plane-to-kro-a-journey-into-kubernetes-extensibility-5don</guid>
      <description>&lt;p&gt;Kubernetes has revolutionized how we deploy and manage infrastructure. But with great power comes great complexity. If you've ever struggled with Custom Resource Definitions (CRDs), hand-rolled controllers, or tangled YAML, you're not alone. This post sets the stage for KRO (Kube Resource Orchestrator)—a project from Google, Microsoft, and AWS—by walking you through how Kubernetes really works under the hood and why KRO is here to save your day.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Kubernetes Works – The Control Plane
&lt;/h2&gt;

&lt;p&gt;The Kubernetes control plane is the brain of the cluster. It consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Server: The front door to the cluster. Everything talks to this.&lt;/li&gt;
&lt;li&gt;etcd: A key-value store that remembers the entire cluster state.&lt;/li&gt;
&lt;li&gt;Controller Manager: Ensures reality matches the desired state.&lt;/li&gt;
&lt;li&gt;Scheduler: Assigns pods to appropriate nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Extending Kubernetes with CRDs
&lt;/h2&gt;

&lt;p&gt;Kubernetes is declarative. You declare what you want, and the system figures out how to do it. But what if you want to define your own resource types?&lt;/p&gt;

&lt;p&gt;That’s where CRDs (Custom Resource Definitions) come in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: my.example.com/v1
kind: App
metadata:
    name: demo
spec:
    release: 1.0.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why CRDs Alone Aren’t Enough
&lt;/h2&gt;

&lt;p&gt;You need a controller (or "operator") to make CRDs come alive. A controller watches for objects like app, then acts—e.g., provisioning infrastructure, updating apps, etc.&lt;/p&gt;

&lt;p&gt;Problem? Controllers are hard to write.&lt;/p&gt;

&lt;p&gt;You typically need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code (often in Go)&lt;/li&gt;
&lt;li&gt;Frameworks like Kubebuilder or Operator SDK&lt;/li&gt;
&lt;li&gt;Deep knowledge of Kubernetes APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Common Pain Points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;overloaded API server from poorly written watches&lt;/li&gt;
&lt;li&gt;etcd bloat from unused CRDs&lt;/li&gt;
&lt;li&gt;Complex reconcilers and ordering logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Tools/Operator Like KCC, ACK, and ASO Aren’t Enough on Their Own
&lt;/h2&gt;

&lt;p&gt;While tools like KCC (Google), ACK (AWS), and ASO (Azure) let you manage cloud resources using Kubernetes CRDs, they’re tightly coupled to their respective clouds. &lt;/p&gt;

&lt;p&gt;They’re great for cloud integration, but not for composing reusable APIs or simplifying multi-step infrastructure workflows.&lt;/p&gt;

&lt;p&gt;That’s where KRO steps in—it’s the glue that turns raw CRDs into full-blown platform APIs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing KRO (Kube Resource Orchestrator)
&lt;/h2&gt;

&lt;p&gt;KRO is a Kubernetes‑native, cloud‑agnostic framework that lets platform teams define resource bundles as reusable APIs via a ResourceGraphDefinition (RGD). KRO helps you build a self-service developer platform that works across clouds by leveraging existing operators (KCC, ACK, ASO)&lt;/p&gt;

&lt;p&gt;Platform teams define defaults and hide complexity, letting developers consume a clean interface.&lt;/p&gt;

&lt;p&gt;When applied, KRO:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamically creates a CRD for your API.&lt;/li&gt;
&lt;li&gt;Sets up a controller to manage instances of that CRD.&lt;/li&gt;
&lt;li&gt;Manages ordering, dependencies via CEL expressions.&lt;/li&gt;
&lt;li&gt;Handles both Kubernetes-native and cloud resources (via ACK, KCC, ASO).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Use-cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Provisioning a GKE/AKS/EKS cluster + IAM &lt;/li&gt;
&lt;li&gt;Deploying web apps combined with cloud databases and load balancers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How KRO Works: Architecture
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Define a ResourceGraphDefinition (RGD) – schema + resource templates + dependency definitions.&lt;/li&gt;
&lt;li&gt;KRO validates the RGD, creates the CRD, and deploys a micro‑controller for that custom type.&lt;/li&gt;
&lt;li&gt;A user instantiates your API object (like WebApp or GKECluster), and KRO generates underlying Kubernetes objects in the correct order.&lt;/li&gt;
&lt;li&gt;Lifecycle is managed automatically—updates, reconciliation, status reporting. &lt;/li&gt;
&lt;/ul&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%2Fnvlvkspz79wrnk83ul6u.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%2Fnvlvkspz79wrnk83ul6u.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;KRO builds on everything that makes Kubernetes powerful—and fixes what makes it painful. Before you dive into building with KRO, it's essential to understand the journey from kubectl to CRDs to controllers. Once you do, you’ll see why KRO isn’t just a new tool—it’s a new way of thinking about Kubernetes extensibility.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>platformengineering</category>
      <category>devops</category>
      <category>kro</category>
    </item>
    <item>
      <title>Building a JWT-Aware Reverse Proxy in Go for Tiered API Access</title>
      <dc:creator>Savinda</dc:creator>
      <pubDate>Tue, 17 Jun 2025 15:45:56 +0000</pubDate>
      <link>https://dev.to/savinda_premachandra/-1kh8</link>
      <guid>https://dev.to/savinda_premachandra/-1kh8</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/savinda_premachandra/building-a-jwt-aware-reverse-proxy-in-go-for-tiered-api-access-1i9n" class="crayons-story__hidden-navigation-link"&gt;Building a JWT-Aware Reverse Proxy in Go for Tiered API Access&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/savinda_premachandra" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F2529115%2Fa86d6e21-3133-42d3-a849-899c19f89701.png" alt="savinda_premachandra profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/savinda_premachandra" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Savinda
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Savinda
                
              
              &lt;div id="story-author-preview-content-2586298" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/savinda_premachandra" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F2529115%2Fa86d6e21-3133-42d3-a849-899c19f89701.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Savinda&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/savinda_premachandra/building-a-jwt-aware-reverse-proxy-in-go-for-tiered-api-access-1i9n" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 12 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/savinda_premachandra/building-a-jwt-aware-reverse-proxy-in-go-for-tiered-api-access-1i9n" id="article-link-2586298"&gt;
          Building a JWT-Aware Reverse Proxy in Go for Tiered API Access
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/go"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;go&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/savinda_premachandra/building-a-jwt-aware-reverse-proxy-in-go-for-tiered-api-access-1i9n" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/savinda_premachandra/building-a-jwt-aware-reverse-proxy-in-go-for-tiered-api-access-1i9n#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>programming</category>
      <category>go</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building a JWT-Aware Reverse Proxy in Go for Tiered API Access</title>
      <dc:creator>Savinda</dc:creator>
      <pubDate>Thu, 12 Jun 2025 10:21:10 +0000</pubDate>
      <link>https://dev.to/savinda_premachandra/building-a-jwt-aware-reverse-proxy-in-go-for-tiered-api-access-1i9n</link>
      <guid>https://dev.to/savinda_premachandra/building-a-jwt-aware-reverse-proxy-in-go-for-tiered-api-access-1i9n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this blog post, I’ll walk you through a small proof-of-concept project I built: a reverse proxy in Go that routes requests to different backend services based on the &lt;code&gt;tier&lt;/code&gt; claim in a JWT token.&lt;/p&gt;

&lt;p&gt;The proxy uses RSA public/private key cryptography to validate the JWT, then forwards the request to either a &lt;code&gt;free-tier&lt;/code&gt; or &lt;code&gt;subscribed-tier&lt;/code&gt; backend. The whole setup runs in containers on Minikube. It’s a great way to understand how reverse proxies and JWT authentication can work together &lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;I wanted to understand how reverse proxies work at a lower level and how JWTs could be used to manage access control between service tiers. I also wanted something I could deploy easily with Docker and Minikube, so it’s very infrastructure- and developer-friendly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;Here's what the system looks like:&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%2Fb398csfjyohj72h02qh7.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%2Fb398csfjyohj72h02qh7.png" alt="Architecture" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The client sends a request with a JWT in the Authorization header&lt;/li&gt;
&lt;li&gt;The reverse proxy verifies the JWT using a public RSA key&lt;/li&gt;
&lt;li&gt;It extracts the &lt;code&gt;tier&lt;/code&gt; claim (e.g., "free" or "subscribed")&lt;/li&gt;
&lt;li&gt;Based on that, it routes the request to the appropriate backend service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All services are containerized and deployed in Minikube.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Components with Code Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔁 Reverse Proxy (Go)
&lt;/h3&gt;

&lt;p&gt;Here's how the reverse proxy is created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;httputil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSingleHostReverseProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModifyResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Response from backend: %d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Custom &lt;code&gt;Director&lt;/code&gt; logic modifies the request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Director&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-Forwarded-For"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteAddr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scheme&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Forwarding request to: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Routing rules come from a YAML config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;free&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://free-tier-service:9000&lt;/span&gt;
  &lt;span class="na"&gt;subscribed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://subscribed-tier-service:9000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is loaded in Go as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Routes&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`yaml:"routes"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔐 JWT Auth
&lt;/h3&gt;

&lt;p&gt;JWT tokens are RSA-signed and validated using the public key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;validateJWT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapClaims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tokenString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;extractToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pubKeyData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ioutil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"public.pem"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pubKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseRSAPublicKeyFromPEM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pubKeyData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pubKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Claims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapClaims&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Token is extracted like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;extractToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bearer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bearer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bearer "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧭 Routing Logic
&lt;/h3&gt;

&lt;p&gt;Once the tier is extracted, routing is handled like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;validateJWT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"tier"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;targetURL&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;routeConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reverseProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeHTTP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Backends
&lt;/h3&gt;

&lt;p&gt;Two simple backend services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;free_home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;msg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello Free-tier User 🌱&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subscribed_home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;msg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello Subscribed User 🚀&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each backend is a basic HTTP server with a unique response to verify routing.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Common Real-World Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SaaS platforms with "free" vs. "premium" tiers controlling access to APIs&lt;/li&gt;
&lt;li&gt;Content streaming services that serve different quality or features based on the user's subscription&lt;/li&gt;
&lt;li&gt;E-learning portals gating content behind subscriptions or course enrollments&lt;/li&gt;
&lt;li&gt;Mobile backend systems offering tier-based feature access&lt;/li&gt;
&lt;li&gt;Enterprise APIs that segment functionality by internal department or external partner level&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🌐 Real-World Considerations
&lt;/h2&gt;

&lt;p&gt;Here’s where things get a bit more nuanced 🔍:&lt;/p&gt;

&lt;p&gt;In a real-world system, user identity and tier access should be validated and persisted both at the authentication system and on the backend services.&lt;/p&gt;

&lt;h4&gt;
  
  
  JWT Signature &amp;amp; PKI
&lt;/h4&gt;

&lt;p&gt;Since JWTs are signed using PKI (public/private key cryptography), any attempt by a user to modify the token’s claims (like the tier) will break the signature verification. This means:&lt;/p&gt;

&lt;p&gt;The backend can (and should) verify the JWT signature itself to ensure the token is genuine and untampered.&lt;/p&gt;

&lt;p&gt;If the signature check fails, the request must be rejected.&lt;/p&gt;

&lt;p&gt;This prevents users from forging or altering their JWTs to escalate privileges.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Backend Validation Matters
&lt;/h4&gt;

&lt;p&gt;Even though the proxy validates the JWT, backends should never blindly trust the proxy. The proxy can be bypassed if someone calls the backend API directly.&lt;/p&gt;

&lt;p&gt;Backends should perform their own JWT validation or check with a centralized auth system.&lt;/p&gt;

&lt;h4&gt;
  
  
  Token Freshness and Revocation
&lt;/h4&gt;

&lt;p&gt;JWTs are stateless, meaning once issued, they carry claims until expiry.&lt;/p&gt;

&lt;p&gt;If user privileges change (e.g., downgrade from subscribed to free), the backend needs a way to invalidate old tokens or verify claims against a database.&lt;/p&gt;

&lt;p&gt;This can be done with short token lifetimes, token revocation lists, or real-time claim checking.&lt;/p&gt;

&lt;h4&gt;
  
  
  Proxy as a Single Point of Failure
&lt;/h4&gt;

&lt;p&gt;The proxy could become a bottleneck or single point of failure.&lt;/p&gt;

&lt;p&gt;For production, consider dedicated API gateways (e.g., Kong, Ambassador, Istio) that offer robust features like rate limiting, observability, and retries.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✋ Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No HTTPS (for now)&lt;/li&gt;
&lt;li&gt;Static public key loading (no hot reload or key rotation)&lt;/li&gt;
&lt;li&gt;Basic error handling&lt;/li&gt;
&lt;li&gt;No rate limiting, observability, or distributed tracing&lt;/li&gt;
&lt;li&gt;No token revocation or refresh support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still, it’s a clean and focused implementation that illustrates the core ideas beautifully.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚧 Source Code &amp;amp; Deployment
&lt;/h2&gt;

&lt;p&gt;You can find the full source code on my &lt;a href="https://github.com/savindapremachandra/JWT-Aware-Reverse-Proxy/tree/main/free-api" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To deploy it in Minikube:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build the Docker images for the proxy and backends&lt;/li&gt;
&lt;li&gt;Apply the Kubernetes manifests&lt;/li&gt;
&lt;li&gt;Test with curl and different JWTs&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;This was a fun project to build and learn from. If you’re new to Go or want to understand JWT-based routing and reverse proxy logic, I highly recommend trying something like this. Yes, it’s basic — but it’s real, working code, and you’ll walk away with actual insights.&lt;/p&gt;

&lt;p&gt;Let me know what you think! Feedback is welcome — just keep in mind that this was built for educational purposes, not production 🚀&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>Behind the Code: A Simple Look at the Software Supply Chain</title>
      <dc:creator>Savinda</dc:creator>
      <pubDate>Fri, 16 May 2025 03:40:55 +0000</pubDate>
      <link>https://dev.to/savinda_premachandra/behind-the-code-a-simple-look-at-the-software-supply-chain-5065</link>
      <guid>https://dev.to/savinda_premachandra/behind-the-code-a-simple-look-at-the-software-supply-chain-5065</guid>
      <description>&lt;p&gt;Whether you're building your first web app or deploying containers in the cloud, you're already using a software supply chain — even if you’ve never heard of it before. This blog post is a beginner-friendly introduction to what the software supply chain is, why it matters, and how it can affect your code and security. No complex jargon, no deep dives — just the core concepts, explained in simple terms, with a few memes along the way to keep things fun.&lt;/p&gt;

&lt;p&gt;Modern software development is rarely about building everything from scratch. Instead, we assemble applications using open-source libraries, external APIs, containers, CI/CD tools, and cloud platforms. This network of components and tools is known as the software supply chain.&lt;/p&gt;

&lt;p&gt;But while this speeds up innovation, it also introduces risk: if any part of the chain is compromised — intentionally or not — the whole system can be affected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example
&lt;/h2&gt;

&lt;p&gt;Let’s say you're building a Node.js app and install a package: &lt;code&gt;npm install express&lt;/code&gt;&lt;br&gt;
What you might miss is that express pulls in multiple dependencies, and one of those could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;outdated and vulnerable&lt;/li&gt;
&lt;li&gt;or worse, a trojan placed by a malicious actor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how supply chain attacks happen and that’s why software supply chain security is now a top priority for developers and organizations alike.&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%2F4i6n98fywfue7mzqhwv6.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%2F4i6n98fywfue7mzqhwv6.png" alt="Image description" width="705" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It Matters
&lt;/h2&gt;

&lt;p&gt;Supply chain attacks have become a favored strategy for attackers, as demonstrated in high-profile incidents like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SolarWinds (2020)&lt;/li&gt;
&lt;li&gt;Log4Shell (2021)&lt;/li&gt;
&lt;li&gt;Event-Stream NPM package (2018)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These weren’t just bugs — they were exploits hiding in third-party tools or dependencies. These incidents have pushed the tech world to rethink how software is built and secured.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Protect the Software Supply Chain
&lt;/h2&gt;

&lt;p&gt;Securing your supply chain is about visibility and control. Here’s how to get started:&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Tool/Practice&lt;/u&gt;&lt;br&gt;
SBOMs (Software Bill of Materials) ==&amp;gt;  Know exactly what's in your build&lt;br&gt;
Sigstore (cosign, Fulcio)  ==&amp;gt;  Sign and verify artifacts&lt;br&gt;
Snyk, Trivy, Grype  ==&amp;gt; Scan for vulnerabilities in code and containers&lt;br&gt;
Provenance (in-toto, SLSA)  ==&amp;gt; Track how software was built and by whom&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%2Fi2uszd8l0fgs3ztlkv5b.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%2Fi2uszd8l0fgs3ztlkv5b.png" alt="Image description" width="496" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;If you're deploying software - whether it's to a serverless platform, a Kubernetes cluster, or an IoT device - you're part of the software supply chain.&lt;/p&gt;

&lt;p&gt;Don’t assume trust.&lt;br&gt;
Verify every layer.&lt;br&gt;
Automate scanning and signing where possible.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>supplychainsecurity</category>
      <category>devops</category>
      <category>cybersecurity</category>
    </item>
  </channel>
</rss>
