<?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: Aswani Nayak</title>
    <description>The latest articles on DEV Community by Aswani Nayak (@aswani_nayak_cdcb2fe8ee38).</description>
    <link>https://dev.to/aswani_nayak_cdcb2fe8ee38</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%2F3937023%2Fcf9892f5-ba86-45f8-8056-5a5f47d13ea7.jpg</url>
      <title>DEV Community: Aswani Nayak</title>
      <link>https://dev.to/aswani_nayak_cdcb2fe8ee38</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aswani_nayak_cdcb2fe8ee38"/>
    <language>en</language>
    <item>
      <title>From Prompting to Production: A Practical Framework for AI-Assisted Software Development</title>
      <dc:creator>Aswani Nayak</dc:creator>
      <pubDate>Wed, 22 Jul 2026 16:06:22 +0000</pubDate>
      <link>https://dev.to/aswani_nayak_cdcb2fe8ee38/from-prompting-to-production-a-practical-framework-for-ai-assisted-software-development-37pp</link>
      <guid>https://dev.to/aswani_nayak_cdcb2fe8ee38/from-prompting-to-production-a-practical-framework-for-ai-assisted-software-development-37pp</guid>
      <description>&lt;p&gt;&lt;em&gt;How structured workflows, context engineering, and human oversight can transform AI from a coding assistant into a true engineering partner.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Generative AI is rapidly changing how software is built. While many development teams have experimented with AI-powered coding tools, the real challenge is not generating code—it's creating a repeatable process that produces reliable, high-quality outcomes.&lt;br&gt;
Recently, we conducted a hands-on workshop to explore how AI can support the complete software development lifecycle. Rather than using toy examples, the session focused on solving a real business problem while applying a structured AI-assisted development workflow.&lt;br&gt;
The result was more than just working software. We uncovered a practical framework that helps engineers collaborate effectively with AI agents, improve productivity, and maintain engineering quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Importance of Preparation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the key messages before the workshop was simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't start with code. Start with understanding.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Developers were encouraged to review business requirements in advance and become familiar with the problem domain before engaging coding agents.&lt;br&gt;
The goal was not simply to generate code faster, but to:&lt;br&gt;
    • Understand the business problem&lt;br&gt;
    • Validate AI-generated outputs&lt;br&gt;
    • Review implementation plans critically&lt;br&gt;
    • Verify test cases before implementation&lt;br&gt;
The workshop reinforced a crucial principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI can accelerate development, but humans remain responsible for understanding the business intent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Shift from Prompt Engineering to Context Engineering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many discussions about AI focus on writing the perfect prompt.&lt;br&gt;
The workshop highlighted something more important:&lt;br&gt;
Context engineering.&lt;br&gt;
The best outcomes occurred when engineers supplied:&lt;br&gt;
    • Business objectives&lt;br&gt;
    • Functional requirements&lt;br&gt;
    • Acceptance criteria&lt;br&gt;
    • System context&lt;br&gt;
    • Integration dependencies&lt;br&gt;
    • Architectural constraints&lt;br&gt;
    • Source-of-truth considerations&lt;br&gt;
Instead of immediately asking an AI agent to generate code, the team first provided comprehensive context and required the agent to fully understand the problem.&lt;br&gt;
For example:&lt;/p&gt;

&lt;p&gt;"I want to create a new Spring Boot application for a sales platform. Review the requirements, understand the acceptance criteria, and grill me on the requirements before creating an implementation plan."&lt;/p&gt;

&lt;p&gt;The business requirement explained that sellers needed a streamlined way to serve customers while relying on existing systems as the source of truth and avoiding unnecessary data duplication across platforms.&lt;br&gt;
Providing this level of context dramatically improved the quality of AI-generated plans, test cases, and implementation recommendations.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;"Grill Me"&lt;/strong&gt; Approach&lt;/p&gt;

