Google OAuth — Passport bilan
OAuth nima?
Foydalanuvchi "Google bilan kirish" tugmasini bosadi. Nima bo'ladi?
Siz Google ga parolni bermaysiz — Google o'zi tekshiradi. Google sizga faqat "bu foydalanuvchi kim" degan ma'lumotni beradi. Bu — OAuth.
Hayotiy o'xshatma: mehmonxonaga keldingiz. Pasportingizni ko'rsatasiz — mehmonxona xodimi pasportni o'qiydi, lekin saqlamaydi. Faqat "bu kishi kim" degan ma'lumotni oladi. Pasportingiz sizda qoladi.
OAuth da Google — pasport beruvchi davlat. Sizning ilovangiz — mehmonxona. Foydalanuvchi — mehmon.
Google Console da sozlash
Kod yozishdan oldin Google Console da loyiha yaratish kerak:
- console.cloud.google.com ga kiring
- Yangi loyiha yarating
- "APIs & Services" → "Credentials" → "Create Credentials" → "OAuth 2.0 Client ID"
- Application type: "Web application"
- Authorized redirect URIs:
http://localhost:3000/auth/google/callback Client IDvaClient Secretni oling —.envga saqlang
npm install passport-google-oauth20
Strategiya sozlash
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
},
async (accessToken, refreshToken, profile, done) => {
// profile — Google dan kelgan foydalanuvchi ma'lumoti
try {
const email = profile.emails[0].value;
const name = profile.displayName;
// Foydalanuvchi allaqachon ro'yxatdan o'tganmi?
let result = await pool.query('SELECT * FROM users WHERE google_id = $1', [profile.id]);
if (result.rows.length > 0) {
return done(null, result.rows[0]); // mavjud foydalanuvchi
}
// Yangi foydalanuvchi — yaratish
result = await pool.query(
'INSERT INTO users (name, email, google_id) VALUES ($1, $2, $3) RETURNING *',
[name, email, profile.id]
);
return done(null, result.rows[0]);
} catch (err) {
return done(err);
}
}
));
profile — Google dan kelgan ma'lumot: profile.id (Google ID), profile.displayName (ism), profile.emails[0].value (email).
Route lar
// 1. Foydalanuvchini Google ga yo'naltirish
router.get('/auth/google',
passport.authenticate('google', { scope: ['profile', 'email'] })
);
// 2. Google qaytib kelganda
router.get('/auth/google/callback',
passport.authenticate('google', { session: false, failureRedirect: '/login' }),
(req, res) => {
// Muvaffaqiyatli — JWT yaratib frontendga yuborish
const token = jwt.sign(
{ userId: req.user.id, role: req.user.role },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
// Frontend ga token bilan yo'naltirish
res.redirect(`${process.env.FRONTEND_URL}/auth/callback?token=${token}`);
}
);
Jarayon qanday ishlaydi:
Foydalanuvchi /auth/google ga boradi
↓
Express → Google login sahifasiga yo'naltiradi
↓
Foydalanuvchi Google da login qiladi
↓
Google → /auth/google/callback ga qaytaradi
↓
Passport strategiya ishlaydi — foydalanuvchi topiladi/yaratiladi
↓
JWT yaratiladi, frontend ga yuboriladi
scope nima?
scope: ['profile', 'email'] — Google dan qanday ma'lumot so'ralishi. profile — ism, rasm. email — email manzil. Foydalanuvchi login qilganda Google "bu ilova sizning profilingiz va emailingizni ko'rmoqchi" deb so'raydi.
Faqat kerakli ma'lumotlar so'raladi — bu yaxshi amaliyot.
Ma'lumotlar bazasi jadval
ALTER TABLE users ADD COLUMN google_id VARCHAR(255) UNIQUE;
ALTER TABLE users ALTER COLUMN password_hash DROP NOT NULL;
-- Google bilan kirgan foydalanuvchining paroli bo'lmaydi
Tez-tez uchraydigan xatolar
Redirect URI mos kelmasa:
Error: redirect_uri_mismatch
Google Console da yozilgan redirect URI va kodda yozilgan bir xil bo'lishi kerak. http va https, localhost:3000 va localhost:3001 — farq qiladi.
scope ni unutish:
passport.authenticate('google') // scope yo'q — email kelmaydi
passport.authenticate('google', { scope: ['profile', 'email'] }) // to'g'ri
Xulosa
OAuth — foydalanuvchi parolini bermaydi, Google o'zi tekshiradi va "bu kim" degan ma'lumotni beradi.
Google Console da Client ID va Secret olinadi. Strategiya foydalanuvchini Google ID bo'yicha topadi yoki yangi yaratadi. Muvaffaqiyatli bo'lgach JWT yaratiladi.
Keyingi dars
24-dars: Session — express-session, cookie-session