next-firebase-auth-edge
का परिचयअपने मौजूदा या नए नेक्स्ट.जेएस एप्लिकेशन में फायरबेस ऑथेंटिकेशन जोड़ने के तरीकों की खोज करते समय आपको संभवतः यह लेख मिला होगा। आपका लक्ष्य एक स्मार्ट, निष्पक्ष और भविष्योन्मुखी निर्णय लेना है जिससे आपके ऐप के सफल होने की संभावना अधिकतम हो जाएगी। नेक्स्ट-फायरबेस-ऑथ-एज के निर्माता के रूप में, मुझे यह स्वीकार करना होगा कि पूरी तरह से निष्पक्ष राय प्रदान करना मेरी विशेषता नहीं है, लेकिन कम से कम मैं लाइब्रेरी को डिजाइन करते समय अपनाए गए दृष्टिकोण को सही ठहराने की कोशिश करूंगा। उम्मीद है, इस गाइड के अंत तक, आपको दीर्घावधि के लिए यह दृष्टिकोण सरल और व्यवहार्य दोनों मिल सकता है।
मैं आपके लिए लंबे परिचय सहेज कर रखूंगा। मैं बस यह कहना चाहता हूं कि पुस्तकालय का विचार संभवतः आपके जैसी स्थिति से प्रेरित था। यह वह समय था जब नेक्स्ट.जेएस ने ऐप राउटर का कैनरी संस्करण जारी किया था। मैं ऐसे ऐप पर काम कर रहा था जो पुनर्लेखन और आंतरिक रीडायरेक्ट पर अत्यधिक निर्भर था। उसके लिए, हम कस्टम Node.js express
सर्वर रेंडरिंग Next.js ऐप का उपयोग कर रहे थे।
हम ऐप राउटर और सर्वर कंपोनेंट्स के लिए वास्तव में उत्साहित थे, फिर भी जानते थे कि यह हमारे कस्टम सर्वर के साथ संगत नहीं होगा। मिडलवेयर एक शक्तिशाली सुविधा की तरह लग रहा था जिसे हम कस्टम एक्सप्रेस सर्वर की आवश्यकता को खत्म करने के लिए लाभ उठा सकते थे, इसके बजाय उपयोगकर्ताओं को गतिशील रूप से विभिन्न पृष्ठों पर रीडायरेक्ट और रीराइट करने के लिए नेक्स्ट.जेएस की अंतर्निहित सुविधाओं पर भरोसा करने का विकल्प चुना।
उस समय, हम Next-firebase-auth का उपयोग कर रहे थे। हमें लाइब्रेरी वास्तव में पसंद आई, लेकिन इसने हमारे प्रमाणीकरण तर्क को next.config.js
, pages/_app.tsx
, pages/api/login.ts
, pages/api/logout.ts
फाइलों के माध्यम से फैलाया, जिन्हें विरासत माना जा रहा था। जल्द ही। इसके अलावा, लाइब्रेरी मिडलवेयर के साथ संगत नहीं थी, जिससे हमें यूआरएल को दोबारा लिखने या उपयोगकर्ताओं को उनके संदर्भ के आधार पर रीडायरेक्ट करने से रोका जा सका।
इसलिए, मैंने अपनी खोज शुरू की, लेकिन मुझे आश्चर्य हुआ, मुझे ऐसी कोई लाइब्रेरी नहीं मिली जो मिडलवेयर के भीतर फायरबेस प्रमाणीकरण का समर्थन करती हो। – ऐसा क्यों हो सकता है? यह नामुमकिन है! Node.js और React में 11 वर्षों से अधिक के व्यावसायिक अनुभव के साथ एक सॉफ्टवेयर इंजीनियर के रूप में, मैं इस पहेली से निपटने के लिए तैयारी कर रहा था।
तो, मैंने शुरुआत की। और उत्तर स्पष्ट हो गया. मिडलवेयर एज रनटाइम के अंदर चल रहा है। एज रनटाइम के अंदर वेब क्रिप्टो एपीआई के साथ संगत कोई फायरबेस लाइब्रेरी उपलब्ध नहीं है। मैं बर्बाद हो गया था . मैं असहाय महसूस कर रहा था. क्या यह पहली बार है जब मुझे नए और फैंसी एपीआई के साथ खेलने के लिए वास्तव में इंतजार करना होगा? - नहीं। एक अंतहीन इंतज़ार। मैंने तुरंत रोना बंद कर दिया और नेक्स्ट-फ़ायरबेस-ऑर्ट , फ़ायरबेस-एडमिन और कई अन्य जेडब्ल्यूटी प्रमाणीकरण लाइब्रेरीज़ को रिवर्स-इंजीनियर करना शुरू कर दिया, और उन्हें एज रनटाइम में अनुकूलित किया। मैंने पिछले प्रमाणीकरण पुस्तकालयों के साथ मेरे सामने आए सभी मुद्दों को संबोधित करने का अवसर जब्त कर लिया, जिसका लक्ष्य सबसे हल्का, कॉन्फ़िगर करने में आसान और भविष्य-उन्मुख प्रमाणीकरण पुस्तकालय बनाना था।
लगभग दो सप्ताह बाद, नेक्स्ट-फायरबेस-ऑथ-एज का संस्करण 0.0.1
पैदा हुआ। यह अवधारणा का एक ठोस प्रमाण था, लेकिन आप संस्करण 0.0.1
उपयोग नहीं करना चाहेंगे। मुझ पर भरोसा करें।
लगभग दो साल बाद , मुझे यह घोषणा करते हुए खुशी हो रही है कि 372 प्रतिबद्धताओं , 110 हल किए गए मुद्दों और दुनिया भर के अद्भुत डेवलपर्स से अमूल्य प्रतिक्रिया के बाद, लाइब्रेरी एक ऐसे चरण पर पहुंच गई है जहां मेरे अन्य स्वयं अनुमोदन में मेरे पास हैं।
इस गाइड में, मैं स्क्रैच से प्रमाणित नेक्स्ट.जेएस ऐप बनाने के लिए नेक्स्ट-फायरबेस-ऑथ-एज के संस्करण 1.4.1 का उपयोग करूंगा। हम प्रत्येक चरण के बारे में विस्तार से जानेंगे, जिसकी शुरुआत एक नए फायरबेस प्रोजेक्ट और नेक्स्ट.जेएस ऐप के निर्माण से होगी, इसके बाद next-firebase-auth-edge
और firebase/auth
लाइब्रेरीज़ के साथ एकीकरण होगा। इस ट्यूटोरियल के अंत में, हम यह पुष्टि करने के लिए ऐप को वर्सेल में तैनात करेंगे कि सब कुछ स्थानीय और उत्पादन-तैयार वातावरण में काम कर रहा है।
यह भाग मानता है कि आपने अभी तक फ़ायरबेस प्रमाणीकरण सेटअप नहीं किया है। यदि अन्यथा हो तो बेझिझक अगले भाग पर जाएँ।
आइए फायरबेस कंसोल पर जाएं और एक प्रोजेक्ट बनाएं
प्रोजेक्ट बनने के बाद, आइए फायरबेस प्रमाणीकरण सक्षम करें। कंसोल खोलें और बिल्ड > प्रमाणीकरण > साइन-इन विधि का पालन करें और ईमेल और पासवर्ड विधि सक्षम करें। यही वह तरीका है जिसका हम अपने ऐप में समर्थन करने जा रहे हैं
अपनी पहली साइन-इन विधि सक्षम करने के बाद, आपके प्रोजेक्ट के लिए फायरबेस प्रमाणीकरण सक्षम होना चाहिए और आप प्रोजेक्ट सेटिंग्स में अपनी वेब एपीआई कुंजी पुनः प्राप्त कर सकते हैं
एपीआई कुंजी को कॉपी करें और इसे सुरक्षित रखें। अब, अगला टैब खोलें - क्लाउड मैसेजिंग, और सेंडर आईडी नोट करें। हमें बाद में इसकी आवश्यकता पड़ेगी।
अंतिम लेकिन महत्वपूर्ण बात, हमें सेवा खाता क्रेडेंशियल उत्पन्न करने की आवश्यकता है। वे आपके ऐप को आपकी फायरबेस सेवाओं तक पूर्ण पहुंच प्राप्त करने की अनुमति देंगे। प्रोजेक्ट सेटिंग्स > सेवा खाते पर जाएं और नई निजी कुंजी जेनरेट करें पर क्लिक करें। यह सेवा खाता क्रेडेंशियल्स के साथ एक .json
फ़ाइल डाउनलोड करेगा। इस फ़ाइल को किसी ज्ञात स्थान पर सहेजें.
इतना ही! हम Next.js ऐप को फायरबेस ऑथेंटिकेशन के साथ एकीकृत करने के लिए तैयार हैं
यह मार्गदर्शिका मानती है कि आपके पास Node.js और npm स्थापित है। इस ट्यूटोरियल में उपयोग किए गए कमांड को नवीनतम LTS Node.js v20 के विरुद्ध सत्यापित किया गया था। आप टर्मिनल में node -v
चलाकर नोड संस्करण को सत्यापित कर सकते हैं। आप Node.js संस्करणों के बीच शीघ्रता से स्विच करने के लिए NVM जैसे टूल का भी उपयोग कर सकते हैं।
अपना पसंदीदा टर्मिनल खोलें, अपने प्रोजेक्ट फ़ोल्डर में जाएँ और चलाएँ
npx create-next-app@latest
इसे सरल बनाए रखने के लिए, आइए डिफ़ॉल्ट कॉन्फ़िगरेशन का उपयोग करें। इसका मतलब है कि हम TypeScript
और tailwind
का उपयोग करेंगे
✔ What is your project named? … my-app ✔ Would you like to use TypeScript? … Yes ✔ Would you like to use ESLint? … Yes ✔ Would you like to use Tailwind CSS? … Yes ✔ Would you like to use `src/` directory? … No ✔ Would you like to use App Router? (recommended) … Yes ✔ Would you like to customize the default import alias (@/*)? … No
आइए प्रोजेक्ट के रूट डीआईआर पर जाएँ और सुनिश्चित करें कि सभी निर्भरताएँ स्थापित हैं
cd my-app npm install
यह पुष्टि करने के लिए कि सब कुछ अपेक्षा के अनुरूप काम करता है, आइए npm run dev
कमांड के साथ Next.js dev सर्वर शुरू करें। जब आप http://localhost:3000 खोलते हैं, तो आपको Next.js स्वागत पृष्ठ देखना चाहिए, जो इस जैसा है:
इससे पहले कि हम फायरबेस के साथ एकीकरण शुरू करें, हमें अपने फायरबेस कॉन्फ़िगरेशन को संग्रहीत करने और पढ़ने का एक सुरक्षित तरीका चाहिए। सौभाग्य से, Next.js बिल्ट-इन dotenv समर्थन के साथ आता है।
अपना पसंदीदा कोड संपादक खोलें और प्रोजेक्ट फ़ोल्डर पर जाएँ
आइए प्रोजेक्ट की रूट डायरेक्टरी में .env.local
फ़ाइल बनाएं और इसे निम्नलिखित पर्यावरण चर से भरें:
FIREBASE_ADMIN_CLIENT_EMAIL=... FIREBASE_ADMIN_PRIVATE_KEY=... AUTH_COOKIE_NAME=AuthToken AUTH_COOKIE_SIGNATURE_KEY_CURRENT=secret1 AUTH_COOKIE_SIGNATURE_KEY_PREVIOUS=secret2 USE_SECURE_COOKIES=false NEXT_PUBLIC_FIREBASE_PROJECT_ID=... NEXT_PUBLIC_FIREBASE_API_KEY=AIza... NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=....firebaseapp.com NEXT_PUBLIC_FIREBASE_DATABASE_URL=....firebaseio.com NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=...
कृपया ध्यान दें कि NEXT_PUBLIC_
के साथ उपसर्ग वाले वेरिएबल क्लाइंट-साइड बंडल में उपलब्ध होंगे। हमें फायरबेस ऑथ क्लाइंट एसडीके सेटअप करने के लिए उनकी आवश्यकता होगी
NEXT_PUBLIC_FIREBASE_PROJECT_ID
, FIREBASE_ADMIN_CLIENT_EMAIL
और FIREBASE_ADMIN_PRIVATE_KEY
सेवा खाता क्रेडेंशियल बनाने के बाद डाउनलोड की गई .json
फ़ाइल से पुनर्प्राप्त किया जा सकता है
AUTH_COOKIE_NAME
उपयोगकर्ता क्रेडेंशियल संग्रहीत करने के लिए उपयोग की जाने वाली कुकी का नाम होगा
AUTH_COOKIE_SIGNATURE_KEY_CURRENT
और AUTH_COOKIE_SIGNATURE_KEY_PREVIOUS
ऐसे रहस्य हैं जिनके साथ हम क्रेडेंशियल्स पर हस्ताक्षर करने जा रहे हैं
NEXT_PUBLIC_FIREBASE_API_KEY
प्रोजेक्ट सेटिंग्स सामान्य पृष्ठ से प्राप्त वेब एपीआई कुंजी है
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
आपका प्रोजेक्ट-आईडी है .firebaseapp.com
NEXT_PUBLIC_FIREBASE_DATABASE_URL
आपका प्रोजेक्ट-आईडी है .firebaseio.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
प्रोजेक्ट सेटिंग्स > क्लाउड मैसेजिंग पेज से प्राप्त किया जा सकता है
USE_SECURE_COOKIES
उपयोग स्थानीय विकास के लिए नहीं किया जाएगा, लेकिन यह तब काम आएगा जब हम अपने ऐप को वर्सेल में तैनात करेंगे
next-firebase-auth-edge
और प्रारंभिक कॉन्फ़िगरेशन स्थापित करना npm install next-firebase-auth-edge@^1.4.1
चलाकर प्रोजेक्ट की निर्भरता में लाइब्रेरी जोड़ें
आइए अपने प्रोजेक्ट कॉन्फ़िगरेशन को इनकैप्सुलेट करने के लिए config.ts
फ़ाइल बनाएं। इसकी आवश्यकता नहीं है, लेकिन यह कोड उदाहरणों को अधिक पठनीय बना देगा।
उन मूल्यों पर विचार करने में बहुत अधिक समय व्यतीत न करें। जैसे-जैसे हम आगे बढ़ेंगे हम उन्हें और अधिक विस्तार से समझाएंगे।
export const serverConfig = { cookieName: process.env.AUTH_COOKIE_NAME!, cookieSignatureKeys: [process.env.AUTH_COOKIE_SIGNATURE_KEY_CURRENT!, process.env.AUTH_COOKIE_SIGNATURE_KEY_PREVIOUS!], cookieSerializeOptions: { path: "/", httpOnly: true, secure: process.env.USE_SECURE_COOKIES === "true", sameSite: "lax" as const, maxAge: 12 * 60 * 60 * 24, }, serviceAccount: { projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID!, clientEmail: process.env.FIREBASE_ADMIN_CLIENT_EMAIL!, privateKey: process.env.FIREBASE_ADMIN_PRIVATE_KEY?.replace(/\\n/g, "\n")!, } }; export const clientConfig = { projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY!, authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL, messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID };
प्रोजेक्ट के रूट में middleware.ts
फ़ाइल बनाएं और निम्नलिखित को पेस्ट करें
import { NextRequest } from "next/server"; import { authMiddleware } from "next-firebase-auth-edge"; import { clientConfig, serverConfig } from "./config"; export async function middleware(request: NextRequest) { return authMiddleware(request, { loginPath: "/api/login", logoutPath: "/api/logout", apiKey: clientConfig.apiKey, cookieName: serverConfig.cookieName, cookieSignatureKeys: serverConfig.cookieSignatureKeys, cookieSerializeOptions: serverConfig.cookieSerializeOptions, serviceAccount: serverConfig.serviceAccount, }); } export const config = { matcher: [ "/", "/((?!_next|api|.*\\.).*)", "/api/login", "/api/logout", ], };
विश्वास करें या न करें, लेकिन हमने अपने ऐप के सर्वर को फायरबेस प्रमाणीकरण के साथ एकीकृत कर दिया है। इससे पहले कि हम वास्तव में इसका उपयोग करें, आइए कॉन्फ़िगरेशन को थोड़ा समझाएं:
loginPath
ऑथमिडलवेयर को GET /api/login
एंडपॉइंट को उजागर करने का निर्देश देगा। जब इस समापन बिंदु को Authorization: Bearer ${idToken}
* हेडर के साथ कॉल किया जाता है, तो यह HTTP(S)-केवल Set-Cookie
हेडर के साथ प्रतिक्रिया करता है जिसमें हस्ताक्षरित कस्टम और रीफ्रेश टोकन होते हैं
* idToken
Firebase क्लाइंट SDK में उपलब्ध getIdToken
फ़ंक्शन के साथ पुनर्प्राप्त किया जाता है। इस पर बाद में और अधिक जानकारी।
इसी तरह, logoutPath
मिडलवेयर को GET /api/logout
उजागर करने का निर्देश देता है, लेकिन इसके लिए किसी अतिरिक्त हेडर की आवश्यकता नहीं होती है। कॉल करने पर, यह ब्राउज़र से प्रमाणीकरण कुकीज़ हटा देता है।
apiKey
वेब एपीआई कुंजी है। मिडलवेयर इसका उपयोग कस्टम टोकन को रीफ्रेश करने और क्रेडेंशियल समाप्त होने के बाद प्रमाणीकरण कुकीज़ को रीसेट करने के लिए करता है।
cookieName
कुकी सेट का नाम है और /api/login
और /api/logout
एंडपॉइंट द्वारा हटा दिया गया है
cookieSignatureKeys
गुप्त कुंजियों की एक सूची है जिसके साथ उपयोगकर्ता क्रेडेंशियल पर हस्ताक्षर किए जाते हैं। क्रेडेंशियल्स पर हमेशा सूची में पहली कुंजी के साथ हस्ताक्षर किए जाएंगे, इसलिए आपको कम से कम एक मान प्रदान करना होगा। आप कुंजी घुमाने के लिए एकाधिक कुंजियाँ प्रदान कर सकते हैं
cookieSerializeOptions
Set-Cookie
हेडर जेनरेट करते समय कुकी को दिए गए विकल्प हैं। अधिक जानकारी के लिए कुकी README देखें
serviceAccount
लाइब्रेरी को आपकी फायरबेस सेवाओं का उपयोग करने के लिए अधिकृत करता है।
मिलान करने वाला नेक्स्ट.जेएस सर्वर को /api/login
, /api/logout
, /
और किसी अन्य पथ के विरुद्ध मिडिलवेयर चलाने का निर्देश देता है जो फ़ाइल या एपीआई कॉल नहीं है।
export const config = { matcher: [ "/", "/((?!_next|api|.*\\.).*)", "/api/login", "/api/logout", ], };
आप सोच रहे होंगे कि हम सभी /api/*
कॉल के लिए मिडलवेयर सक्षम क्यों नहीं कर रहे हैं। हम कर सकते थे, लेकिन एपीआई रूट हैंडलर के भीतर ही अप्रमाणित कॉल को संभालना एक अच्छा अभ्यास है। यह इस ट्यूटोरियल के दायरे से थोड़ा बाहर है, लेकिन यदि आप रुचि रखते हैं, तो मुझे बताएं और मैं कुछ उदाहरण तैयार करूंगा!
जैसा कि आप देख सकते हैं, कॉन्फ़िगरेशन न्यूनतम है और स्पष्ट रूप से परिभाषित उद्देश्य के साथ है। अब, आइए अपने /api/login
और /api/logout
एंडपॉइंट पर कॉल करना शुरू करें।
चीजों को यथासंभव सरल बनाने के लिए, आइए डिफ़ॉल्ट Next.js होम पेज को साफ़ करें और इसे कुछ वैयक्तिकृत सामग्री से बदलें
./app/page.tsx
खोलें और इसे पेस्ट करें:
import { getTokens } from "next-firebase-auth-edge"; import { cookies } from "next/headers"; import { notFound } from "next/navigation"; import { clientConfig, serverConfig } from "../config"; export default async function Home() { const tokens = await getTokens(cookies(), { apiKey: clientConfig.apiKey, cookieName: serverConfig.cookieName, cookieSignatureKeys: serverConfig.cookieSignatureKeys, serviceAccount: serverConfig.serviceAccount, }); if (!tokens) { notFound(); } return ( <main className="flex min-h-screen flex-col items-center justify-center p-24"> <h1 className="text-xl mb-4">Super secure home page</h1> <p> Only <strong>{tokens?.decodedToken.email}</strong> holds the magic key to this kingdom! </p> </main> ); }
आइए इसे थोड़ा-थोड़ा करके तोड़ें।
getTokens
फ़ंक्शन को कुकीज़ से उपयोगकर्ता क्रेडेंशियल्स को मान्य करने और निकालने के लिए डिज़ाइन किया गया है
const tokens = await getTokens(cookies(), { apiKey: clientConfig.apiKey, cookieName: serverConfig.cookieName, cookieSignatureKeys: serverConfig.cookieSignatureKeys, serviceAccount: serverConfig.serviceAccount, });
यदि उपयोगकर्ता अप्रमाणित है, या दो गुणों वाली वस्तु है, तो यह null
के साथ हल हो जाती है:
token
जो आईडीटोकन string
है जिसका उपयोग आप बाहरी बैकएंड सेवाओं के लिए एपीआई अनुरोधों को अधिकृत करने के लिए कर सकते हैं। यह थोड़ा दायरे से बाहर है, लेकिन यह उल्लेख करना उचित है कि लाइब्रेरी वितरित सेवा वास्तुकला को सक्षम बनाती है। token
संगत है और सभी प्लेटफार्मों पर सभी आधिकारिक फायरबेस लाइब्रेरी के साथ उपयोग के लिए तैयार है।
decodedToken
जैसा कि नाम से पता चलता है, token
का डिकोडेड संस्करण है, जिसमें उपयोगकर्ता की पहचान करने के लिए आवश्यक सभी जानकारी शामिल है, जिसमें ई-मेल पता, प्रोफ़ाइल चित्र और कस्टम दावे शामिल हैं, जो हमें भूमिकाओं और अनुमतियों के आधार पर पहुंच को प्रतिबंधित करने में सक्षम बनाता है।
tokens
प्राप्त करने के बाद, हम यह सुनिश्चित करने के लिए next/navigation
से नॉटफाउंड फ़ंक्शन का उपयोग करते हैं कि पेज केवल प्रमाणित उपयोगकर्ताओं के लिए ही पहुंच योग्य है।
if (!tokens) { notFound(); }
अंत में, हम कुछ बुनियादी, वैयक्तिकृत उपयोगकर्ता सामग्री प्रस्तुत करते हैं
<main className="flex min-h-screen flex-col items-center justify-center p-24"> <h1 className="text-xl mb-4">Super secure home page</h1> <p> Only <strong>{tokens?.decodedToken.email}</strong> holds the magic key to this kingdom!" </p> </main>
चलिए इसे चलाते हैं.
यदि आपने अपना डेव सर्वर बंद कर दिया है, तो बस npm run dev
चलाएं।
जब आप http://localhost:3000/ तक पहुंचने का प्रयास करते हैं, तो आपको 404 देखना चाहिए: यह पृष्ठ नहीं मिला।
सफलता! हमने अपने रहस्यों को चुभती नज़रों से सुरक्षित रखा है!
firebase
स्थापित करना और फ़ायरबेस क्लाइंट SDK प्रारंभ करना प्रोजेक्ट की रूट डायरेक्टरी पर npm install firebase
चलाएँ
क्लाइंट SDK स्थापित होने के बाद, प्रोजेक्ट रूट डायरेक्टरी में firebase.ts
फ़ाइल बनाएं और निम्नलिखित पेस्ट करें
import { initializeApp } from 'firebase/app'; import { clientConfig } from './config'; export const app = initializeApp(clientConfig);
यह फायरबेस क्लाइंट एसडीके को आरंभ करेगा और क्लाइंट घटकों के लिए ऐप ऑब्जेक्ट को उजागर करेगा
यदि कोई इसे देख ही नहीं सकता तो सुपर सुरक्षित होम पेज का क्या मतलब है? आइए लोगों को हमारे ऐप में प्रवेश देने के लिए एक सरल पंजीकरण पृष्ठ बनाएं।
आइए ./app/register/page.tsx
के अंतर्गत एक नया, आकर्षक पेज बनाएं
"use client"; import { FormEvent, useState } from "react"; import Link from "next/link"; import { getAuth, createUserWithEmailAndPassword } from "firebase/auth"; import { app } from "../../firebase"; import { useRouter } from "next/navigation"; export default function Register() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [confirmation, setConfirmation] = useState(""); const [error, setError] = useState(""); const router = useRouter(); async function handleSubmit(event: FormEvent) { event.preventDefault(); setError(""); if (password !== confirmation) { setError("Passwords don't match"); return; } try { await createUserWithEmailAndPassword(getAuth(app), email, password); router.push("/login"); } catch (e) { setError((e as Error).message); } } return ( <main className="flex min-h-screen flex-col items-center justify-center p-8"> <div className="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700"> <div className="p-6 space-y-4 md:space-y-6 sm:p-8"> <h1 className="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white"> Pray tell, who be this gallant soul seeking entry to mine humble abode? </h1> <form onSubmit={handleSubmit} className="space-y-4 md:space-y-6" action="#" > <div> <label htmlFor="email" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > Your email </label> <input type="email" name="email" value={email} onChange={(e) => setEmail(e.target.value)} id="email" className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="[email protected]" required /> </div> <div> <label htmlFor="password" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > Password </label> <input type="password" name="password" value={password} onChange={(e) => setPassword(e.target.value)} id="password" placeholder="••••••••" className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required /> </div> <div> <label htmlFor="confirm-password" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > Confirm password </label> <input type="password" name="confirm-password" value={confirmation} onChange={(e) => setConfirmation(e.target.value)} id="confirm-password" placeholder="••••••••" className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required /> </div> {error && ( <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert" > <span className="block sm:inline">{error}</span> </div> )} <button type="submit" className="w-full text-white bg-gray-600 hover:bg-gray-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-gray-600 dark:hover:bg-gray-700 dark:focus:ring-primary-800" > Create an account </button> <p className="text-sm font-light text-gray-500 dark:text-gray-400"> Already have an account?{" "} <Link href="/login" className="font-medium text-gray-600 hover:underline dark:text-gray-500" > Login here </Link> </p> </form> </div> </div> </main> ); }
मुझे पता है। यह बहुत सारा पाठ है, लेकिन धैर्य रखें।
हम "use client";
यह इंगित करने के लिए कि पंजीकरण पृष्ठ क्लाइंट-साइड एपीआई का उपयोग करेगा
const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [confirmation, setConfirmation] = useState(""); const [error, setError] = useState("");
फिर, हम अपनी फॉर्म स्थिति को बनाए रखने के लिए कुछ वेरिएबल्स और सेटर्स को परिभाषित करते हैं
const router = useRouter(); async function handleSubmit(event: FormEvent) { event.preventDefault(); setError(""); if (password !== confirmation) { setError("Passwords don't match"); return; } try { await createUserWithEmailAndPassword(getAuth(app), email, password); router.push("/login"); } catch (e) { setError((e as Error).message); } }
यहां, हम अपने फॉर्म सबमिशन तर्क को परिभाषित करते हैं। सबसे पहले, हम सत्यापित करते हैं कि password
और confirmation
बराबर हैं या नहीं, अन्यथा हम त्रुटि स्थिति को अपडेट करते हैं। यदि मान मान्य हैं, तो हम firebase/auth
से createUserWithEmailAndPassword
के साथ उपयोगकर्ता खाता बनाते हैं। यदि यह चरण विफल हो जाता है (उदाहरण के लिए ई-मेल लिया जाता है), तो हम त्रुटि को अपडेट करके उपयोगकर्ता को सूचित करते हैं।
यदि सब कुछ ठीक रहता है, तो हम उपयोगकर्ता को /login
पेज पर रीडायरेक्ट करते हैं। आप शायद अभी भ्रमित हैं, और आपका ऐसा होना सही है। /login
पेज अभी मौजूद नहीं है. हम बस इसकी तैयारी कर रहे हैं कि आगे क्या होने वाला है।
जब आप http://localhost:3000/register पर जाते हैं, तो पेज लगभग इस तरह दिखना चाहिए:
अब, जब उपयोगकर्ता पंजीकरण करने में सक्षम हैं, तो उन्हें अपनी पहचान साबित करने दें
./app/login/page.tsx
के अंतर्गत एक लॉगिन पेज बनाएं
"use client"; import { FormEvent, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { getAuth, signInWithEmailAndPassword } from "firebase/auth"; import { app } from "../../firebase"; export default function Login() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(""); const router = useRouter(); async function handleSubmit(event: FormEvent) { event.preventDefault(); setError(""); try { const credential = await signInWithEmailAndPassword( getAuth(app), email, password ); const idToken = await credential.user.getIdToken(); await fetch("/api/login", { headers: { Authorization: `Bearer ${idToken}`, }, }); router.push("/"); } catch (e) { setError((e as Error).message); } } return ( <main className="flex min-h-screen flex-col items-center justify-center p-8"> <div className="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700"> <div className="p-6 space-y-4 md:space-y-6 sm:p-8"> <h1 className="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white"> Speak thy secret word! </h1> <form onSubmit={handleSubmit} className="space-y-4 md:space-y-6" action="#" > <div> <label htmlFor="email" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > Your email </label> <input type="email" name="email" value={email} onChange={(e) => setEmail(e.target.value)} id="email" className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="[email protected]" required /> </div> <div> <label htmlFor="password" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > Password </label> <input type="password" name="password" value={password} onChange={(e) => setPassword(e.target.value)} id="password" placeholder="••••••••" className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required /> </div> {error && ( <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert" > <span className="block sm:inline">{error}</span> </div> )} <button type="submit" className="w-full text-white bg-gray-600 hover:bg-gray-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-gray-600 dark:hover:bg-gray-700 dark:focus:ring-primary-800" > Enter </button> <p className="text-sm font-light text-gray-500 dark:text-gray-400"> Don't have an account?{" "} <Link href="/register" className="font-medium text-gray-600 hover:underline dark:text-gray-500" > Register here </Link> </p> </form> </div> </div> </main> ); }
जैसा कि आप देख रहे हैं, यह काफी हद तक पंजीकरण पृष्ठ के समान है। आइए महत्वपूर्ण बिंदु पर ध्यान दें:
async function handleSubmit(event: FormEvent) { event.preventDefault(); setError(""); try { const credential = await signInWithEmailAndPassword( getAuth(app), email, password ); const idToken = await credential.user.getIdToken(); await fetch("/api/login", { headers: { Authorization: `Bearer ${idToken}`, }, }); router.push("/"); } catch (e) { setError((e as Error).message); } }
यहीं पर सारा जादू घटित होता है। हम उपयोगकर्ता का idToken
प्राप्त करने के लिए firebase/auth
से signInEmailAndPassword
उपयोग करते हैं।
फिर, हम मिडलवेयर द्वारा उजागर /api/login
एंडपॉइंट को कॉल करते हैं। यह एंडपॉइंट हमारे ब्राउज़र कुकीज़ को उपयोगकर्ता क्रेडेंशियल्स के साथ अपडेट करता है।
अंत में, हम router.push("/");
लॉगिन पेज मोटे तौर पर इस तरह दिखना चाहिए
आइए इसका परीक्षण करें!
http://localhost:3000/register पर जाएं, खाता बनाने के लिए कुछ यादृच्छिक ई-मेल पता और पासवर्ड दर्ज करें। http://localhost:3000/लॉगिन पेज में उन क्रेडेंशियल्स का उपयोग करें। एंटर पर क्लिक करने के बाद, आपको सुपर सिक्योर होम पेज पर पुनः निर्देशित किया जाएगा
आख़िरकार हमें अपना निजी , अत्यंत सुरक्षित होम पेज देखने को मिल गया! पर रुको! हम कैसे बाहर निकलें?
हमें खुद को दुनिया से हमेशा के लिए (या 12 दिन) लॉक न करने के लिए एक लॉगआउट बटन जोड़ने की जरूरत है।
शुरू करने से पहले, हमें एक क्लाइंट घटक बनाना होगा जो फायरबेस क्लाइंट एसडीके का उपयोग करके हमें साइन आउट करने में सक्षम होगा।
आइए ./app/HomePage.tsx
के अंतर्गत एक नई फ़ाइल बनाएं
"use client"; import { useRouter } from "next/navigation"; import { getAuth, signOut } from "firebase/auth"; import { app } from "../firebase"; interface HomePageProps { email?: string; } export default function HomePage({ email }: HomePageProps) { const router = useRouter(); async function handleLogout() { await signOut(getAuth(app)); await fetch("/api/logout"); router.push("/login"); } return ( <main className="flex min-h-screen flex-col items-center justify-center p-24"> <h1 className="text-xl mb-4">Super secure home page</h1> <p className="mb-8"> Only <strong>{email}</strong> holds the magic key to this kingdom! </p> <button onClick={handleLogout} className="text-white bg-gray-600 hover:bg-gray-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-gray-600 dark:hover:bg-gray-700 dark:focus:ring-primary-800" > Logout </button> </main> ); }
जैसा कि आपने देखा होगा, यह हमारे ./app/page.tsx
का थोड़ा संशोधित संस्करण है। हमें एक अलग क्लाइंट घटक बनाना पड़ा, क्योंकि getTokens
केवल सर्वर घटकों और एपीआई रूट हैंडलर के अंदर काम करता है, जबकि signOut
और useRouter
क्लाइंट संदर्भ में चलाने की आवश्यकता होती है। मुझे पता है कि यह थोड़ा जटिल है, लेकिन वास्तव में यह काफी शक्तिशाली है। मैं बाद में समझाऊंगा.
आइए लॉगआउट प्रक्रिया पर ध्यान दें
const router = useRouter(); async function handleLogout() { await signOut(getAuth(app)); await fetch("/api/logout"); router.push("/login"); }
सबसे पहले, हम फायरबेस क्लाइंट एसडीके से साइन आउट करते हैं। फिर, हम मिडलवेयर द्वारा उजागर /api/logout
एंडपॉइंट को कॉल करते हैं। हम उपयोगकर्ता को /login
पेज पर रीडायरेक्ट करके समाप्त करते हैं।
आइए अपने सर्वर होम पेज को अपडेट करें। ./app/page.tsx
पर जाएं और निम्नलिखित पेस्ट करें
import { getTokens } from "next-firebase-auth-edge"; import { cookies } from "next/headers"; import { notFound } from "next/navigation"; import { clientConfig, serverConfig } from "../config"; import HomePage from "./HomePage"; export default async function Home() { const tokens = await getTokens(cookies(), { apiKey: clientConfig.apiKey, cookieName: serverConfig.cookieName, cookieSignatureKeys: serverConfig.cookieSignatureKeys, serviceAccount: serverConfig.serviceAccount, }); if (!tokens) { notFound(); } return <HomePage email={tokens?.decodedToken.email} />; }
अब, हमारा Home
सर्वर घटक केवल उपयोगकर्ता टोकन लाने और उसे HomePage
क्लाइंट घटक तक पहुंचाने के लिए जिम्मेदार है। यह वास्तव में काफी सामान्य और उपयोगी पैटर्न है।
आइए इसका परीक्षण करें:
वोइला! अब हम अपनी इच्छानुसार एप्लिकेशन से लॉगइन और लॉगआउट कर सकते हैं। यह एकदम सही है!
या यह है?
जब अप्रमाणित उपयोगकर्ता http://localhost:3000/ खोलकर होम पेज में प्रवेश करने का प्रयास करता है तो हम 404 दिखाते हैं: यह पेज नहीं मिल सका।
साथ ही, प्रमाणित उपयोगकर्ता अभी भी लॉग आउट किए बिना http://localhost:3000/register और http://localhost:3000/login पेज तक पहुंचने में सक्षम हैं।
हम बेहतर कर सकते हैं.
ऐसा लगता है कि हमें कुछ पुनर्निर्देशन तर्क जोड़ने की आवश्यकता है। आइए कुछ नियम परिभाषित करें:
/register
और /login
पृष्ठों तक पहुंचने का प्रयास करता है, तो हमें उन्हें /
पर रीडायरेक्ट करना चाहिए/
पेज तक पहुंचने का प्रयास करता है, तो हमें उन्हें /login
पर रीडायरेक्ट करना चाहिए
नेक्स्ट.जेएस ऐप्स में रीडायरेक्ट को संभालने के लिए मिडलवेयर सबसे अच्छे तरीकों में से एक है। सौभाग्य से, authMiddleware
रीडायरेक्ट परिदृश्यों की विस्तृत श्रृंखला को संभालने के लिए कई विकल्पों और सहायक कार्यों का समर्थन करता है।
आइए middleware.ts
फ़ाइल खोलें और इस अद्यतन संस्करण को पेस्ट करें
import { NextRequest, NextResponse } from "next/server"; import { authMiddleware, redirectToHome, redirectToLogin } from "next-firebase-auth-edge"; import { clientConfig, serverConfig } from "./config"; const PUBLIC_PATHS = ['/register', '/login']; export async function middleware(request: NextRequest) { return authMiddleware(request, { loginPath: "/api/login", logoutPath: "/api/logout", apiKey: clientConfig.apiKey, cookieName: serverConfig.cookieName, cookieSignatureKeys: serverConfig.cookieSignatureKeys, cookieSerializeOptions: serverConfig.cookieSerializeOptions, serviceAccount: serverConfig.serviceAccount, handleValidToken: async ({token, decodedToken}, headers) => { if (PUBLIC_PATHS.includes(request.nextUrl.pathname)) { return redirectToHome(request); } return NextResponse.next({ request: { headers } }); }, handleInvalidToken: async (reason) => { console.info('Missing or malformed credentials', {reason}); return redirectToLogin(request, { path: '/login', publicPaths: PUBLIC_PATHS }); }, handleError: async (error) => { console.error('Unhandled authentication error', {error}); return redirectToLogin(request, { path: '/login', publicPaths: PUBLIC_PATHS }); } }); } export const config = { matcher: [ "/", "/((?!_next|api|.*\\.).*)", "/api/login", "/api/logout", ], };
ऐसा ही होना चाहिए. हमने सभी रीडायरेक्ट नियम लागू कर दिए हैं. आइए इसे तोड़ें।
const PUBLIC_PATHS = ['/register', '/login'];
handleValidToken: async ({token, decodedToken}, headers) => { if (PUBLIC_PATHS.includes(request.nextUrl.pathname)) { return redirectToHome(request); } return NextResponse.next({ request: { headers } }); },
handleValidToken
तब कॉल किया जाता है जब वैध उपयोगकर्ता क्रेडेंशियल अनुरोध से जुड़े होते हैं, अर्थात। उपयोगकर्ता प्रमाणित है. इसे पहले तर्क के रूप में tokens
ऑब्जेक्ट और दूसरे तर्क के रूप में संशोधित अनुरोध हेडर कहा जाता है। इसे NextResponse
के साथ हल करना चाहिए।
next-firebase-auth-edge
से redirectToHome
एक सहायक फ़ंक्शन है जो एक ऑब्जेक्ट लौटाता है जिसे NextResponse.redirect(new URL(“/“))
में सरल बनाया जा सकता है
PUBLIC_PATHS.includes(request.nextUrl.pathname)
की जाँच करके, हम सत्यापित करते हैं कि क्या प्रमाणित उपयोगकर्ता /login
या /register
पृष्ठ तक पहुँचने का प्रयास करता है, और यदि ऐसा है तो होम पर रीडायरेक्ट करते हैं।
handleInvalidToken: async (reason) => { console.info('Missing or malformed credentials', {reason}); return redirectToLogin(request, { path: '/login', publicPaths: PUBLIC_PATHS }); },
जब कुछ अपेक्षित होता है तो handleInvalidToken
कॉल किया जाता है। इस अपेक्षित घटनाओं में से एक यह है कि उपयोगकर्ता आपके ऐप को पहली बार किसी अन्य डिवाइस से देख रहा है, या क्रेडेंशियल समाप्त होने के बाद।
यह जानने के बाद कि handleInvalidToken
को अप्रमाणित उपयोगकर्ता के लिए बुलाया जाता है, हम दूसरे नियम के साथ आगे बढ़ सकते हैं: जब अप्रमाणित उपयोगकर्ता /
पेज तक पहुंचने का प्रयास करता है, तो हमें उन्हें /login
पर रीडायरेक्ट करना चाहिए
क्योंकि पूरा करने के लिए कोई अन्य शर्त नहीं है, हम केवल redirectToLogin
का परिणाम लौटाते हैं जिसे NextResponse.redirect(new URL(“/login”))
में सरल बनाया जा सकता है। यह यह भी सुनिश्चित करता है कि उपयोगकर्ता रीडायरेक्ट लूप में न पड़े।
अंततः,
handleError: async (error) => { console.error('Unhandled authentication error', {error}); return redirectToLogin(request, { path: '/login', publicPaths: PUBLIC_PATHS }); }
handleInvalidToken
के विपरीत, handleError
तब कॉल किया जाता है जब कुछ अप्रत्याशित* होता है और संभवतः जांच की आवश्यकता होती है। आप दस्तावेज़ीकरण में उनके विवरण के साथ संभावित त्रुटियों की एक सूची पा सकते हैं
किसी त्रुटि की स्थिति में, हम इस तथ्य को लॉग करते हैं और उपयोगकर्ता को सुरक्षित रूप से लॉगिन पेज पर रीडायरेक्ट करते हैं
* Google सार्वजनिक कुंजी अपडेट होने के बाद handleError
INVALID_ARGUMENT
त्रुटि के साथ कॉल किया जा सकता है।
यह कुंजी घुमाव का एक रूप है और अपेक्षित है। अधिक जानकारी के लिए यह Github अंक देखें
अब, बस इतना ही. अंत में।
आइए अपने वेब ऐप से लॉग-आउट करें और http://localhost:3000/ खोलें। हमें /login
पेज पर पुनः निर्देशित किया जाना चाहिए।
आइए फिर से लॉग इन करें, और http://localhost:3000/login दर्ज करने का प्रयास करें। हमें /
पेज पर पुनर्निर्देशित किया जाना चाहिए।
हमने न केवल सहज उपयोगकर्ता अनुभव प्रदान किया। next-firebase-auth-edge
शून्य-बंडल आकार की लाइब्रेरी है जो केवल ऐप के सर्वर में काम कर रही है और अतिरिक्त क्लाइंट-साइड कोड पेश नहीं करती है। परिणामी बंडल वास्तव में न्यूनतम है। इसे ही मैं परिपूर्ण कहता हूं।
हमारा ऐप अब सर्वर और क्लाइंट दोनों घटकों में फायरबेस प्रमाणीकरण के साथ पूरी तरह से एकीकृत है। हम Next.js की पूरी क्षमता का उपयोग करने के लिए तैयार हैं!
ऐप का सोर्स कोड Next-firebase-auth-edge/examples/next-typescript-minimal में पाया जा सकता है
इस गाइड में, हमने फायरबेस प्रमाणीकरण के साथ नए नेक्स्ट.जेएस ऐप को एकीकृत किया है।
हालांकि काफी व्यापक, लेख ने प्रमाणीकरण प्रवाह के कुछ महत्वपूर्ण हिस्सों को छोड़ दिया, जैसे कि पासवर्ड रीसेट फॉर्म या ईमेल और पासवर्ड के अलावा अन्य तरीकों से साइन इन करना।
यदि आप लाइब्रेरी में रुचि रखते हैं, तो आप संपूर्ण नेक्स्ट-फायरबेस-ऑथ-एज स्टार्टर डेमो पेज का पूर्वावलोकन कर सकते हैं।
इसमें फायरस्टोर इंटीग्रेशन , सर्वर एक्शन , ऐप-चेक सपोर्ट और बहुत कुछ शामिल है
लाइब्रेरी ढेर सारे उदाहरणों के साथ एक समर्पित दस्तावेज़ीकरण पृष्ठ प्रदान करती है
यदि आपको लेख पसंद आया, तो मैं नेक्स्ट-फायरबेस-ऑथ-एज रिपॉजिटरी अभिनीत की सराहना करूंगा। प्रोत्साहित करना! 🎉
यह बोनस गाइड आपको सिखाएगा कि अपने नेक्स्ट.जेएस ऐप को वर्सेल में कैसे तैनात किया जाए
वर्सेल में तैनात करने में सक्षम होने के लिए, आपको अपने नए ऐप के लिए एक रिपॉजिटरी बनाने की आवश्यकता होगी।
https://github.com/ पर जाएं और एक नया रिपॉजिटरी बनाएं।
create-next-app
पहले ही हमारे लिए एक स्थानीय git रिपॉजिटरी शुरू कर दी है, इसलिए आपको बस अपने प्रोजेक्ट के रूट फ़ोल्डर का अनुसरण करना होगा और चलाना होगा:
git add --all git commit -m "first commit" git branch -M main git remote add origin [email protected]:path-to-your-new-github-repository.git git push -u origin main
https://vercel.com/ पर जाएं और अपने Github खाते से साइन इन करें
लॉग इन करने के बाद, वर्सेल के अवलोकन पृष्ठ पर जाएं और नया जोड़ें > प्रोजेक्ट पर क्लिक करें
हमारे द्वारा अभी बनाए गए Github रिपॉजिटरी के आगे आयात पर क्लिक करें। अभी तक तैनात न करें.
तैनात करने से पहले, हमें प्रोजेक्ट कॉन्फ़िगरेशन प्रदान करना होगा। आइए कुछ पर्यावरण चर जोड़ें:
USE_SECURE_COOKIES
true
पर सेट करना याद रखें, क्योंकि वर्सेल डिफ़ॉल्ट रूप से HTTPS का उपयोग करता है
अब, हम डिप्लॉय पर क्लिक करने के लिए तैयार हैं
एक या दो मिनट प्रतीक्षा करें, और आप इस जैसे यूआरएल के साथ अपने ऐप तक पहुंचने में सक्षम होंगे: https://next-typescript-minimal-xi.vercel.app/
हो गया। मुझे यकीन है कि आपने यह इतना आसान होने की उम्मीद नहीं की होगी।
यदि आपको मार्गदर्शिका पसंद आई, तो मैं नेक्स्ट-फायरबेस-ऑथ-एज रिपोजिटरी अभिनीत करने की सराहना करूंगा।
आप मुझे टिप्पणियों में अपनी प्रतिक्रिया भी बता सकते हैं। प्रोत्साहित करना! 🎉