&lt;p&gt;One of the most valuable concepts introduced during the workshop was the Grill Me technique.&lt;br&gt;
Rather than immediately proposing a solution, the AI agent is instructed to challenge assumptions and ask follow-up questions until it understands the requirements thoroughly.&lt;br&gt;
This transforms the agent from a code generator into a business analyst.&lt;br&gt;
Instead of guessing, the AI asks questions such as:&lt;br&gt;
    • What business outcome are we trying to achieve?&lt;br&gt;
    • What systems currently own the data?&lt;br&gt;
    • What are the integration constraints?&lt;br&gt;
    • What are the edge cases?&lt;br&gt;
    • What constitutes success?&lt;br&gt;
The objective is to eliminate ambiguity before planning or implementation begins.&lt;br&gt;
This often uncovers gaps in requirements long before development starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Structured AI Development Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The workshop followed a repeatable workflow designed to maximize AI effectiveness while preserving engineering discipline.&lt;/p&gt;

&lt;p&gt;Step 1: Requirement Discovery&lt;/p&gt;

&lt;p&gt;Provide the business requirements to the AI agent and ask it to fully understand the request before proposing a solution.&lt;br&gt;
The agent should review the available context and ask clarifying questions until requirements are well understood.&lt;br&gt;
Outcome: Clear understanding of the problem.&lt;/p&gt;

&lt;p&gt;Step 2: Implementation Planning&lt;/p&gt;

&lt;p&gt;Once requirements are understood, the AI generates:&lt;br&gt;
    • Solution architecture&lt;br&gt;
    • Technical approach&lt;br&gt;
    • Task breakdown&lt;br&gt;
    • Risks and assumptions&lt;br&gt;
Outcome: An actionable implementation plan.&lt;/p&gt;

&lt;p&gt;Step 3: Human Review&lt;/p&gt;

&lt;p&gt;Developers review the proposed plan and challenge assumptions.&lt;br&gt;
This is one of the most important phases in the process.&lt;br&gt;
The objective is not to approve the plan blindly but to verify:&lt;br&gt;
    • Architectural decisions&lt;br&gt;
    • Business alignment&lt;br&gt;
    • Missing requirements&lt;br&gt;
    • Technical feasibility&lt;br&gt;
Outcome: A validated implementation strategy.&lt;/p&gt;

&lt;p&gt;Step 4: Test-Driven Development&lt;/p&gt;

&lt;p&gt;Before writing code, the AI generates test cases.&lt;br&gt;
A structured TDD approach encourages engineers to define expected system behavior before implementation begins.&lt;br&gt;
Benefits include:&lt;br&gt;
    • Better requirement validation&lt;br&gt;
    • Improved quality&lt;br&gt;
    • Higher confidence in outcomes&lt;br&gt;
    • Earlier detection of requirement gaps&lt;br&gt;
Outcome: Comprehensive test coverage aligned to business needs.&lt;/p&gt;

&lt;p&gt;Step 5: Review Test Cases&lt;/p&gt;

&lt;p&gt;Developers review generated tests to ensure:&lt;br&gt;
    • Requirements are fully represented&lt;br&gt;
    • Edge cases are covered&lt;br&gt;
    • Acceptance criteria are addressed&lt;br&gt;
Strong test cases frequently reveal requirement gaps before implementation starts.&lt;br&gt;
Outcome: Reliable validation criteria.&lt;/p&gt;

&lt;p&gt;Step 6: Code Implementation&lt;/p&gt;

&lt;p&gt;After requirements, plans, and tests have been validated, the AI generates implementation code.&lt;br&gt;
Because the earlier phases established strong guardrails, implementation quality improves significantly.&lt;br&gt;
Outcome: Faster and more accurate development.&lt;/p&gt;

&lt;p&gt;Step 7: Validation and Refinement&lt;/p&gt;

&lt;p&gt;AI-generated code should never be considered production-ready by default.&lt;br&gt;
Engineers still perform:&lt;br&gt;
    • Code reviews&lt;br&gt;
    • Functional validation&lt;br&gt;
    • Performance verification&lt;br&gt;
    • Security checks&lt;br&gt;
    • Refinement and optimization&lt;br&gt;
Outcome: Production-quality software.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Approach Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Several important lessons emerged from the workshop.&lt;br&gt;
Requirements Quality Drives AI Quality&lt;br&gt;
The quality of the output is directly related to the quality of the requirements provided.&lt;br&gt;
Clear business requirements consistently produce:&lt;br&gt;
    • Better implementation plans&lt;br&gt;
    • Better test coverage&lt;br&gt;
    • Better code quality&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human Oversight Remains Critical&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI can accelerate analysis, planning, testing, and coding.&lt;br&gt;
