OAuth 2.0

يتناول هذا المستند بروتوكول OAuth 2.0، ومتى يتم استخدامها، وكيفية الحصول على معرِّفات العملاء، وكيفية استخدامه مع مكتبة برامج Google API لنظام .NET

بروتوكول OAuth 2.0

OAuth 2.0 هو بروتوكول التفويض الذي تستخدمه أداة Google APIs. يجب أن تكون على دراية بالبروتوكول من خلال قراءة الروابط التالية:

الحصول على معرِّفات العملاء وأسرارهم

يمكنك الحصول على معرِّفات العملاء والأسرار على وحدة التحكم في واجهة Google API. هناك أنواع مختلفة من معرّفات العملاء، لذا تأكَّد من تحديد النوع الصحيح لتطبيقك:

في كل مقتطف من مقتطفات الرمز أدناه (باستثناء حساب الخدمة الأول)، يجب تنزيل سر العميل وتخزينه باسم client_secrets.json في مشروعك.

بيانات الاعتماد

بيانات اعتماد المستخدم

UserCredential هي فئة مساعدة آمنة سلسلة التعليمات لاستخدام رمز الدخول للوصول إلى الموارد المحمية. عادةً ما تنتهي صلاحية رمز الدخول بعد ساعة، وسيصلك خطأ إذا حاولت استخدامه.

UserCredential أو AuthorizationCodeFlow الحرص على "إعادة التحميل" تلقائيًا الرمز، وهو ما يعني ببساطة الحصول على رمز دخول جديد. ويتم ذلك باستخدام رمز مميز طويل الأمد لإعادة التحميل، والذي تتلقاه مع رمز الدخول إذا كنت تستخدم access_type=offline المعلمة أثناء تدفق رمز التفويض.

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

للتأكد من استمرار رموز الدخول والتحديث، يمكنك تقديم التنفيذ الخاص بك IDataStore، أو يمكنك استخدام أحد الإجراءات التالية التي توفّرها المكتبة:

  • FileDataStore لـ NET .أن بيانات الاعتماد ستكون دائمة في ملف.

ServiceAccountCredential

ServiceAccountCredential يشبه UserCredential، لكنه يخدم غرضًا مختلفًا. يتوافق Google OAuth 2.0 مع التفاعلات من خادم إلى خادم، مثل تلك التي تتم بين تطبيق ويب وGoogle Cloud Storage. ويجب أن يُثبت التطبيق الذي قدّم الطلب هويته الخاصة ليتمكّن من الوصول إلى واجهة برمجة التطبيقات، ولا داعي لإشراك المستخدم النهائي. يخزِّن ServiceAccountCredential مفتاحًا خاصًا يُستخدم لتوقيع طلب للحصول على رمز دخول جديد.

يتم تنفيذ كل من UserCredential وServiceAccountCredential. IConfigurableHttpClientInitializer إذًا، يمكنك تسجيل كل منهما على النحو التالي:

  • إذا لم يتم التعامل مع معالج الاستجابة غير الناجح وبالتالي، ستتم إعادة تحميل الرمز المميّز إذا تلقّى رمز حالة HTTP 401.
  • أداة اعتراض، لاعتراض Authorization في كل طلب.

التطبيقات المثبتة

نموذج رمز باستخدام Books API:

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Books.v1;
using Google.Apis.Books.v1.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;

