<?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: Istaprasad Patra</title>
    <description>The latest articles on DEV Community by Istaprasad Patra (@istaprasad_patra_db896155).</description>
    <link>https://dev.to/istaprasad_patra_db896155</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%2F2234783%2F4983c2ff-5263-44d4-b15f-85ece7474681.png</url>
      <title>DEV Community: Istaprasad Patra</title>
      <link>https://dev.to/istaprasad_patra_db896155</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/istaprasad_patra_db896155"/>
    <language>en</language>
    <item>
      <title>Protecting Routes in Next.js with Unkey: A Personal Experience</title>
      <dc:creator>Istaprasad Patra</dc:creator>
      <pubDate>Fri, 25 Oct 2024 13:43:54 +0000</pubDate>
      <link>https://dev.to/istaprasad_patra_db896155/protecting-routes-in-nextjs-with-unkey-a-personal-experience-3b9o</link>
      <guid>https://dev.to/istaprasad_patra_db896155/protecting-routes-in-nextjs-with-unkey-a-personal-experience-3b9o</guid>
      <description>&lt;p&gt;When we build web applications with Next.js, securing sensitive routes is a critical aspect of maintaining the integrity of the app and user data. I recently implemented Unkey, a modern security platform, to protect the routes in a Next.js project. &lt;br&gt;
Here’s a detailed walkthrough of my experience with it, highlighting why I choose Unkey, how I integrated it, and the results I achieved.&lt;/p&gt;
&lt;h2&gt;
  
  
  About Unkey
&lt;/h2&gt;

&lt;p&gt;Before diving into the integration, I was looking for a solution that could offer robust access control with minimal configuration. Unkey stood out because of its:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: It provides pre-built SDKs for JavaScript frameworks, making it easy to set up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Granular Control&lt;/strong&gt;: Unkey enables fine-grained access control, letting you protect routes based on user roles, permissions, and other custom rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: It works well for both small projects and large-scale applications, which was appealing for future growth.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Setting up Unkey into NextJs
&lt;/h2&gt;

&lt;p&gt;I am building a stock management application and in this blog I will be telling you about the backend of this project.&lt;/p&gt;

&lt;p&gt;The steps to setup are pretty clearly given in the &lt;a href="https://www.unkey.com/docs/quickstart/apis/nextjs" rel="noopener noreferrer"&gt;&lt;em&gt;docs&lt;/em&gt;&lt;/a&gt;. Firstly, we need create an account in &lt;a href="https://www.unkey.com/" rel="noopener noreferrer"&gt;&lt;em&gt;unkey.com&lt;/em&gt;&lt;/a&gt; and create an api key and then go through the below steps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; npx create-next-app@latest
 npm install @unkey/nextjs
 npm install mongoose mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up Database
&lt;/h2&gt;

&lt;p&gt;I am using mongodb as my database, you can database as per your comfort.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NextResponse } from "next/server";
import mongoose, { Document, Model, Schema } from "mongoose";

const uri: string = process.env.MONGO_URI as string;

// Connect to MongoDB using mongoose
export async function connectToDatabase(): Promise&amp;lt;void&amp;gt; {
  try {
    await mongoose.connect(uri, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    });
    console.log("Connected to the database");
  } catch (error) {
    console.error("Database connection error:", error);
    throw error;
  }
}

// Define the Inventory interface
interface IInventory extends Document {
  slug: string;
  quantity: number;
  price: string;
}

// Define the schema
const inventorySchema: Schema&amp;lt;IInventory&amp;gt; = new Schema({
  slug: {
    type: String,
    required: true,
    unique: true,
  },
  quantity: {
    type: Number,
    required: true,
  },
  price: {
    type: String,
    required: true,
  },
});

// Create the model
const Inventory: Model&amp;lt;IInventory&amp;gt; = mongoose.models.Inventory || mongoose.model&amp;lt;IInventory&amp;gt;("Inventory", inventorySchema);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making Fetching Data, Adding Data and Searching Data Routes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NextResponse } from "next/server";
import { withUnkey } from "@unkey/sdk/next";  // Ensure this import path is correct based on your SDK setup.
import type { NextRequest } from "next/server";

export const POST = withUnkey(async (req: NextRequest) =&amp;gt; {
  if (!req.unkey?.valid) {
    return new NextResponse("Unauthorized", { status: 403 });
  }

  await connectToDatabase();

  try {
    const data = await req.json();
    console.log(data);
    const product = await Inventory.create(data);
    return NextResponse.json({ product, ok: true }, { status: 200 });
  } catch (error: any) {
    return NextResponse.json({ error: error.message }, { status: 400 });
  }
});

export const GET = withUnkey(async (req: NextRequest) =&amp;gt; {
  if (!req.unkey?.valid) {
    return new NextResponse("Unauthorized", { status: 403 });
  }

  await connectToDatabase();

  try {
    const allProducts = await Inventory.find({});
    return NextResponse.json({ allProducts }, { status: 200 });
  } catch (error: any) {
    return NextResponse.json({ error: error.message || "An error occurred" }, { status: 400 });
  }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the searching data route is in another page :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NextResponse } from "next/server";
import { withUnkey } from "@unkey/sdk/next"; 
import { connectToDatabase } from "../mongo/route"; 
import { Inventory } from "../mongo/route";
import type { NextRequest } from "next/server";

export const GET = withUnkey(async (req: NextRequest) =&amp;gt; {
  if (!req.unkey?.valid) {
    return new NextResponse("Unauthorized", { status: 403 });
  }

  await connectToDatabase();

  try {
    const { searchParams } = new URL(req.url);
    const slug = searchParams.get("slug") || "";

    const allProducts = await Inventory.find({
      slug: { $regex: slug, $options: "i" },
    });

    return NextResponse.json({ allProducts }, { status: 200 });
  } catch (error: any) {
    return NextResponse.json({ error: error.message || "An error occurred" }, { status: 400 });
  }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits I Experienced
&lt;/h2&gt;

&lt;p&gt;Using Unkey to secure my Next.js app brought several advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customization&lt;/strong&gt;: I appreciated the flexibility to define custom rules for different user roles. This gave me full control over route access management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of Use&lt;/strong&gt;: The SDK’s tight integration with Next.js allowed me to focus more on the business logic while handling security effortlessly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Initially I faced a few problems as I wasn't able to understand what exactly it does but as I used it, I understood how it helps. In a big application, it will handle the security of the routes and remove a huge burden from my shoulders.&lt;/p&gt;

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

&lt;p&gt;Using Unkey to protect routes in Next.js provided a powerful yet simple solution for managing access control in my application. Its integration with Next.js was seamless, and the flexibility it offers for defining custom rules based on user roles made it perfect for my needs.&lt;/p&gt;

&lt;p&gt;For anyone looking for a scalable security solution to protect routes in their Next.js application, I highly recommend giving &lt;a href="https://www.unkey.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Unkey&lt;/em&gt;&lt;/a&gt; a try.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>unkey</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Easy Authentication Using Hanko.io</title>
      <dc:creator>Istaprasad Patra</dc:creator>
      <pubDate>Sat, 19 Oct 2024 18:05:06 +0000</pubDate>
      <link>https://dev.to/istaprasad_patra_db896155/easy-authentication-using-hankoio-2okd</link>
      <guid>https://dev.to/istaprasad_patra_db896155/easy-authentication-using-hankoio-2okd</guid>
      <description>&lt;p&gt;Building dependable online apps in the rapidly changing world of web development today requires smooth and secure authentication. A contemporary, safe, and passwordless method of user authentication is provided by Hanko, a robust authentication API. I'll demonstrate how to integrate Hanko Elements and Hanko API into a React application in this blog post, and then I'll show you a demonstration of the authentication system we created.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let's get started!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Hanko?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hanko is an authentication service that offers a passwordless experience to streamline the user authentication process. Because it supports WebAuthn, developers may use security keys, biometrics, or other passwordless login methods. Additionally, Hanko offers pre-made user interface components (known as Hanko Elements) to facilitate a smooth integration process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Setting Up Your React Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, if you haven’t already, initialize a React application using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app hanko
cd hanko
npm install react-router-dom
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new React project and spin up the development server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Install Hanko Elements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, install the Hanko Elements library to get access to their pre-built authentication components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @teamhanko/hanko-elements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This package will allow us to easily embed Hanko authentication elements into our React components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Configure Hanko in Your Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before diving into the code, you’ll need to sign up at Hanko.io and get your API key. After setting up your Hanko project, you can retrieve the Hanko API base URL and Hanko API key from your dashboard.&lt;/p&gt;

&lt;p&gt;Add these values to your environment variables in the &lt;em&gt;.env&lt;/em&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REACT_APP_HANKO_API_URL=&amp;lt;YOUR_HANKO_API_BASE_URL&amp;gt;
REACT_APP_HANKO_API_KEY=&amp;lt;YOUR_HANKO_API_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Building the Authentication Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we have the project set up and the Hanko Elements installed, let's move on to integrating the authentication functionality.&lt;/p&gt;

&lt;p&gt;Create a Login.js file that will handle user authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { useEffect, useCallback, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { register, Hanko } from "@teamhanko/hanko-elements";

const hankoApi = process.env.REACT_APP_HANKO_API_URL;

function Login() {
  const navigate = useNavigate();
  const hanko = useMemo(() =&amp;gt; new Hanko(hankoApi), []);
  const [userState, setUserState] = useState({
    id: "",
    email: "",
    error: "",
  });

  const [sessionState, setSessionState] = useState({
    userID: "",
    jwt: "",
    isValid: false,
    error: "",
  });

  const redirectAfterLogin = useCallback(() =&amp;gt; {
    navigate("/logout");
  }, [navigate]);

  useEffect(
    () =&amp;gt;
      hanko.onSessionCreated(() =&amp;gt; {
        hanko?.user
          .getCurrent()
          .then(({ id, email }) =&amp;gt; {
            setUserState({ id, email, error: "" });
            console.log(id,email)
          })
          .catch((error) =&amp;gt; {
            setUserState((prevState) =&amp;gt; ({ ...prevState, error: error }));
          });
        redirectAfterLogin();
      }),
    [hanko, redirectAfterLogin]
  );

  useEffect(() =&amp;gt; {
    if (hanko) {
      const isValid = hanko.session.isValid();
      const session = hanko.session.get();

      if (isValid &amp;amp;&amp;amp; session) {
        const { userID, jwt = "" } = session;
        setSessionState({
          userID,
          jwt,
          isValid,
          error: null,
        });
        console.log(jwt);
      } else {
        setSessionState((prevState) =&amp;gt; ({
          ...prevState,
          isValid: false,
          error: "Invalid session",
        }));
      }
    }
  }, [hanko]);

  useEffect(() =&amp;gt; {
    register(hankoApi).catch((error) =&amp;gt; {
      console.log(error);
    });
  }, []);
  return (
    &amp;lt;div className="m-0 flex justify-center items-center"&amp;gt;
      &amp;lt;hanko-auth /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Login;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we authenticate without even using an backend server, simply using &lt;a href="https://www.hanko.io/" rel="noopener noreferrer"&gt;hanko.io&lt;/a&gt; . The  provides a frontend block which helps the user to login and also signin it he/she doesn't has an account. It authenticates does email verfication by sending OTP to the user's email. It also provides the feature of login even &lt;em&gt;if the user forgets his password&lt;/em&gt; and also provides 2-factor authentication using &lt;em&gt;passkeys&lt;/em&gt; and also using &lt;em&gt;device's biometrics&lt;/em&gt; .You can also other social authentication methods like google,facebook,github etc. &lt;/p&gt;

&lt;p&gt;Here, we also get jwt tokens which can be further used in other routes to check the user's autheticity using the JWKS URL. We will be able to do all these stuff without even having a backend server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Handling Logout&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To allow users to log out, we can just add a logout button in the further pages of the website.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Hanko } from "@teamhanko/hanko-elements";

const hankoApi = process.env.REACT_APP_HANKO_API_URL;

function Logout() {
    const navigate = useNavigate();
    const [hanko, setHanko] = useState(&amp;lt;Hanko /&amp;gt;);

    useEffect(() =&amp;gt; {
      import("@teamhanko/hanko-elements").then(({ Hanko }) =&amp;gt;
        setHanko(new Hanko(hankoApi ?? ""))
      );
    }, []);

    const logout = async () =&amp;gt; {
      try {
        await hanko?.user.logout();
        navigate("/");
      } catch (error) {
        console.error("Error during logout:", error);
      }
    };

    return (
    &amp;lt;button onClick={logout} className="mt-10 bg-red-50 w-24 text-2xl hover:text-3xl hover:text-red-400 duration-300"&amp;gt;Logout&amp;lt;/button&amp;gt;
);
}

export default Logout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just an example how you can use the logout component in your website. As you can see that we can logout easily just using simple functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Experience&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I personally loved hanko.io because first of all, it has made my work very easy and also when I read the docs, it is super easy to understand and use. Most of the code which will be used in development process is already mentioned in the docs and so it makes our work very easy.&lt;/p&gt;

&lt;p&gt;Secondly, there are a lot of options to use it like we can use it with other frontend frameworks like Vue, Angular, Svelte etc. We can also with many languages with which backend servers are written like NodeJs, Go, Python, Rust etc. So this makes it very compatible with every language. We can also use it with other frameworks like NextJs, Remix, Nuxt etc.&lt;/p&gt;

&lt;p&gt;When I first visited their website, I found it to be very professional and easy to navigate. If someone just follows it step by step then it is super easy to understand and use.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With this blog, developers can understand how to integrate a modern and secure authentication system using Hanko in their projects, ensuring robust security while enhancing the user experience.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For more information you can visit&lt;/strong&gt; &lt;a href="https://www.hanko.io/" rel="noopener noreferrer"&gt;hanko.io&lt;/a&gt; &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>node</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