It cannot replace engineering judgment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developers remain responsible for:&lt;/strong&gt;&lt;br&gt;
    • Understanding business intent&lt;br&gt;
    • Challenging assumptions&lt;br&gt;
    • Evaluating architecture&lt;br&gt;
    • Ensuring quality&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TDD Complements AI Extremely Well&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Generating tests before implementation creates a powerful partnership between developers and AI agents.&lt;br&gt;
Tests provide structure, define expectations, and reduce ambiguity.&lt;br&gt;
The combination of AI-generated tests and human review proved particularly effective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Process Matters More Than the Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the most surprising lessons was that success depended less on the specific AI model being used and more on the workflow surrounding it.&lt;br&gt;
Teams often focus on finding the "best" model.&lt;br&gt;
In reality, a disciplined process consistently delivered better results than relying on model capabilities alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Evolving Role of Developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Perhaps the most significant takeaway is that software engineering is evolving.&lt;br&gt;
Developers are spending less time writing repetitive code and more time:&lt;br&gt;
    • Understanding business problems&lt;br&gt;
    • Evaluating solutions&lt;br&gt;
    • Reviewing AI-generated outputs&lt;br&gt;
    • Designing systems&lt;br&gt;
    • Defining quality standards&lt;br&gt;
    • Making architectural decisions&lt;br&gt;
The most valuable engineering skill is no longer typing code quickly.&lt;br&gt;
It is providing the right context, asking the right questions, and validating the right outcomes.&lt;/p&gt;

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

&lt;p&gt;The future of software development is not about replacing engineers with AI.&lt;br&gt;
It is about creating an effective partnership between human expertise and AI capabilities.&lt;br&gt;
The workshop demonstrated that successful AI adoption begins long before code generation. It starts with understanding requirements, providing rich context, challenging assumptions, reviewing plans, validating tests, and maintaining ownership of quality throughout the development lifecycle.&lt;br&gt;
When combined with a disciplined workflow, AI becomes more than a productivity tool—it becomes a force multiplier for engineering teams.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>software</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Enabling CSRF in a JWT-Based React + Spring Boot Application (Enterprise-Ready Approach)</title>
      <dc:creator>Aswani Nayak</dc:creator>
      <pubDate>Wed, 27 May 2026 13:52:27 +0000</pubDate>
      <link>https://dev.to/aswani_nayak_cdcb2fe8ee38/enabling-csrf-in-a-jwt-based-react-spring-boot-application-enterprise-ready-approach-8a0</link>
      <guid>https://dev.to/aswani_nayak_cdcb2fe8ee38/enabling-csrf-in-a-jwt-based-react-spring-boot-application-enterprise-ready-approach-8a0</guid>
      <description>&lt;p&gt;Modern applications often use:&lt;br&gt;
&lt;strong&gt;•   React SPA (Single Page Application)&lt;br&gt;
• Spring Boot backend&lt;br&gt;
• JWT-based authentication&lt;br&gt;
• Stateless REST APIs&lt;/strong&gt;&lt;br&gt;
In this architecture, it’s common to disable CSRF:&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;.csrf(AbstractHttpConfigurer::disable)&lt;/code&gt;&lt;br&gt;
However, many enterprise security teams and tools (e.g., GitHub CodeQL) flag this as a &lt;strong&gt;high-severity issue&lt;/strong&gt;.&lt;br&gt;
This blog explains:&lt;br&gt;
• ✅ Why CSRF is flagged&lt;br&gt;
• ✅ Whether JWT APIs need CSRF&lt;br&gt;
• ✅ How to enable CSRF without breaking your SPA&lt;br&gt;
• ✅ A production-ready implementation&lt;/p&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;Understanding the Problem&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What is CSRF?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;CSRF (Cross-Site Request Forgery)&lt;/strong&gt; is an attack where a malicious website tricks a browser into making an authenticated request to another site.&lt;br&gt;
CSRF attacks rely on:&lt;br&gt;
• Automatic cookie sending by the browser&lt;br&gt;
• Session-based authentication&lt;br&gt;
Spring Security enables CSRF by default for this reason.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why JWT APIs Typically Disable CSRF&lt;/strong&gt;&lt;br&gt;
In a JWT-based system:&lt;br&gt;
• Authentication is done via:&lt;br&gt;
• Authorization: Bearer &lt;br&gt;
• Browsers do NOT automatically attach Authorization headers.&lt;br&gt;
• No session cookies are involved.&lt;br&gt;
• The API is stateless.&lt;br&gt;
Therefore, CSRF protection is &lt;strong&gt;not strictly required&lt;/strong&gt;.&lt;br&gt;
However...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Security Teams Still Want It Enabled&lt;/strong&gt;&lt;br&gt;
Enterprise AppSec teams often require:&lt;br&gt;
• Defense-in-depth&lt;br&gt;
• Uniform policy enforcement&lt;br&gt;
• Future-proof protection (in case cookies are introduced later)&lt;br&gt;
• Clean security scans without exceptions&lt;br&gt;
Instead of disabling CSRF, we can implement it correctly for SPA.&lt;/p&gt;