namespace Books.ListMyLibrary
{
    /// <summary>
    /// Sample which demonstrates how to use the Books API.
    /// https://developers.google.com/books/docs/v1/getting_started
    /// <summary>
    internal class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine("Books API Sample: List MyLibrary");
            Console.WriteLine("================================");
            try
            {
                new Program().Run().Wait();
            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    Console.WriteLine("ERROR: " + e.Message);
                }
            }
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }

        private async Task Run()
        {
            UserCredential credential;
            using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    new[] { BooksService.Scope.Books },
                    "user", CancellationToken.None, new FileDataStore("Books.ListMyLibrary"));
            }

            // Create the service.
            var service = new BooksService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Books API Sample",
                });

            var bookshelves = await service.Mylibrary.Bookshelves.List().ExecuteAsync();
            ...
        }
    }
}
  
  • في نموذج الرمز هذا، يتم إنشاء مثيل UserCredential جديد من خلال استدعاء طريقة GoogleWebAuthorizationBroker.AuthorizeAsync. تحصل هذه الطريقة الثابتة على ما يلي:

    • سر العميل (أو بث إلى سر العميل)
    • النطاقات المطلوبة.
    • معرّف المستخدِم.
    • الرمز المميز للإلغاء لإلغاء عملية.
    • مخزن بيانات اختياري. إذا لم يتم تحديد مخزن البيانات، تكون القيمة التلقائية هي FileDataStore. باستخدام مجلد Google.Apis.Auth تلقائي. تم إنشاء المجلد في "Environment.SpecialFolder.ApplicationData".
  • تم ضبط UserCredential الذي يتم عرضه باستخدام هذه الطريقة على أنّه HttpClientInitializer في BooksService (باستخدام أداة الإعداد). كما هو موضّح أعلاه، تنفِّذ UserCredential مهيئ عميل HTTP.

  • لاحظ أنه في نموذج التعليمات البرمجية أعلاه، يتم تحميل معلومات سر العميل من ملف، ولكن يمكنك أيضًا إجراء ما يلي:

    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
        new ClientSecrets
        {
            ClientId = "PUT_CLIENT_ID_HERE",
            ClientSecret = "PUT_CLIENT_SECRETS_HERE"
        },
        new[] { BooksService.Scope.Books },
        "user",
        CancellationToken.None,
        new FileDataStore("Books.ListMyLibrary"));
          

يمكنك إلقاء نظرة على نموذج من كتب.

تطبيقات الويب (ASP.NET Core 3)

التوافق مع واجهات Google APIs OAuth 2.0 لتطبيقات خادم الويب

صفحة Google.Apis.Auth.AspNetCore3 هي المكتبة التي يُنصح باستخدامها لمعظم المستخدمين المقيمين في Google. سيناريوهات OAuth 2.0 في تطبيقات ASP.NET Core 3. وهي تطبق سياسة محددة معالج مصادقة OpenIdConnect إنه يدعم المصادقة التزايدية، ويحدد تطبيق حقن IGoogleAuthProvider لتوفير بيانات اعتماد Google التي يمكن استخدامها مع Google APIs.

يصف هذا القسم كيفية ضبط واستخدام Google.Apis.Auth.AspNetCore3. الرمز المعروض هنا يستند إلى Google.Apis.Auth.AspNetCore3.IntegrationTests، يُعتبر تطبيق ASP.NET عاديًا ويعمل بكامل طاقته تطبيق Core 3.

إذا كنت تريد متابعة هذه الوثائق كدليل تعليمي، فستحتاج إلى صفحة ASP.NET الخاصة بك تطبيق Core 3 وإكمال هذه الخطوات كشرط أساسي.

المتطلبات الأساسية

  • تثبيت حزمة Google.Apis.Auth.AspNetCore3
  • نستخدم Google Drive API لذلك يجب عليك عليك أيضًا تثبيت Google.Apis.Drive.v3 طرد.
  • أنشِئ مشروعًا على Google Cloud في حال لم يكن لديك مشروع. متابعة هذه التعليمات لإجراء ذلك. سيكون هذا هو المشروع الذي يتم تحديد تطبيقك به.
  • احرص على تفعيل Google Drive API. لتفعيل واجهات برمجة التطبيقات، اتّبِع الخطوات التالية هذه التعليمات.
  • أنشئ بيانات اعتماد للتفويض تساعد Google في التعرّف على تطبيقك. متابعة هذه التعليمات لإنشاء بيانات اعتماد التفويض وتنزيل ملف client_secrets.json. هناك عنصران مهمان:
    • لاحظ أن بيانات الاعتماد أن يكون تطبيق ويب.
    • لتشغيل هذا التطبيق، فإن معرّف الموارد المنتظم (URI) لإعادة التوجيه الوحيد الذي تحتاج إلى إضافته هو https://localhost:5001/signin-oidc

تهيئة تطبيقك لاستخدام Google.Apis.Auth.AspNetCore3

تم ضبط Google.Apis.Auth.AspNetCore3 في فئة Startup أو فئة مشابهة البديل الذي قد تستخدمه. تم استخراج المقتطفات التالية من Startup.cs في مشروع Google.Apis.Auth.AspNetCore3.IntegrationTests.

  • أضِف ما يلي باستخدام التوجيه إلى ملف Startup.cs.
    using Google.Apis.Auth.AspNetCore3;
  • في طريقة Startup.ConfigureServices، أضِف الرمز التالي، وغيِّر العناصر النائبة لمعرف العميل وسر العميل بالقيم الموجودة في ملف client_secrets.json. يمكنك تحميل هذه القيم مباشرةً من ملف JSON. أو يمكنك تخزينها بأي طريقة أخرى آمنة. يمكنك إلقاء نظرة على ClientInfo.Load في Google.Apis.Auth.AspNetCore3.IntegrationTests للحصول على مثال حول كيفية تحميل هذه القيم مباشرةً من ملف JSON.
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    
        // This configures Google.Apis.Auth.AspNetCore3 for use in this app.
        services
            .AddAuthentication(o =>
            {
                // This forces challenge results to be handled by Google OpenID Handler, so there's no
                // need to add an AccountController that emits challenges for Login.
                o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
                // This forces forbid results to be handled by Google OpenID Handler, which checks if
                // extra scopes are required and does automatic incremental auth.
                o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
                // Default scheme that will handle everything else.
                // Once a user is authenticated, the OAuth2 token info is stored in cookies.
                o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddGoogleOpenIdConnect(options =>
            {
                options.ClientId = {YOUR_CLIENT_ID};
                options.ClientSecret = {YOUR_CLIENT_SECRET};
            });
    }
          
  • في طريقة Startup.Configure، تأكَّد من إضافة مصادقة ASP.NET Core 3 وإتاحة مكوِّنات البرمجيات الوسيطة على مسار العملية، بالإضافة إلى عمليات إعادة التوجيه عبر HTTPS:
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
        app.UseHttpsRedirection();
        ...
    
        app.UseAuthentication();
        app.UseAuthorization();
    
        ...
    }
          

استخدام بيانات اعتماد المستخدم للوصول إلى Google APIs نيابةً عنه

يمكنك الآن إضافة طرق الإجراءات إلى وحدات التحكُّم التي تتطلّب بيانات اعتماد المستخدم من أجل الوصول إلى Google APIs نيابةً عنهم. يوضح المقتطف التالي كيفية إدراج الملفات في حساب Google Drive للمستخدم الذي تمت مصادقته. لاحظ شيئين في الغالب:

  • لا يحتاج المستخدم إلى المصادقة فحسب، بل يحتاج أيضًا إلى منح نطاق https://www.googleapis.com/auth/drive.readonly إلى تطبيقك، التي تحددها باستخدام السمة GoogleScopedAuthorize.
  • نستخدم آلية حقن التبعية القياسية في ASP.NET Core 3 للحصول على IGoogleAuthProvider التي نستخدمها للحصول على بيانات اعتماد المستخدم.

الرمز:

  • أضف أولاً ما يلي باستخدام الأوامر إلى وحدة التحكم.
    using Google.Apis.Auth.AspNetCore3;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Drive.v3;
    using Google.Apis.Services;
          
  • أضف إجراء وحدة التحكم، على النحو التالي (وأرفه بطريقة عرض بسيطة التي تتلقّى نموذج IList<string>):
    /// <summary>
    /// Lists the authenticated user's Google Drive files.
    /// Specifying the <see cref="GoogleScopedAuthorizeAttribute"> will guarantee that the code
    /// executes only if the user is authenticated and has granted the scope specified in the attribute
    /// to this application.
    /// </summary>
    /// <param name="auth">The Google authorization provider.
    /// This can also be injected on the controller constructor.</param>
    [GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)]
    public async Task<IActionResult> DriveFileList([FromServices] IGoogleAuthProvider auth)
    {
        GoogleCredential cred = await auth.GetCredentialAsync();
        var service = new DriveService(new BaseClientService.Initializer
        {
            HttpClientInitializer = cred
        });
        var files = await service.Files.List().ExecuteAsync();
        var fileNames = files.Files.Select(x => x.Name).ToList();
        return View(fileNames);
    }
          

