تسجيل الدخول بحساب Google للتطبيقات من جهة الخادم

لاستخدام خدمات Google نيابةً عن المستخدم عندما يكون غير متصل بالإنترنت، يجب استخدام مسار مختلط من جانب الخادم حيث يفوّض المستخدم تطبيقك على العميل باستخدام عميل واجهة برمجة تطبيقات JavaScript وترسل رسالة خاصة مرة واحدة رمز التفويض إلى خادمك. يتبادل الخادم هذا الإصدار الذي يُستخدم لمرة واحدة للحصول على رمز الدخول وتحديث الرموز المميزة من Google للخادم قادرًا على إجراء طلبات البيانات من واجهة برمجة التطبيقات الخاصة به، والتي يمكن إجراؤها أثناء عدم اتصال المستخدم بالإنترنت. يتميز مسار الرمز البرمجي الذي يتم استخدامه مرة واحدة بمزايا أمنية تتفوق على كلٍ من التشفير الخالص من جهة الخادم وإرسال رموز الدخول إلى الخادم.

مسار تسجيل الدخول للحصول على رمز الدخول من جهة الخادم التطبيق موضح أدناه.

تتمتع الرموز التي تُستخدم مرة واحدة بالعديد من مزايا الأمان. باستخدام الرموز، توفر Google يقدم الرموز المميزة إلى خادمك مباشرةً بدون أي وسطاء. على الرغم من أنّنا لا ننصح تسريب الرموز، فإنّ استخدامها صعب جدًا. بدون سر العميل. حافِظ على سر العميل.

تنفيذ مسار الرمز الذي يُستخدم لمرة واحدة

يوفر زر تسجيل الدخول بحساب Google كلاً من رمز الدخول رمز التفويض. هذا الرمز هو رمز يُستخدم لمرة واحدة ويمكن للخادم تبادله مع خوادم Google للحصول على رمز دخول.

يوضح الرمز النموذجي التالي كيفية إجراء تدفق رمز لمرة واحدة.

تتطلب منك مصادقة "تسجيل الدخول بحساب Google" من خلال مسار رمز لمرة واحدة ما يلي:

الخطوة 1: إنشاء معرِّف عميل وسر عميل

ولإنشاء معرِّف عميل وسر عميل، عليك إنشاء مشروع في وحدة تحكم واجهة برمجة تطبيقات Google. إعداد معرِّف عميل OAuth وتسجيل مصادر JavaScript:

  1. انتقِل إلى وحدة التحكم في واجهة Google API.

  2. من القائمة المنسدلة للمشروع، اختَر مشروعًا حاليًا أو أنشِئ مشروعًا جديدًا. من خلال اختيار إنشاء مشروع جديد

  3. في الشريط الجانبي ضمن "واجهات برمجة التطبيقات "الخدمات"، اختَر بيانات الاعتماد، ثم انقر على ضبط شاشة الموافقة

    اختَر عنوان بريد إلكتروني وحدِّد اسم منتج ثم اضغط على حفظ.

  4. في علامة التبويب بيانات الاعتماد، اختَر القائمة المنسدلة إنشاء بيانات اعتماد. واختر معرِّف عميل OAuth.

  5. ضمن نوع التطبيق، اختَر تطبيق الويب.

    يمكنك تسجيل المصادر التي يُسمح لتطبيقك من خلالها بالوصول إلى Google APIs، على النحو التالي. المصدر هو مجموعة فريدة من البروتوكولات، واسم المضيف والمنفذ.

    1. في حقل مصادر JavaScript المعتمَدة، أدخِل مصدر تطبيقك. يمكنك إدخال مصادر متعددة للسماح بتشغيل تطبيقك على بروتوكولات أو نطاقات أو نطاقات فرعية مختلفة. ولا يمكنك استخدام أحرف البدل. في المثال أدناه، قد يكون عنوان URL الثاني عنوان URL إنتاجية.

      http://localhost:8080
      https://myproductionurl.example.com
      
    2. ولا يتطلب حقل معرّف الموارد المنتظم (URI) لإعادة التوجيه المسموح به أي قيمة. إعادة التوجيه لا يتم استخدام معرفات الموارد المنتظمة (URI) مع واجهات برمجة تطبيقات JavaScript.

    3. اضغط على الزر إنشاء.

  6. من مربع الحوار عميل OAuth الناتج، انسخ معرِّف العميل. تشير رسالة الأشكال البيانية يتيح معرِّف العميل لتطبيقك الوصول إلى Google APIs المفعَّلة.

