Theory
તમે કોણ છો, અને તમે આ કરી શકો?
FestConnect ને ખબર હોવી જોઈએ કે દરેક વપરાશકર્તા કોણ છે (authentication), અને જે કામ અમુક વપરાશકર્તાઓ જ કરી શકે એમને સાચવવાં પણ પડે. સલામત login જાતે બનાવવું, એટલે કે passwords ને hash કરવા અને sessions સંભાળવાં, અઘરું છે અને એમાં ખતરનાક ભૂલ થવી સહેલી છે. એટલે FestConnect એ કામ Firebase Authentication ને સોંપે છે.
Firebase નોંધણી અને login સંભાળે છે; સફળ થાય ત્યારે એ app ને એવો token આપે છે જે વપરાશકર્તા કોણ છે તે સાબિત કરે છે. Angular નું front end એ token requests સાથે મોકલે છે, અને Express નું backend સાચવેલાં કામ કરવા દેતાં પહેલાં એને verify કરે છે. આ છેલ્લો પાઠ એ જ પ્રવાહ સમજાવે છે, જે app ની સલામતીની કરોડરજ્જુ છે.
Theory
Firebase Auth અને token (JWT)
Firebase Authentication તૈયાર નોંધણી અને login આપે છે (બીજી રીતો ઉપરાંત email અને password પણ), એટલે તમે કાચા passwords કદી જાતે સાચવતા નથી, એ કામ Firebase સલામત રીતે કરે છે.
વપરાશકર્તા log in કરે ત્યારે Firebase client ને ID token આપે છે, જે JWT (JSON Web Token) છે: નાનકડો, સહી કરેલો token, જે વપરાશકર્તાની ઓળખ સાથે લઈને ફરે છે. એના પર એવી ગુપ્ત ચાવીથી સહી થયેલી હોય છે જેના પર ફક્ત Firebase અને તમારો server ભરોસો કરે છે, એટલે એને પકડાયા વગર બનાવટી બનાવી કે બદલી શકાતો નથી. Angular app ને login વખતે આ token મળે છે અને એ દરેક request સાથે એને મોકલીને વપરાશકર્તાની ઓળખ સાબિત કરે છે. JWT ને એવા ઓળખપત્ર જેવો ગણો જેમાં છેડછાડ થઈ શકતી નથી અને જે વપરાશકર્તા login પછી સાથે રાખે છે.
Practical
Angular: register કરવું, log in કરવું અને token મોકલવો
// Using the Firebase Auth SDK in Angular
import { getAuth, createUserWithEmailAndPassword,
signInWithEmailAndPassword } from 'firebase/auth';
const auth = getAuth();
// register
await createUserWithEmailAndPassword(auth, email, password);
// login
const cred = await signInWithEmailAndPassword(auth, email, password);
const token = await cred.user.getIdToken(); // the JWT
// send it with an API request so the server can verify who you are:
this.http.get('/api/profile', {
headers: { Authorization: `Bearer ${token}` },
}).subscribe(/* ... */);Practical
Express: protected route પીરસતાં પહેલાં token verify કરવો
const admin = require('firebase-admin'); // Firebase Admin SDK
// middleware: verify the token, or reject with 401
async function requireAuth(req, res, next) {
const header = req.headers.authorization || '';
const token = header.replace('Bearer ', '');
try {
req.user = await admin.auth().verifyIdToken(token); // trust only if valid
next();
} catch {
res.status(401).json({ error: 'Not authenticated' });
}
}
app.get('/api/profile', requireAuth, (req, res) => res.json(req.user));This example runs in Gri-Learn on the web, where you can edit it and see the output.
Formula
Client પર કદી ભરોસો નહીં; ખાતરી હંમેશા server પર
અહીં સલામતીનો સોનેરી નિયમ આ છે: front end કંઈ પણ દાવો કરી શકે છે, એટલે server એ ખાતરી કરવી પડે. Browser માં જે ચાલે છે એ કોઈ પણ બદલી શકે છે, એટલે 'હું admin છું' એવું કહેતા request નો કશો અર્થ નથી, જ્યાં સુધી server token તપાસે નહીં.
Express ની બાજુએ Firebase Admin SDK બરાબર એ જ કરે છે: verifyIdToken(token) protected route ચાલે એ પહેલાં ગણિતની રીતે ખાતરી કરે છે કે token અસલી છે અને એની મુદત પૂરી થઈ નથી. Token ન હોય કે ખોટો હોય તો request નકારાય છે (401). UI માં button છુપાવવું એ સલામતી નથી; server પર token verify કરવું એ સલામતી છે. દરેક protected route ને આ જ રીતે સાચવો.
Quiz
વપરાશકર્તા Firebase દ્વારા log in કરે એ પછી, Express backend ને કઈ રીતે ખબર પડે કે protected route પરનું request ખરેખર પ્રમાણિત વપરાશકર્તા તરફથી જ આવ્યું છે?
- Angular app request માં જે દાવો કરે એના પર એ ભરોસો કરી લે છે
- એ request સાથે આવેલા ID token (JWT) ને Firebase Admin SDK (verifyIdToken) વડે verify કરે છે; ખોટો token નકારાય છે
- એ તપાસે છે કે UI માં button દેખાતું હતું કે નહીં
- એને ખબર પડી જ ન શકે; દરેક request ને પ્રવેશ મળે છે
Show the answer
એ request સાથે આવેલા ID token (JWT) ને Firebase Admin SDK (verifyIdToken) વડે verify કરે છે; ખોટો token નકારાય છે
Backend, client એ request સાથે મોકલેલા ID token (સહી કરેલા JWT) ને Firebase Admin SDK ના verifyIdToken વડે verify કરે છે, જે ગણિતની રીતે ખાતરી કરે છે કે token અસલી છે અને વપરાશકર્તાને ઓળખાવે છે; token ન હોય કે ખોટો હોય તો 401 સાથે નકારાય છે. વિકલ્પ A પાયાના નિયમનો ભંગ કરે છે, એટલે કે client ના દાવા પર કદી ભરોસો ન કરવો, કારણ કે request નું body કોઈ પણ બનાવટી બનાવી શકે છે, અને ઓળખ ફક્ત verify થયેલો token જ સાબિત કરે છે. વિકલ્પ C UI ની વિગત છે, સલામતી નહીં: button છુપાવવાથી કોઈને સીધું request ઘડતાં અટકાવી શકાતું નથી, એટલે એ કશું સાબિત કરતું નથી. વિકલ્પ D ખોટો છે: token ની ખાતરી હોય તો server ચોક્કસ જાણી શકે છે (અને જાણવું જ જોઈએ) કે કોણ બોલાવે છે. Token server પર verify કરો; client ના દાવા પર ભરોસો ન કરો.
Think first
ભરોસાપાત્ર ન હોય એવા browser માંથી પસાર થતો સહી કરેલો JWT કેમ ભરોસાપાત્ર ગણાય?
Token વપરાશકર્તાના browser માંથી પસાર થાય છે, જેમાં છેડછાડ થઈ શકે છે. તો પણ server એના પર ભરોસો કેમ કરી શકે? વિચારીને પછી tap કરો.
Show the answer
કારણ કે JWT પર ગણિતની રીતે સહી થયેલી હોય છે, એટલે કોઈ પણ છેડછાડથી સહી તૂટે છે અને server એ પકડી પાડે છે; token ની વિશ્વસનીયતા ગણિતમાંથી આવે છે, browser પરના ભરોસામાંથી નહીં.
Firebase ID token આપે ત્યારે એ token ની અંદરની વિગતો (વપરાશકર્તા કોણ છે, એની મુદત ક્યારે પૂરી થાય છે) પર ગુપ્ત ચાવીથી સહી કરે છે. Server, Firebase Admin SDK વાપરીને, verifyIdToken દરમિયાન એ સહીને Firebase ની જાહેર ચાવીઓ સામે તપાસે છે. જો browser માં token નો એક અક્ષર પણ બદલાય, દાખલા તરીકે user id બદલીને 'admin' કરી દેવાય, તો સહી હવે બદલાયેલી વિગતો સાથે મેળ ખાતી નથી, અને ખાતરી નિષ્ફળ જાય છે, એટલે બનાવટી token નકારાય છે.
હુમલો કરનાર બદલાયેલી વિગતો માટે માન્ય સહી બનાવી શકતો નથી, કારણ કે એની પાસે સહી કરવાની ગુપ્ત ચાવી નથી; ખરેખર સહી કરેલા tokens ફક્ત Firebase જ બનાવી શકે છે. એટલે જ token ને ભરોસાપાત્ર ન હોય એવા browser માંથી પસાર થવા દેવો અને client પાસે મોકલાવવો સલામત છે: server browser પ્રામાણિક હશે એવો ભરોસો કરતો નથી, એ તો ગણિતથી ખાતરી કરે છે કે token Firebase એ જ આપ્યો છે અને એમાં ફેરફાર થયો નથી.
ખાતરી વખતે મુદત પણ તપાસાય છે, એટલે જૂના tokens ચાલતા બંધ થાય છે અને કોઈ token લીક થાય તો પણ નુકસાન મર્યાદિત રહે છે. સહી કરેલા tokens નો આખો સાર આ જ છે: ભરોસો વહનના માધ્યમ પર નહીં, પણ ગણિતના પુરાવા પર બંધાય છે. તૂટેલી સહી એટલે નકારાયેલું request, અને એટલે જ 'token verify કરો' એ ખરી સલામતી છે, જ્યારે 'browser એ કહ્યું' એ સલામતી નથી. સહીઓ token માં થયેલી છેડછાડ ઉઘાડી પાડે છે, એટલે server ભરોસાપાત્ર ન હોય એવી જગ્યાએથી આવેલા token પર પણ ભરોસો કરી શકે છે.
Summary
Key takeaways
- Firebase Authentication વપરાશકર્તાની નોંધણી અને login સંભાળે છે (email અને password ઉપરાંત બીજી રીતો પણ), એટલે passwords તમારે જાતે સાચવવા પડતા નથી.
- Login વખતે Firebase client ને ID token આપે છે, જે વપરાશકર્તાની ઓળખ સાથે લઈને ફરતો સહી કરેલો JWT છે.
- Angular નું front end એ token requests સાથે મોકલે છે (Authorization: Bearer <token>), જેથી વપરાશકર્તા કોણ છે તે સાબિત થાય.
- Express નું backend protected route પીરસતાં પહેલાં Firebase Admin SDK (verifyIdToken) વડે token verify કરે છે; ખોટો હોય તો 401.
- સોનેરી નિયમ: client ના દાવા પર કદી ભરોસો ન કરો; ખાતરી હંમેશા server પર કરો.
- ભરોસાપાત્ર ન હોય એવા browser માંથી પસાર થતો સહી કરેલો JWT એટલા માટે ભરોસાપાત્ર છે કે છેડછાડથી એની સહી તૂટે છે અને ખાતરી (તથા મુદતની તપાસ) એને પકડી પાડે છે.
- યાદ રાખવાની કડી: Firebase વપરાશકર્તાઓને log in કરાવે છે અને JWT આપે છે; server request પર ભરોસો કરતાં પહેલાં એને verify કરે છે.