وهذه هي الأساسيات. يمكنك إلقاء نظرة على HomeController.cs من مشروع Google.Apis.Auth.AspNetCore3.IntegrationTests لمعرفة كيف يمكنك تحقيق:

  • مصادقة المستخدم فقط، بدون نطاقات محددة
  • وظائف تسجيل الخروج
  • تفويض متزايد عبر الرمز. لاحظ أن المقتطف أعلاه يعرض عناصر متزايدة التفويض من خلال السمات.
  • فحص النطاقات الممنوحة حاليًا
  • فحص رموز الدخول وإعادة التحميل
  • فرض إعادة تحميل رمز الدخول لاحظ أنه لا يتعين عليك القيام بذلك بنفسك سيكتشف Google.Apis.Auth.AspNetCore3 ما إذا كان رمز الدخول منتهي الصلاحية أو أوشكت صلاحيته على الانتهاء. وسيتم تحديثه تلقائيًا.

حساب الخدمة

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

يوقّع تطبيق العميل على طلب رمز الدخول باستخدام مفتاح خاص تم تنزيله من وحدة التحكم في واجهة Google API. بعد إنشاء معرِّف عميل جديد، عليك اختيار "حساب الخدمة". نوع التطبيق ثم يمكنك تنزيل المفتاح الخاص. يمكنك إلقاء نظرة على نموذج حساب خدمة باستخدام واجهة برمجة تطبيقات Google Plus.

using System;
using System.Security.Cryptography.X509Certificates;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Plus.v1;
using Google.Apis.Plus.v1.Data;
using Google.Apis.Services;

namespace Google.Apis.Samples.PlusServiceAccount
{
    /// <summary>
    /// This sample demonstrates the simplest use case for a Service Account service.
    /// The certificate needs to be downloaded from the Google API Console
    /// <see cref="https://console.cloud.google.com/">
    ///   "Create another client ID..." -> "Service Account" -> Download the certificate,
    ///   rename it as "key.p12" and add it to the project. Don't forget to change the Build action
    ///   to "Content" and the Copy to Output Directory to "Copy if newer".
    /// </summary>
    public class Program
    {
        // A known public activity.
        private static String ACTIVITY_ID = "z12gtjhq3qn2xxl2o224exwiqruvtda0i";

        public static void Main(string[] args)
        {
            Console.WriteLine("Plus API - Service Account");
            Console.WriteLine("==========================");

            String serviceAccountEmail = "SERVICE_ACCOUNT_EMAIL_HERE";

            var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable);

            ServiceAccountCredential credential = new ServiceAccountCredential(
               new ServiceAccountCredential.Initializer(serviceAccountEmail)
               {
                   Scopes = new[] { PlusService.Scope.PlusMe }
               }.FromCertificate(certificate));

            // Create the service.
            var service = new PlusService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "Plus API Sample",
            });

            Activity activity = service.Activities.Get(ACTIVITY_ID).Execute();
            Console.WriteLine("  Activity: " + activity.Object.Content);
            Console.WriteLine("  Video: " + activity.Object.Attachments[0].Url);

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

ينشئ نموذج التعليمات البرمجية أعلاه ServiceAccountCredential تم ضبط النطاقات المطلوبة وهناك طلب إلى FromCertificate، الذي يحمّل المفتاح الخاص من X509Certificate2 المحدَّد. كما هو الحال في جميع رموز النماذج الأخرى، تم ضبط بيانات الاعتماد على HttpClientInitializer.