الخطوة 2: تضمين مكتبة منصّات Google في صفحتك

قم بتضمين النصوص البرمجية التالية التي توضح دالة مجهولة يقوم بإدراج نص برمجي في DOM لصفحة الويب index.html هذه.

<!-- The top of file index.html -->
<html itemscope itemtype="http://schema.org/Article">
<head>
  <!-- BEGIN Pre-requisites -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
  </script>
  <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer>
  </script>
  <!-- END Pre-requisites -->

الخطوة 3: إعداد كائن GoogleAuth

حمِّل مكتبة auth2 واتصل بـ gapi.auth2.init() لإعداد كائن GoogleAuth. تحديد معرِّف العميل والنطاقات التي تريد طلبها عند الاتصال بـ init().

<!-- Continuing the <head> section -->
  <script>
    function start() {
      gapi.load('auth2', function() {
        auth2 = gapi.auth2.init({
          client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
          // Scopes to request in addition to 'profile' and 'email'
          //scope: 'additional_scope'
        });
      });
    }
  </script>
</head>
<body>
  <!-- ... -->
</body>
</html>

الخطوة 4: إضافة زر تسجيل الدخول إلى صفحتك

إضافة زر تسجيل الدخول إلى صفحة الويب وإرفاق معالج النقرات للاتصال grantOfflineAccess() لبدء تدفق التعليمات البرمجية لمرة واحدة.

<!-- Add where you want your sign-in button to render -->
<!-- Use an image that follows the branding guidelines in a real app -->
<button id="signinButton">Sign in with Google</button>
<script>
  $('#signinButton').click(function() {
    // signInCallback defined in step 6.
    auth2.grantOfflineAccess().then(signInCallback);
  });
</script>

الخطوة 5: تسجيل دخول المستخدم

ينقر المستخدم على زر تسجيل الدخول ويمنح تطبيقك إمكانية الوصول إلى الأذونات. الذي طلبته. بعد ذلك، تُستخدم دالة معاودة الاتصال التي حددتها في يتم تمرير طريقة grantOfflineAccess().then() كائن JSON مع رمز التفويض. على سبيل المثال:

{"code":"4/yU4cQZTMnnMtetyFcIWNItG32eKxxxgXXX-Z4yyJJJo.4qHskT-UtugceFc0ZRONyF4z7U4UmAI"}

الخطوة 6: إرسال رمز التفويض إلى الخادم

إنّ code هو رمز يُستخدم لمرة واحدة ويمكن للخادم استبداله بأخرى خاصة به. رمز الدخول وإعادة تحميل الرمز. لا يمكنك الحصول على الرمز المميز لإعادة التحميل إلا بعد تم عرض مربع حوار تفويض يطلب الوصول بلا إنترنت للمستخدم. إذا حددت prompt في select-account في OfflineAccessOptions في الخطوة 4، يجب عليك تخزين الرمز المميز لإعادة التحميل الذي تسترده للاستخدام لاحقًا لأنّ التبادلات اللاحقة ستعرض null للرمز المميز لإعادة التحميل. هذا المسار لتوفير المزيد من الأمان عبر مسار OAuth 2.0 العادي.

يتم إرجاع رموز الدخول دائمًا مع استبدال تفويض صالح الرمز.

يحدّد النص البرمجي التالي وظيفة استدعاء لزر تسجيل الدخول. فعندما بنجاح عملية تسجيل الدخول، تخزن الدالة رمز الدخول الرمز الذي يُستخدم لمرة واحدة ويُرسله إلى خادمك على النطاق نفسه

<!-- Last part of BODY element in file index.html -->
<script>
function signInCallback(authResult) {
  if (authResult['code']) {

    // Hide the sign-in button now that the user is authorized, for example:
    $('#signinButton').attr('style', 'display: none');

    // Send the code to the server
    $.ajax({
      type: 'POST',
      url: 'http://example.com/storeauthcode',
      // Always include an `X-Requested-With` header in every AJAX request,
      // to protect against CSRF attacks.
      headers: {
        'X-Requested-With': 'XMLHttpRequest'
      },
      contentType: 'application/octet-stream; charset=utf-8',
      success: function(result) {
        // Handle or verify the server response.
      },
      processData: false,
      data: authResult['code']
    });
  } else {
    // There was an error.
  }
}
</script>

الخطوة 7: استبدال رمز التفويض برمز دخول

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

إذا طلبت الوصول إلى الملف الشخصي، ستحصل أيضًا على رمز مميز للتعريف يحتوي على معلومات الملف الشخصي للمستخدم.

على سبيل المثال:

Java
// (Receive authCode via HTTPS POST)


if (request.getHeader("X-Requested-With") == null) {
  // Without the `X-Requested-With` header, this request could be forged. Aborts.
}

// Set path to the Web application client_secret_*.json file you downloaded from the
// Google API Console: https://console.cloud.google.com/apis/credentials
// You can also find your Web application client ID and client secret from the
// console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest
// object.
String CLIENT_SECRET_FILE = "/path/to/client_secret.json";

// Exchange auth code for access token
GoogleClientSecrets clientSecrets =
    GoogleClientSecrets.load(
        JacksonFactory.getDefaultInstance(), new FileReader(CLIENT_SECRET_FILE));
GoogleTokenResponse tokenResponse =
          new GoogleAuthorizationCodeTokenRequest(
              new NetHttpTransport(),
              JacksonFactory.getDefaultInstance(),
              "https://oauth2.googleapis.com/token",
              clientSecrets.getDetails().getClientId(),
              clientSecrets.getDetails().getClientSecret(),
              authCode,
              REDIRECT_URI)  // Specify the same redirect URI that you use with your web
                             // app. If you don't have a web version of your app, you can
                             // specify an empty string.
              .execute();

String accessToken = tokenResponse.getAccessToken();

// Use access token to call API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Drive drive =
    new Drive.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
        .setApplicationName("Auth Code Exchange Demo")
        .build();
File file = drive.files().get("appfolder").execute();

// Get profile info from ID token
GoogleIdToken idToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = idToken.getPayload();
String userId = payload.getSubject();  // Use this value as a key to identify a user.
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
Python
from apiclient import discovery
import httplib2
from oauth2client import client

# (Receive auth_code by HTTPS POST)


# If this request does not have `X-Requested-With` header, this could be a CSRF
if not request.headers.get('X-Requested-With'):
    abort(403)

# Set path to the Web application client_secret_*.json file you downloaded from the
# Google API Console: https://console.cloud.google.com/apis/credentials
CLIENT_SECRET_FILE = '/path/to/client_secret.json'

# Exchange auth code for access token, refresh token, and ID token
credentials = client.credentials_from_clientsecrets_and_code(
    CLIENT_SECRET_FILE,
    ['https://www.googleapis.com/auth/drive.appdata', 'profile', 'email'],
    auth_code)

# Call Google API
http_auth = credentials.authorize(httplib2.Http())
drive_service = discovery.build('drive', 'v3', http=http_auth)
appfolder = drive_service.files().get(fileId='appfolder').execute()

# Get profile info from ID token
userid = credentials.id_token['sub']
email = credentials.id_token['email']