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

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

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

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

تنفيذ تدفق الرمز لمرة واحدة

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

يوضح نموذج التعليمات البرمجية التالي كيفية القيام بتدفق التعليمة البرمجية لمرة واحدة.

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

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

لإنشاء معرّف العميل وسر العميل، أنشِئ مشروعًا على وحدة تحكُّم واجهة Google API وإعداد معرِّف عميل 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 Platform في صفحتك

ضمِّن النصوص البرمجية التالية التي توضح دالة مجهولة الهوية تُدرج نصًا برمجيًا في نموذج العناصر في المستند (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: تسجيل دخول المستخدم

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

{"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']