تقنية

كيفية استخدام Google OAuth 2.0 للوصول إلى Google APIs باستخدام رمز التحديث


لنقم بإنشاء تطبيق ويب بسيط يستخدم Google OAuth 2.0 للوصول إلى Google APIs. يمكن للمستخدم تسجيل الدخول باستخدام حساب Google الخاص به والسماح للتطبيق بالوصول إلى Google Drive أو أي خدمة أخرى من خدمات Google.

عندما يقوم المستخدم بتسجيل الدخول، تعيد Google توجيه المستخدم إلى صفحة تفويض Google OAuth 2.0. يطلب من المستخدم منح حق الوصول إلى التطبيق. يقوم التطبيق بعد ذلك بتبادل رمز التفويض لرمز الوصول ورمز التحديث. ستنتهي صلاحية رمز الوصول بعد ساعة ولكن رمز التحديث سيكون صالحًا إلى أجل غير مسمى (ما لم يتم إبطاله يدويًا بواسطة المستخدم).

وبالتالي، سنقوم بتخزين رمز التحديث في Cloud Firestore، واستخدامه لإنشاء رمز وصول جديد عندما يحتاج التطبيق إلى الوصول إلى Google APIs نيابة عن المستخدم.

نحن لا نستخدم تسجيل الدخول إلى Google باستخدام مصادقة Firebase لأنها لا توفر رمز التحديث المطلوب لتشغيل مهام واجهة برمجة التطبيقات في الخلفية دون مراقبة.

الخطوة 1: إنشاء عميل Google OAuth 2.0

قم بإنشاء عميل OAuth 2.0 جديد داخل مشروع Google Cloud الخاص بك كما هو موضح في هذا الدليل خطوة بخطوة.

داخل Google Cloud Console، انتقل إلى APIs & Services القسم، انقر على Credentials وانقر على Create credentials > OAuth Client Id لإنشاء معرف عميل جديد.

أثناء التطوير، يمكنك وضع https://localhost:5001/oauthCallback باعتباره URI لإعادة التوجيه نظرًا لأن محاكي Firebase، افتراضيًا، سيقوم بتشغيل تطبيق الويب محليًا على المنفذ 5001.

قم بتدوين معرف العميل وسر العميل المقدم من Google.

الخطوة 2: تهيئة وظيفة Firebase

افتح المحطة الطرفية الخاصة بك، وقم بإنشاء دليل مشروع جديد وقم بتهيئة مشروع Firebase.

$ mkdir oauth2-application
$ cd oauth2-application
$ npx firebase init functions
$ npm install googleapis

يمكنك اختيار Use an existing Firebase project الخيار ثم حدد مشروع Google Cloud الخاص بك باستخدام الوظيفة. التبديل إلى functions دليل.

الخطوة 3. تهيئة متغيرات بيئة Firebase

إنشاء جديد .env ملف وإضافة متغيرات البيئة التالية:

CLIENT_ID=<your client ID>
CLIENT_SECRET=<your client secret>
REDIRECT_URI=<your redirect URI>

الخطوة 4. إنشاء عنوان URL للتفويض

سنقوم بإنشاء وظيفة تنشئ عنوان URL للتفويض للمستخدم لتسجيل الدخول باستخدام حساب Google الخاص به. بالإضافة إلى drive النطاق، طلبنا يطلب أيضًا userinfo.email نطاق للحصول على عنوان البريد الإلكتروني للمستخدم.

const functions = require('firebase-functions');
const { google } = require('googleapis');

exports.googleLogin = functions.https.onRequest((request, response) => {
  const SCOPES = [
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/drive.metadata.readonly'
  ];
  const oAuth2Client = new google.auth.OAuth2(
    process.env.CLIENT_ID,
    process.env.CLIENT_SECRET,
    process.env.REDIRECT_URI
  );
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES,
    prompt: 'consent',
    login_hint: request.query.email_address || ''
  });
  response.set('Cache-Control', 'private, max-age=0, s-maxage=0');
  response.redirect(authUrl);
});

