<?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: Mahesha Dinushan Heenatigala</title>
    <description>The latest articles on DEV Community by Mahesha Dinushan Heenatigala (@maheshadinu).</description>
    <link>https://dev.to/maheshadinu</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%2F3646769%2F7584922c-0929-46a4-99b0-4b5133cb84e4.jpeg</url>
      <title>DEV Community: Mahesha Dinushan Heenatigala</title>
      <link>https://dev.to/maheshadinu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maheshadinu"/>
    <language>en</language>
    <item>
      <title>Securing My Stack: Features and Experience Integrating Asgardeo, Ballerina, and Choreo</title>
      <dc:creator>Mahesha Dinushan Heenatigala</dc:creator>
      <pubDate>Thu, 04 Dec 2025 16:49:03 +0000</pubDate>
      <link>https://dev.to/maheshadinu/securing-my-stack-features-and-experience-integrating-asgardeo-ballerina-and-choreo-43dm</link>
      <guid>https://dev.to/maheshadinu/securing-my-stack-features-and-experience-integrating-asgardeo-ballerina-and-choreo-43dm</guid>
      <description>&lt;h2&gt;
  
  
  🔑 Securing My Stack: Features and Experience with WSO2 Asgardeo
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🚀 Introduction: Building a Secure Microservice Gateway
&lt;/h2&gt;

&lt;p&gt;For my Secure Gateway Project—integrating a &lt;strong&gt;React Frontend&lt;/strong&gt; with a &lt;strong&gt;Ballerina Backend&lt;/strong&gt; on &lt;strong&gt;WSO2 Choreo&lt;/strong&gt;—I chose &lt;strong&gt;WSO2 Asgardeo&lt;/strong&gt; as the core Identity Provider (IDP). My goal was to leverage a modern, cloud-native Identity and Access Management (CIAM) solution that seamlessly handles the complexities of OAuth 2.0 and OpenID Connect (OIDC).&lt;/p&gt;

&lt;p&gt;This post details the specific features of Asgardeo I utilized and explores my hands-on experience integrating them into a secure microservice architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Architecture at a Glance
&lt;/h2&gt;

&lt;p&gt;Our simple stack provided layered security:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Security Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Frontend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;React (Vite)&lt;/td&gt;
&lt;td&gt;Initiates the OIDC flow and handles user session.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backend API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ballerina&lt;/td&gt;
&lt;td&gt;Contains protected business logic, secured by a JWT Validator.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Choreo Connect&lt;/td&gt;
&lt;td&gt;The first security layer; validates the JWT before routing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IDP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Asgardeo&lt;/td&gt;
&lt;td&gt;Issues the authenticated &lt;strong&gt;JSON Web Token (JWT)&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💻 Feature 1: Seamless SPA Setup and PKCE
&lt;/h2&gt;

&lt;p&gt;The developer experience for setting up the client application in the &lt;strong&gt;Asgardeo Console&lt;/strong&gt; was remarkably straightforward.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Experience: Intuitive and Secure Configuration
&lt;/h3&gt;

&lt;p&gt;I defined my application as a &lt;strong&gt;Single Page Application (SPA)&lt;/strong&gt;. This choice instantly configured the necessary security protocol: the &lt;strong&gt;Authorization Code flow with PKCE (Proof Key for Code Exchange)&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PKCE is Critical:&lt;/strong&gt; For public clients like an SPA (which cannot securely store a Client Secret), PKCE is essential to prevent code interception attacks. Asgardeo automatically mandates this when the SPA template is chosen, offering immediate security without manual configuration struggle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redirect Management:&lt;/strong&gt; Configuring the &lt;strong&gt;Authorized Redirect URLs&lt;/strong&gt; (e.g., &lt;code&gt;https://&amp;lt;my-app-url&amp;gt;/callback&lt;/code&gt;) was simple and clear, which is crucial for preventing authentication flow breakage.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛡️ Feature 2: The React SDK (&lt;code&gt;@asgardeo/auth-react&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Integrating the actual login/logout functionality was significantly simplified using the official Asgardeo SDK for React.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Experience: Token Reliability in a Reactive App
&lt;/h3&gt;

&lt;p&gt;The SDK provided the high-level hooks and context necessary to manage the user session:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;useAuthContext&lt;/code&gt; Hook:&lt;/strong&gt; This hook provided instant access to the user's authentication state (&lt;code&gt;isAuthenticated&lt;/code&gt;) and session data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Reliability:&lt;/strong&gt; I learned a crucial distinction: relying on the reactive state for the access token can lead to race conditions. The SDK's &lt;strong&gt;&lt;code&gt;getAccessToken()&lt;/code&gt;&lt;/strong&gt; function, which is an asynchronous method, proved &lt;strong&gt;absolutely reliable&lt;/strong&gt; for fetching the final, valid token just before initiating the API call. This guaranteed that the &lt;strong&gt;&lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;&lt;/strong&gt; header was always current and complete.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;javascript&lt;br&gt;
// Reliable way to fetch the token just before the API call&lt;br&gt;
const fetchData = async () =&amp;gt; {&lt;br&gt;
  const token = await getAccessToken();&lt;br&gt;
  const apiResponse = await fetch(apiUrl, {&lt;br&gt;
    headers: {&lt;br&gt;
      Authorization: `Bearer ${token}`&lt;br&gt;
    }&lt;br&gt;
  });&lt;br&gt;
  // ... handle response&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 Feature 3: JWT Access Token Generation and Validation
&lt;/h2&gt;

&lt;p&gt;The core function of Asgardeo was to issue a token that my backend could trust. This feature led to my deepest technical investigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Experience: Uncovering the Issuer Conflict
&lt;/h3&gt;

&lt;p&gt;My Ballerina API required a &lt;strong&gt;JWT (JSON Web Token)&lt;/strong&gt; for validation. Asgardeo issued a valid JWT, but its content presented a challenge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problematic Claim:&lt;/strong&gt; The &lt;strong&gt;Issuer (&lt;code&gt;iss&lt;/code&gt;)&lt;/strong&gt; claim in the generated JWT contained the full token endpoint URL (&lt;code&gt;https://.../oauth2/token&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Standard Expectation:&lt;/strong&gt; My validators were initially configured to expect the &lt;strong&gt;base URL&lt;/strong&gt; (&lt;code&gt;https://.../t/maheshadinushan&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This experience demonstrated the importance of inspecting the &lt;strong&gt;actual token payload&lt;/strong&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%2Fvugfw12dpaotdgeqoc10.jpeg" 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%2Fvugfw12dpaotdgeqoc10.jpeg" alt="Image of JWT token structure" width="800" height="552"&gt;&lt;/a&gt;&lt;br&gt;
:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson Learned:&lt;/strong&gt; While documentation suggests the standard base URL, I had to configure my API Gateway (Choreo) and my Ballerina service to &lt;strong&gt;trust the full endpoint URL&lt;/strong&gt; (&lt;code&gt;.../oauth2/token&lt;/code&gt;) to match the exact token generated by Asgardeo. This adaptability was key to solving the &lt;strong&gt;JWT Validator Deadlock&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>security</category>
      <category>ballerina</category>
      <category>wso2</category>
    </item>
  </channel>
</rss>