&lt;p&gt;2️⃣ &lt;strong&gt;Enterprise-Ready Solution&lt;/strong&gt;&lt;br&gt;
We will:&lt;br&gt;
• ✅ Keep JWT authentication&lt;br&gt;
• ✅ Keep backend stateless&lt;br&gt;
• ✅ Enable CSRF&lt;br&gt;
• ✅ Make it work with React SPA&lt;br&gt;
• ✅ Pass security review&lt;br&gt;
The key is:&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;CookieCsrfTokenRepository&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;3️⃣ &lt;strong&gt;Spring Boot Implementation&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Step 1: Security Configuration&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
            // ✅ Enable CSRF with Cookie repository (SPA-friendly)
            .csrf(csrf -&amp;gt; csrf
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            )

            // ✅ Keep application stateless
            .sessionManagement(session -&amp;gt;
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )

            .authorizeHttpRequests(auth -&amp;gt; auth
                .requestMatchers("/auth/**").permitAll()
                .anyRequest().authenticated()
            )

            // ✅ Add JWT filter
            .addFilterBefore(jwtAuthenticationFilter,
                    UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;What This Does&lt;/strong&gt;&lt;br&gt;
Spring Security will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Generate a CSRF token&lt;/li&gt;
&lt;li&gt; Send it in a cookie named:
XSRF-TOKEN&lt;/li&gt;
&lt;li&gt; Expect the frontend to send it back in header:
X-XSRF-TOKEN
This pattern is SPA-friendly and secure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;4️⃣ &lt;strong&gt;React Implementation&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Step 1: Enable Credentials&lt;/strong&gt;&lt;br&gt;
When using cookies, you must enable credentials:&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const api = axios.create({
  baseURL: "http://localhost:8080",
  withCredentials: true
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Step 2: Read CSRF Cookie&lt;/strong&gt;&lt;br&gt;
Helper function:&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Step 3: Axios Interceptor&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api.interceptors.request.use((config) =&amp;gt; {

  const jwt = localStorage.getItem("jwt");
  const csrfToken = getCookie("XSRF-TOKEN");

  if (jwt) {
    config.headers.Authorization = `Bearer ${jwt}`;
  }

  if (csrfToken) {
    config.headers["X-XSRF-TOKEN"] = csrfToken;
  }

  return config;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every request sends:&lt;br&gt;
• ✅ JWT token&lt;br&gt;
• ✅ CSRF token&lt;/p&gt;

&lt;p&gt;5️⃣ &lt;strong&gt;CORS Configuration (Critical)&lt;/strong&gt;&lt;br&gt;
When using cookies, you must allow credentials.&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(List.of("http://localhost:3000"));
    configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
    configuration.setAllowedHeaders(
        List.of("Authorization", "Content-Type", "X-XSRF-TOKEN")
    );
    configuration.setAllowCredentials(true);

    UrlBasedCorsConfigurationSource source =
            new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And enable CORS:&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;http.cors(Customizer.withDefaults());&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;6️⃣ &lt;strong&gt;Request Flow Explained&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Initial Request&lt;/strong&gt;&lt;br&gt;
• Backend generates CSRF token&lt;br&gt;
• Sends XSRF-TOKEN cookie&lt;br&gt;
✅ &lt;strong&gt;API Call&lt;/strong&gt;&lt;br&gt;
React sends:&lt;br&gt;
Authorization: Bearer &lt;br&gt;
X-XSRF-TOKEN: &lt;br&gt;
✅ &lt;strong&gt;Spring Validates&lt;/strong&gt;&lt;br&gt;
• JWT signature&lt;br&gt;
• CSRF token match&lt;br&gt;
If both valid → request succeeds.&lt;/p&gt;

&lt;p&gt;7️⃣ Architecture Summary&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%2Faw0q0k8cjgg3ax95aapo.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%2Faw0q0k8cjgg3ax95aapo.png" alt=" " width="168" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8️⃣ &lt;strong&gt;Why This Is a Strong Design&lt;/strong&gt;&lt;br&gt;
Even though JWT Authorization header authentication does not require CSRF, enabling it provides:&lt;br&gt;
• Defense-in-depth&lt;br&gt;
• Protection against future cookie-based changes&lt;br&gt;
• Compliance with security standards&lt;br&gt;
• Cleaner audit results&lt;br&gt;
This approach balances:&lt;br&gt;
✅ Security&lt;br&gt;
✅ Architecture purity&lt;br&gt;
✅ Enterprise compliance&lt;/p&gt;

&lt;p&gt;9️⃣ &lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
If you are building:&lt;br&gt;
• React SPA&lt;br&gt;
• Spring Boot backend&lt;br&gt;
• JWT authentication&lt;br&gt;
And your security team requires CSRF to be enabled:&lt;br&gt;
✅ Use CookieCsrfTokenRepository&lt;br&gt;
✅ Send CSRF token via header&lt;br&gt;
✅ Keep the application stateless&lt;br&gt;
This gives you:&lt;br&gt;
• Modern architecture&lt;br&gt;
• Strong security posture&lt;br&gt;
• Enterprise-ready implementation&lt;/p&gt;

</description>
      <category>react</category>
      <category>security</category>
      <category>springboot</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Storing Personal Information in React: sessionStorage vs Context API</title>
      <dc:creator>Aswani Nayak</dc:creator>
      <pubDate>Mon, 18 May 2026 02:25:35 +0000</pubDate>
      <link>https://dev.to/aswani_nayak_cdcb2fe8ee38/storing-personal-information-in-react-sessionstorage-vs-context-api-25pa</link>
      <guid>https://dev.to/aswani_nayak_cdcb2fe8ee38/storing-personal-information-in-react-sessionstorage-vs-context-api-25pa</guid>
      <description>&lt;p&gt;When building React applications, developers often need to handle personal information such as names, emails, profile data, or authentication details.&lt;br&gt;
A common question arises:&lt;br&gt;
Should I store personal information in sessionStorage or use React’s Context API?&lt;br&gt;
The answer depends heavily on security, persistence needs, and application design. In this post, we’ll break down the differences, risks, and best practices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding the Two Options&lt;br&gt;
1️⃣ What Is sessionStorage?&lt;/strong&gt;&lt;br&gt;
sessionStorage is a browser-based storage mechanism that:&lt;br&gt;
• Stores data per tab&lt;br&gt;
• Persists across page refreshes&lt;br&gt;
• Clears when the tab is closed&lt;br&gt;
• Is accessible via JavaScript&lt;br&gt;
Example:&lt;br&gt;
Code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store data&lt;/span&gt;
&lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userEmail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userEmail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2️⃣ What Is React Context API?&lt;/strong&gt;&lt;br&gt;
The Context API is a React feature that allows you to:&lt;br&gt;
• Share state across components&lt;br&gt;
• Store data in memory&lt;br&gt;
• Avoid prop drilling&lt;br&gt;
• Reset data on page refresh&lt;br&gt;
Example:&lt;br&gt;
Code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Key Differences&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%2Fov25hwjnk9uawpwwsmhe.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%2Fov25hwjnk9uawpwwsmhe.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Security Considerations (Critical for Personal Info)&lt;/strong&gt;&lt;br&gt;
When storing personal information (PII), security should be your top priority.&lt;br&gt;
🔴 &lt;strong&gt;Risks of Using sessionStorage&lt;/strong&gt;&lt;br&gt;
• Accessible via browser DevTools&lt;br&gt;
• Accessible to any script running on the page&lt;br&gt;
• Vulnerable to Cross-Site Scripting (XSS)&lt;br&gt;
• Persists after refresh (increasing exposure window)&lt;br&gt;
If your app suffers from an XSS vulnerability, malicious code could easily run:&lt;br&gt;
&lt;strong&gt;Code&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;sessionStorage.getItem("userSSN");&lt;/code&gt;&lt;br&gt;
That’s a serious risk.&lt;/p&gt;




&lt;p&gt;🟢 &lt;strong&gt;Why Context API Is Safer&lt;/strong&gt;&lt;br&gt;
Context data:&lt;br&gt;
• Lives only in memory&lt;br&gt;
• Disappears on refresh&lt;br&gt;
• Is scoped within your React app&lt;br&gt;
• Is not automatically accessible globally&lt;br&gt;
However, note:&lt;br&gt;
Context is still vulnerable to XSS if your app is compromised.&lt;br&gt;
No client-side storage is 100% secure.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;When Should You Use Each?&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Use Context API When:&lt;/strong&gt;&lt;br&gt;
• Handling sensitive personal information&lt;br&gt;
• Data does not need to survive page refresh&lt;br&gt;
• You want better encapsulation&lt;br&gt;
• Managing user session state&lt;br&gt;
Examples:&lt;br&gt;
• User profile details&lt;br&gt;
• Temporary form data&lt;br&gt;
• Authenticated user state&lt;/p&gt;




&lt;p&gt;✅ Use sessionStorage When:&lt;br&gt;
• You need data to persist across refresh&lt;br&gt;
• The data is low sensitivity&lt;br&gt;
• UX depends on temporary persistence&lt;br&gt;
Examples:&lt;br&gt;
• Wizard step progress&lt;br&gt;
• Non-sensitive UI preferences&lt;br&gt;
• Temporary search filters&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Should NEVER Store in sessionStorage&lt;/strong&gt;&lt;br&gt;
Avoid storing:&lt;br&gt;
• Passwords&lt;br&gt;
• Social Security Numbers&lt;br&gt;
• Credit card numbers&lt;br&gt;
• Medical data&lt;br&gt;
• Raw authentication tokens&lt;br&gt;
• Sensitive PII&lt;br&gt;
If the data would be catastrophic if exposed — don’t store it client-side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Best Practice Architecture&lt;/strong&gt;&lt;br&gt;
For handling personal information securely in modern React apps:&lt;br&gt;
✅ &lt;strong&gt;Recommended Approach&lt;/strong&gt;&lt;br&gt;
• Store authentication tokens in &lt;strong&gt;HTTP-only secure cookies&lt;/strong&gt;&lt;br&gt;
• Store user profile data in &lt;strong&gt;React Context (memory)&lt;/strong&gt;&lt;br&gt;
• Keep highly sensitive data on the &lt;strong&gt;backend only&lt;/strong&gt;&lt;br&gt;
Architecture flow:&lt;br&gt;
Backend&lt;br&gt;
   ↓&lt;br&gt;
HTTP-only cookie (auth token)&lt;br&gt;
   ↓&lt;br&gt;
React Context (user state in memory)&lt;br&gt;
Why this works:&lt;br&gt;
• HTTP-only cookies cannot be accessed via JavaScript&lt;br&gt;
• Context keeps sensitive UI data ephemeral&lt;br&gt;
• Exposure window is minimized&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Recommendation&lt;/strong&gt;&lt;br&gt;
If you're choosing between sessionStorage and Context API for personal information:&lt;br&gt;
✅ Use &lt;strong&gt;React Context&lt;/strong&gt; for sensitive data&lt;br&gt;
⚠️ Use sessionStorage only for low-risk persistence needs&lt;br&gt;
And remember:&lt;br&gt;
The most secure data is the data you never store on the client.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>security</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