قمنا بتعيين access_type ل offline للحصول على رمز التحديث. ال consent تم ضبطه على prompt لإجبار المستخدم على الموافقة على التطبيق. قمنا أيضًا بتعيين login_hint إلى عنوان البريد الإلكتروني للمستخدم إذا قام بتسجيل الدخول إلى حسابات Google متعددة.

الخطوة 5. قم بتخزين رمز التحديث

بمجرد قيام المستخدم بتسجيل الدخول، تقوم Google بإعادة توجيه المستخدم إلى عنوان URL لإعادة التوجيه. يحتوي URI لإعادة التوجيه على رمز التفويض الذي نحتاج إلى استبداله برمز وصول ورمز تحديث لتخزينه في قاعدة البيانات.

const functions = require('firebase-functions');
const { firestore as adminFirestore } = require('firebase-admin');
const { google } = require('googleapis');

admin.initializeApp();

exports.oAuthCallback = functions.https.onRequest(async (request, response) => {
  const { query: { error, code } = {} } = request;

  // User may deny access to the application.
  if (error) {
    response.status(500).send(error);
    return;
  }

  const oAuth2Client = new google.auth.OAuth2(
    process.env.CLIENT_ID,
    process.env.CLIENT_SECRET,
    process.env.REDIRECT_URI
  );

  // Exchange the authorization code for an access token.
  const { tokens } = await oAuth2Client.getToken(code);

  oAuth2Client.setCredentials(tokens);
  const oauth2 = google.oauth2({
    auth: oAuth2Client,
    version: 'v2',
  });

  // Get the user's email address and Google user ID
  const { data } = await oauth2.userinfo.get();
  const { id, email } = data;
  const { refresh_token } = tokens;

  // Store the refresh token in the Firestore database.
  // Set merge: true to not overwrite any other data in the same document
  const firestore = adminFirestore();
  const usersCollection = firestore.collection('users');
  await usersCollection.doc(id).set({ id, email, refresh_token }, { merge: true });

  response.set('Cache-Control', 'private, max-age=0, s-maxage=0');
  response.send(`User ${email} is authorized! ${id}`);
});

إليك كيفية تخزين المستندات في قاعدة بيانات Firestore NoSQL:

رمز الوصول إلى Firestore

الخطوة 6: الوصول إلى واجهات برمجة تطبيقات Google

الآن بعد أن حصلنا على رمز التحديث، يمكننا استخدامه لإنشاء رمز وصول جديد والوصول إلى Google APIs. في مثالنا، ستعيد وظيفة محرك الأقراص أحدث 5 ملفات من Google Drive للمستخدم المصرح له.

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const { google } = require('googleapis');

admin.initializeApp();

exports.drive = functions.https.onRequest(async (request, response) => {
  const { user_id = '' } = request.query;
  const user = await admin.firestore().collection('users').doc(user_id).get();
  if (!user.exists) {
    response.status(404).send(`User ${user_id} not found`);
    return;
  }

  const { refresh_token } = user.data();
  const oAuth2Client = new google.auth.OAuth2(
    process.env.CLIENT_ID,
    process.env.CLIENT_SECRET,
    process.env.REDIRECT_URI
  );
  oAuth2Client.setCredentials({ refresh_token });

  const googleDrive = google.drive({ version: 'v3', auth: oAuth2Client });
  const { data: { files = [] } = {} } = await googleDrive.files.list({
    pageSize: 5,
    fields: 'files(id, name)'
  });

  response.status(200).send({ files });
});

الخطوة 7: إنشاء وظيفة Firebase Cloud

يمكنك تشغيل الأمر التالي لاختبار الوظائف محليًا:

firebase emulators:start --only functions

عندما تكون مستعدًا لنشر الوظائف في مشروع Firebase الخاص بك، يمكنك تشغيل الأمر التالي:

firebase deploy --only functions



Source link

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى