استفاده از OAuth 2.0 برای برنامه های کاربردی سرور به سرور

سیستم Google OAuth 2.0 از تعاملات سرور به سرور مانند تعاملات بین یک برنامه وب و یک سرویس گوگل پشتیبانی می‌کند. برای این سناریو، شما به یک حساب کاربری سرویس نیاز دارید، که حسابی است که به جای یک کاربر نهایی، متعلق به برنامه شماست. برنامه شما APIهای گوگل را از طرف حساب کاربری سرویس فراخوانی می‌کند، بنابراین کاربران مستقیماً درگیر نمی‌شوند. این سناریو گاهی اوقات "OAuth دو مرحله‌ای" یا "2LO" نامیده می‌شود. (اصطلاح مرتبط "OAuth سه مرحله‌ای" به سناریوهایی اشاره دارد که در آنها برنامه شما APIهای گوگل را از طرف کاربران نهایی فراخوانی می‌کند و در آنها گاهی اوقات رضایت کاربر لازم است.)

برای اطلاعات بیشتر به بهترین شیوه‌ها برای حساب‌های خدماتی مراجعه کنید.

معمولاً یک برنامه زمانی از یک حساب سرویس استفاده می‌کند که از APIهای گوگل برای کار با داده‌های خود به جای داده‌های کاربر استفاده کند. به عنوان مثال، برنامه‌ای که از Google Cloud Datastore برای ماندگاری داده‌ها استفاده می‌کند، از یک حساب سرویس برای تأیید اعتبار فراخوانی‌های خود به Google Cloud Datastore API استفاده می‌کند.

مدیران دامنه Google Workspace همچنین می‌توانند به حساب‌های خدماتی در سطح دامنه، از طرف کاربران آن دامنه، اختیار دسترسی به داده‌های کاربر را اعطا کنند .

این سند توضیح می‌دهد که چگونه یک برنامه می‌تواند جریان OAuth 2.0 سرور به سرور را با استفاده از کتابخانه کلاینت Google APIs (توصیه می‌شود) یا HTTP تکمیل کند.

نمای کلی

برای پشتیبانی از تعاملات سرور به سرور، ابتدا یک حساب کاربری سرویس برای پروژه خود در ... ایجاد کنید. API Consoleاگر می‌خواهید به داده‌های کاربران در حساب Google Workspace خود دسترسی داشته باشید، دسترسی در سطح دامنه را به حساب سرویس واگذار کنید.

سپس، برنامه شما با استفاده از اعتبارنامه‌های حساب سرویس، برای درخواست یک توکن دسترسی از سرور احراز هویت OAuth 2.0، آماده‌ی فراخوانی‌های API مجاز می‌شود.

در نهایت، برنامه شما می‌تواند از توکن دسترسی برای فراخوانی APIهای گوگل استفاده کند.

ایجاد حساب کاربری سرویس

اعتبارنامه‌های یک حساب سرویس شامل یک آدرس ایمیل تولید شده منحصر به فرد و حداقل یک جفت کلید عمومی/خصوصی است. اگر واگذاری اختیارات در سطح دامنه فعال باشد، شناسه کلاینت نیز بخشی از اعتبارنامه‌های حساب سرویس خواهد بود.

اگر برنامه شما روی Google App Engine اجرا شود، هنگام ایجاد پروژه، یک حساب کاربری سرویس به طور خودکار تنظیم می‌شود.

اگر برنامه شما روی Google Compute Engine اجرا می‌شود، هنگام ایجاد پروژه، یک حساب کاربری سرویس نیز به طور خودکار تنظیم می‌شود، اما هنگام ایجاد نمونه Google Compute Engine باید محدوده‌هایی را که برنامه شما نیاز به دسترسی به آنها دارد، مشخص کنید. برای اطلاعات بیشتر، به آماده‌سازی یک نمونه برای استفاده از حساب‌های کاربری سرویس مراجعه کنید.

اگر برنامه شما روی Google App Engine یا Google Compute Engine اجرا نمی‌شود، باید این اعتبارنامه‌ها را در ... دریافت کنید. Google API Consoleبرای ایجاد اعتبارنامه‌های حساب سرویس یا مشاهده اعتبارنامه‌های عمومی که قبلاً ایجاد کرده‌اید، موارد زیر را انجام دهید:

ابتدا یک حساب کاربری سرویس ایجاد کنید:

  1. باز کنید Service accounts page.
  2. If prompted, select a project, or create a new one.
  3. روی کلیک کنید. ایجاد حساب کاربری سرویس .
  4. در قسمت جزئیات حساب سرویس ، نام، شناسه و توضیحی برای حساب سرویس تایپ کنید، سپس روی ایجاد و ادامه کلیک کنید.
  5. اختیاری: در قسمت «اعطای دسترسی به پروژه برای این حساب سرویس» ، نقش‌های IAM مورد نظر برای اعطای دسترسی به حساب سرویس را انتخاب کنید.
  6. روی ادامه کلیک کنید.
  7. اختیاری: در قسمت «اعطای دسترسی به این حساب سرویس برای کاربران» ، کاربران یا گروه‌هایی را که مجاز به استفاده و مدیریت حساب سرویس هستند، اضافه کنید.
  8. روی انجام شد کلیک کنید.

سپس، یک کلید حساب سرویس ایجاد کنید:

  1. روی آدرس ایمیل حساب سرویسی که ایجاد کرده‌اید کلیک کنید.
  2. روی برگه کلیدها کلیک کنید.
  3. در فهرست کشویی «افزودن کلید» ، «ایجاد کلید جدید» را انتخاب کنید.
  4. روی ایجاد کلیک کنید.

برای کسب اطلاعات بیشتر، به بهترین شیوه‌ها برای مدیریت کلیدهای حساب سرویس مراجعه کنید.

شما می‌توانید به API Console در هر زمانی برای مشاهده آدرس ایمیل، اثر انگشت کلید عمومی و سایر اطلاعات، یا برای ایجاد جفت کلیدهای عمومی/خصوصی اضافی. برای جزئیات بیشتر در مورد اعتبارنامه‌های حساب سرویس در API Console، به حساب‌های سرویس در API Consoleفایل راهنما.

آدرس ایمیل حساب سرویس را یادداشت کنید و فایل کلید خصوصی حساب سرویس را در مکانی که برای برنامه شما قابل دسترسی است ذخیره کنید. برنامه شما برای برقراری تماس‌های API مجاز به آنها نیاز دارد.

تفویض اختیار در سطح دامنه به حساب سرویس

با استفاده از یک حساب کاربری Google Workspace، مدیر Workspace سازمان می‌تواند به یک برنامه اجازه دهد تا به نمایندگی از کاربران در دامنه Google Workspace به داده‌های کاربر Workspace دسترسی داشته باشد. به عنوان مثال، برنامه‌ای که از API تقویم گوگل برای افزودن رویدادها به تقویم‌های همه کاربران در یک دامنه Google Workspace استفاده می‌کند، از یک حساب کاربری برای دسترسی به API تقویم گوگل به نمایندگی از کاربران استفاده می‌کند. اعطای مجوز به یک حساب کاربری برای دسترسی به داده‌ها به نمایندگی از کاربران در یک دامنه، گاهی اوقات به عنوان "واگذاری اختیار در سطح دامنه" به یک حساب کاربری سرویس شناخته می‌شود.

برای واگذاری اختیارات در سطح دامنه به یک حساب سرویس، مدیر ارشد دامنه Google Workspace باید مراحل زیر را انجام دهد:

  1. از کنسول مدیریت دامنه Google Workspace خود، به اصلی > امنیت > کنترل دسترسی و داده‌ها > کنترل‌های API بروید.
  2. در پنل واگذاری اختیارات در سطح دامنه ، گزینه مدیریت واگذاری اختیارات در سطح دامنه را انتخاب کنید.
  3. روی افزودن جدید کلیک کنید.
  4. در فیلد شناسه کلاینت ، شناسه کلاینت حساب سرویس را وارد کنید. می‌توانید شناسه کلاینت حساب سرویس خود را در Service accounts page.
  5. در فیلد OAuth scopes (comma-delimited) ، فهرست scopeهایی را که برنامه شما باید به آنها دسترسی داشته باشد، وارد کنید. برای مثال، اگر برنامه شما نیاز به دسترسی کامل در سطح دامنه به Google Drive API و Google Calendar API دارد، موارد زیر را وارد کنید: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar .
  6. روی تأیید کلیک کنید.

اکنون برنامه شما این اختیار را دارد که به عنوان کاربران در دامنه Workspace شما، فراخوانی‌های API را انجام دهد (تا کاربران را "جعل هویت" کند). هنگامی که برای انجام این فراخوانی‌های API واگذار شده آماده می‌شوید، صریحاً کاربری را که باید جعل هویت کند، مشخص خواهید کرد.

یک فراخوانی API واگذار شده انجام دهید

بخش‌های بعدی نحوه‌ی برقراری یک فراخوانی API مجاز را با استفاده از کتابخانه‌ی کلاینت Google APIs یا با تعامل مستقیم با سیستم OAuth 2.0 با استفاده از HTTP نشان می‌دهند.

جاوا

پس از اینکه آدرس ایمیل کلاینت و کلید خصوصی را از ... دریافت کردید API Console، از کتابخانه Google Auth برای جاوا استفاده کنید تا یک شیء GoogleCredentials از اعتبارنامه‌های حساب سرویس و حوزه‌هایی که برنامه شما نیاز به دسترسی به آنها دارد، ایجاد کنید. برای مثال:

import com.google.auth.oauth2.GoogleCredentials;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("ServiceAccountKey.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

اگر در حال توسعه یک برنامه در Google Cloud هستید، می‌توانید به جای آن از اعتبارنامه‌های پیش‌فرض برنامه استفاده کنید که می‌تواند روند کار را ساده‌تر کند.

تفویض اختیار در سطح دامنه

اگر دسترسی در سطح دامنه به حساب سرویس را واگذار کرده‌اید و می‌خواهید یک حساب کاربری را جعل هویت کنید، آدرس ایمیل حساب کاربری را با متد createDelegated از شیء GoogleCredentials مشخص کنید. برای مثال:

GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream("ServiceAccountKey.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("workspace-user@example.com");

شیء GoogleCredentials برای فراخوانی متد createDelegated() استفاده می‌شود. آرگومان متد createDelegated() باید یک کاربر متعلق به حساب کاربری Workspace شما باشد. کدی که درخواست را ارسال می‌کند، از این اعتبارنامه برای فراخوانی APIهای گوگل با استفاده از حساب کاربری سرویس شما استفاده خواهد کرد.

پایتون

پس از اینکه آدرس ایمیل کلاینت و کلید خصوصی را از ... دریافت کردید API Console، از کتابخانه کلاینت APIهای گوگل برای پایتون برای انجام مراحل زیر استفاده کنید:

  1. یک شیء Credentials از اعتبارنامه‌های حساب سرویس و محدوده‌هایی که برنامه شما نیاز به دسترسی به آنها دارد، ایجاد کنید. برای مثال:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/ServiceAccountKey.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    اگر در حال توسعه یک برنامه در Google Cloud هستید، می‌توانید به جای آن از اعتبارنامه‌های پیش‌فرض برنامه استفاده کنید که می‌تواند روند کار را ساده‌تر کند.

  2. تفویض اختیار در سطح دامنه

    اگر دسترسی در سطح دامنه را به حساب سرویس واگذار کرده‌اید و می‌خواهید یک حساب کاربری را جعل هویت کنید، از متد with_subject از یک شیء ServiceAccountCredentials موجود استفاده کنید. برای مثال:

    delegated_credentials = credentials.with_subject('user@example.org')

از شیء Credentials برای فراخوانی APIهای گوگل در برنامه خود استفاده کنید.

HTTP/REST

پس از دریافت شناسه کلاینت و کلید خصوصی از API Console، درخواست شما باید مراحل زیر را تکمیل کند:

  1. یک JSON Web Token (JWT، تلفظ می‌شود "jot") ایجاد کنید که شامل یک هدر، یک مجموعه ادعا و یک امضا باشد.
  2. درخواست یک توکن دسترسی از سرور احراز هویت Google OAuth 2.0.
  3. پاسخ JSON که سرور احراز هویت برمی‌گرداند را مدیریت کنید.

بخش‌های بعدی نحوه انجام این مراحل را شرح می‌دهند.

اگر پاسخ شامل یک توکن دسترسی باشد، می‌توانید از توکن دسترسی برای فراخوانی یک API گوگل استفاده کنید. (اگر پاسخ شامل توکن دسترسی نباشد، ممکن است درخواست JWT و توکن شما به درستی شکل نگرفته باشد، یا ممکن است حساب سرویس اجازه دسترسی به محدوده‌های درخواستی را نداشته باشد.)

وقتی توکن دسترسی منقضی می‌شود ، برنامه شما JWT دیگری تولید می‌کند، آن را امضا می‌کند و توکن دسترسی دیگری را درخواست می‌کند.

برنامه سرور شما از یک JWT برای درخواست یک توکن از سرور احراز هویت گوگل استفاده می‌کند، سپس از این توکن برای فراخوانی یک نقطه پایانی API گوگل استفاده می‌کند. هیچ کاربر نهایی درگیر نیست.
شکل ۱. برنامه‌ی سرور شما از یک JWT برای درخواست یک توکن از سرور احراز هویت گوگل استفاده می‌کند، سپس از این توکن برای فراخوانی یک نقطه‌ی پایانی API گوگل استفاده می‌کند. هیچ کاربر نهایی درگیر نیست.

ادامه‌ی این بخش، جزئیات ایجاد یک JWT، امضای JWT، تشکیل درخواست توکن دسترسی و مدیریت پاسخ را شرح می‌دهد.

ایجاد یک JWT

یک JWT از سه بخش تشکیل شده است: یک هدر، یک مجموعه ادعا (Claim Set) و یک امضا (signature). هدر و مجموعه ادعا، اشیاء JSON هستند. این اشیاء JSON به بایت‌های UTF-8 سریالی می‌شوند، سپس با استفاده از کدگذاری Base64url کدگذاری می‌شوند. این کدگذاری، مقاومت در برابر تغییرات کدگذاری ناشی از عملیات کدگذاری مکرر را فراهم می‌کند. هدر، مجموعه ادعا (Claim Set) و امضا با یک کاراکتر نقطه ( . ) به هم متصل می‌شوند.

یک JWT به صورت زیر تشکیل می‌شود:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

رشته پایه برای امضا به شرح زیر است:

{Base64url encoded header}.{Base64url encoded claim set}
ساخت هدر JWT

این سرآیند شامل دو فیلد الزامی است: الگوریتم امضا و قالب ادعا، و یک شناسه کلید اختیاری:

  • الگوریتم اجباری است و فقط یک مقدار دارد: "alg": "RS256" .
  • قالب‌بندی اجباری است و فقط یک مقدار دارد: "typ": "JWT" .
  • شناسه کلید اختیاری است و شناسه کلید حساب سرویس مورد استفاده برای امضای JWT است. اگر یک شناسه کلید نادرست مشخص شود، تمام کلیدهای مرتبط با حساب سرویس امتحان می‌شوند. اگر هیچ کلید معتبری یافت نشود، توکن رد می‌شود. گوگل حق رد توکن‌هایی با شناسه کلید نادرست را برای خود محفوظ می‌دارد.

حساب‌های کاربری سرویس به الگوریتم RSA SHA-256 و فرمت توکن JWT متکی هستند. در نتیجه، نمایش JSON از هدر به شرح زیر است:

{"alg":"RS256","typ":"JWT", "kid":"370ab79b4513eb9bad7c9bd16a95cb76b5b2a56a"}

نمایش Base64url این مورد به صورت زیر است:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsICJraWQiOiIzNzBhYjc5YjQ1MTNlYjliYWQ3YzliZDE2YTk1Y2I3NmI1YjJhNTZhIn0=
ساخت مجموعه ادعاهای JWT

مجموعه‌ی درخواست‌های JWT شامل اطلاعاتی در مورد JWT، از جمله مجوزهای درخواستی (اسکوپ‌ها)، هدف توکن، صادرکننده، زمان صدور توکن و طول عمر توکن است. اکثر فیلدها اجباری هستند. مانند هدر JWT، مجموعه‌ی درخواست‌های JWT یک شیء JSON است و در محاسبه‌ی امضا استفاده می‌شود.

ادعاهای مورد نیاز

ادعاهای مورد نیاز در مجموعه ادعاهای JWT می‌توانند به هر ترتیبی در مجموعه ادعاها ظاهر شوند.

نام توضیحات
iss آدرس ایمیل حساب سرویس.
scope فهرستی از مجوزهایی که برنامه درخواست می‌کند، با فاصله از هم جدا شده است.
aud توصیف‌گری از هدف مورد نظر برای ادعا. هنگام درخواست توکن دسترسی، این مقدار همیشه https://oauth2.googleapis.com/token است.
exp زمان انقضای اعلان، که به صورت ثانیه از ساعت 00:00:00 UTC، اول ژانویه 1970 مشخص شده است. این مقدار حداکثر 1 ساعت پس از زمان صدور دارد.
iat زمان صدور ادعا، که به صورت ثانیه از ساعت 00:00:00 UTC، اول ژانویه 1970 مشخص شده است.

این مثالی از نمایش JSON از فیلدهای مورد نیاز در یک مجموعه ادعای JWT است:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
ادعاهای اضافی

در برخی موارد سازمانی، یک برنامه می‌تواند از نمایندگی در سطح دامنه برای اقدام به نمایندگی از یک کاربر خاص در یک سازمان استفاده کند. مجوز انجام این نوع جعل هویت باید قبل از اینکه یک برنامه بتواند هویت یک کاربر را جعل کند، اعطا شود و معمولاً توسط یک مدیر ارشد مدیریت می‌شود. برای اطلاعات بیشتر، به دسترسی به API کنترل با نمایندگی در سطح دامنه مراجعه کنید.

برای به دست آوردن یک توکن دسترسی که به یک برنامه کاربردی اجازه دسترسی به یک منبع را می‌دهد، آدرس ایمیل کاربر را در مجموعه ادعاهای JWT به عنوان مقدار فیلد sub وارد کنید.

نام توضیحات
sub آدرس ایمیل کاربری که برنامه برای او درخواست دسترسی تفویض‌شده را دارد.

اگر یک برنامه اجازه جعل هویت کاربر را نداشته باشد، پاسخ به درخواست توکن دسترسی که شامل فیلد sub باشد، خطا خواهد بود.

این نمونه‌ای از یک مجموعه ادعای JWT است که شامل sub است:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
رمزگذاری مجموعه ادعاهای JWT

مانند هدر JWT، مجموعه Claim مربوط به JWT نیز باید به صورت سریالی و با کدگذاری UTF-8 و Base64url-safe کدگذاری شود. این نمونه‌ای از نمایش JSON از مجموعه Claim مربوط به JWT است:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
محاسبه امضا

امضای وب JSON (JWS) مشخصاتی است که مکانیزم تولید امضا برای JWT را هدایت می‌کند. ورودی امضا، آرایه‌ای از بایت‌ها با محتوای زیر است:

{Base64url encoded header}.{Base64url encoded claim set}

الگوریتم امضای موجود در هدر JWT باید هنگام محاسبه امضا استفاده شود. تنها الگوریتم امضایی که توسط سرور تأیید هویت Google OAuth 2.0 پشتیبانی می‌شود، RSA با استفاده از الگوریتم هش SHA-256 است. این الگوریتم در فیلد alg در هدر JWT به صورت RS256 بیان می‌شود.

نمایش UTF-8 ورودی را با استفاده از SHA256withRSA (که با تابع هش SHA-256 با نام RSASSA-PKCS1-V1_5-SIGN نیز شناخته می‌شود) با کلید خصوصی به‌دست‌آمده از ... امضا کنید. Google API Consoleخروجی یک آرایه از بایت‌ها خواهد بود.

سپس امضا باید با کدگذاری Base64url باشد. هدر، مجموعه ادعا و امضا با یک کاراکتر نقطه ( . ) به هم متصل می‌شوند. نتیجه JWT است. باید به صورت زیر باشد (برای وضوح، خطوط شکسته اضافه شده است):

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

این مثالی از JWT قبل از کدگذاری Base64url است:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

این نمونه‌ای از یک JWT است که امضا شده و آماده‌ی انتقال است:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

درخواست توکن دسترسی

پس از تولید JWT امضا شده، یک برنامه می‌تواند از آن برای درخواست یک توکن دسترسی استفاده کند. این درخواست توکن دسترسی یک درخواست HTTPS POST است و بدنه آن به صورت URL کدگذاری شده است. برای مثال:

https://oauth2.googleapis.com/token

پارامترهای زیر در درخواست HTTPS POST مورد نیاز هستند:

نام توضیحات
grant_type در صورت لزوم از رشته‌ی زیر که به صورت URL کدگذاری شده است استفاده کنید: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JWT، شامل امضا.

این یک نمونه خام از درخواست HTTPS POST است که در یک درخواست توکن دسترسی استفاده شده است:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

این همان درخواست است، با استفاده از curl :

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

مدیریت پاسخ

اگر درخواست JWT و توکن دسترسی به درستی تشکیل شده باشند و حساب کاربری سرویس مجوز انجام عملیات را داشته باشد، پاسخ JSON از سرور احراز هویت شامل یک توکن دسترسی است. در زیر یک نمونه پاسخ آمده است:

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

توکن‌های دسترسی می‌توانند در طول مدت زمان مشخص شده توسط مقدار expires_in دوباره استفاده شوند.

نکته امنیتی مهم: درک جعل هویت

وقتی اختیارات را در سطح دامنه واگذار می‌کنید، به حساب کاربری سرویس دسترسی مستقیم به تمام داده‌های کاربر را نمی‌دهید. در عوض، به آن اجازه می‌دهید هنگام برقراری تماس‌های API، هویت کاربران خاص را جعل کند.
  • دسترسی از طرف یک کاربر است: برنامه شما باید مشخص کند که برای هر درخواست API، هویت کدام کاربر را جعل کند. سپس برنامه با مجوزهای آن کاربر خاص عمل می‌کند، نه با هیچ گونه امتیاز بالا یا امتیاز در سطح دامنه .
  • مجوزها محدود هستند: دسترسی حساب کاربری سرویس توسط دو عامل محدود می‌شود: مجوزهای کاربر جعل هویت شده و دامنه‌های OAuth که شما در کنسول مدیریت مجاز می‌کنید. این حساب کاربری نمی‌تواند به داده‌هایی دسترسی داشته باشد که خود کاربر جعل هویت شده نمی‌تواند به آنها دسترسی داشته باشد.
  • اصل حداقل امتیاز: از آنجا که این ویژگی امکان دسترسی به داده‌های کاربر را بدون رضایت مستقیم آنها فراهم می‌کند، رعایت بهترین شیوه‌های امنیتی بسیار مهم است. فقط دامنه‌های OAuth لازم را اعطا کنید و مطمئن شوید که پیامدهای امنیتی را درک می‌کنید.
برای دستورالعمل‌های امنیتی دقیق، به بهترین شیوه‌های واگذاری اختیار در سطح دامنه مراجعه کنید.

فراخوانی API های گوگل

جاوا

با انجام مراحل زیر، از شیء GoogleCredentials برای فراخوانی APIهای گوگل استفاده کنید:

  1. یک شیء سرویس برای API ایجاد کنید که می‌خواهید با استفاده از شیء GoogleCredentials آن را فراخوانی کنید. برای مثال:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credentials).build();
  2. با استفاده از رابط ارائه شده توسط شیء سرویس، درخواست‌هایی را به سرویس API ارسال کنید. به عنوان مثال، برای فهرست کردن نمونه‌های پایگاه‌های داده Cloud SQL در پروژه exciting-example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

پایتون

با انجام مراحل زیر، از شیء مجاز Credentials برای فراخوانی APIهای گوگل استفاده کنید:

  1. یک شیء سرویس برای API که می‌خواهید فراخوانی کنید، بسازید. شما با فراخوانی تابع build به همراه نام و نسخه API و شیء Credentials مجاز، یک شیء سرویس می‌سازید. به عنوان مثال، برای فراخوانی نسخه 1beta3 از Cloud SQL Administration API:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. با استفاده از رابط ارائه شده توسط شیء سرویس، درخواست‌هایی را به سرویس API ارسال کنید. به عنوان مثال، برای فهرست کردن نمونه‌های پایگاه‌های داده Cloud SQL در پروژه exciting-example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST

پس از اینکه برنامه شما یک توکن دسترسی دریافت کرد، می‌توانید از این توکن برای برقراری تماس با یک API گوگل از طرف یک حساب سرویس یا حساب کاربری مشخص استفاده کنید، البته در صورتی که محدوده (یا محدوده‌های) دسترسی مورد نیاز API اعطا شده باشد. برای انجام این کار، توکن دسترسی را با وارد کردن یک پارامتر پرس‌وجوی access_token یا یک مقدار Bearer هدر HTTP Authorization ، در درخواست به API قرار دهید. در صورت امکان، هدر HTTP ترجیح داده می‌شود، زیرا رشته‌های پرس‌وجو معمولاً در گزارش‌های سرور قابل مشاهده هستند. در بیشتر موارد، می‌توانید از یک کتابخانه کلاینت برای تنظیم تماس‌های خود با APIهای گوگل استفاده کنید (برای مثال، هنگام فراخوانی API فایل‌های درایو ).

شما می‌توانید تمام APIهای گوگل را امتحان کنید و حوزه‌های کاربرد آنها را در OAuth 2.0 Playground مشاهده کنید.

مثال‌های HTTP GET

فراخوانی نقطه پایانی drive.files (رابط برنامه‌نویسی کاربردی Drive Files) با استفاده از هدر HTTP مربوط به Authorization: Bearer ممکن است چیزی شبیه به شکل زیر باشد. توجه داشته باشید که باید توکن دسترسی خودتان را مشخص کنید:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

در اینجا فراخوانی همان API برای کاربر احراز هویت شده با استفاده از پارامتر رشته پرس و جوی access_token مشاهده می‌کنید:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

مثال‌های curl

می‌توانید این دستورات را با برنامه خط فرمان curl آزمایش کنید. در اینجا مثالی آورده شده است که از گزینه هدر HTTP (ترجیحاً) استفاده می‌کند:

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

یا، به طور جایگزین، گزینه پارامتر رشته پرس و جو:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

وقتی توکن‌های دسترسی منقضی می‌شوند

توکن‌های دسترسی صادر شده توسط سرور تأیید اعتبار Google OAuth 2.0 پس از مدت زمان ارائه شده توسط مقدار expires_in منقضی می‌شوند. هنگامی که یک توکن دسترسی منقضی می‌شود، برنامه باید JWT دیگری تولید کند، آن را امضا کند و توکن دسترسی دیگری را درخواست کند.

کدهای خطای JWT

فیلد error فیلد error_description معنی چگونه حل و فصل کنیم
unauthorized_client Unauthorized client or scope in request. اگر می‌خواهید از واگذاری اختیارات در سطح دامنه استفاده کنید، حساب کاربری سرویس در کنسول ادمین دامنه کاربر مجاز نیست.

مطمئن شوید که حساب کاربری سرویس در صفحه واگذاری اختیارات در سطح دامنه (Domain-wide delegation) کنسول مدیریت برای کاربر در فیلد sub claim (فیلد) مجاز (authorized) شده است.

اگرچه معمولاً چند دقیقه طول می‌کشد، اما ممکن است تا ۲۴ ساعت طول بکشد تا مجوز برای همه کاربران حساب گوگل شما ارسال شود.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. یک حساب کاربری سرویس با استفاده از آدرس ایمیل کلاینت به جای شناسه کلاینت (عددی) در کنسول مدیریت، یا یک گروه گوگل برای احراز هویت، مجاز شده است. در صفحه واگذاری اختیارات در سطح دامنه در کنسول مدیریت، کلاینت را حذف کنید و آن را با شناسه عددی دوباره اضافه کنید، یا گروه گوگل را حذف کرده و آن را با سرویس یا حساب کاربری شخصی جایگزین کنید.
access_denied (هر مقداری) اگر از واگذاری اختیارات در سطح دامنه استفاده می‌کنید، یک یا چند محدوده درخواستی در کنسول مدیریت مجاز نیستند.

مطمئن شوید که حساب کاربری سرویس در صفحه واگذاری دامنه در کنسول مدیریت برای کاربر موجود در فیلد sub claim (فیلد) مجاز شده است، و اینکه شامل تمام scopeهایی است که شما در scope Claim JWT خود درخواست می‌کنید.

با بررسی «مدیریت دسترسی به سرویس‌هایی که به صورت جداگانه کنترل نمی‌شوند»، تأیید کنید که دسترسی به سرویس‌های گوگل محدود نشده است.

اگرچه معمولاً چند دقیقه طول می‌کشد، اما ممکن است تا ۲۴ ساعت طول بکشد تا مجوز برای همه کاربران حساب گوگل شما ارسال شود.

admin_policy_enforced (هر مقداری) به دلیل سیاست‌های مدیر Google Workspace، حساب Google قادر به تأیید یک یا چند محدوده درخواستی نیست.

برای اطلاعات بیشتر در مورد اینکه چگونه یک مدیر می‌تواند دسترسی به همه حوزه‌ها یا حوزه‌های حساس و محدود شده را تا زمانی که دسترسی به طور صریح به شناسه کلاینت OAuth شما اعطا نشده باشد، محدود کند، به مقاله راهنمای مدیریت Google Workspace با عنوان «کنترل دسترسی برنامه‌های شخص ثالث و داخلی به داده‌های Google Workspace» مراجعه کنید.

invalid_client (هر مقداری)

کلاینت OAuth یا توکن JWT نامعتبر است یا به طور نادرست پیکربندی شده است.

برای جزئیات بیشتر به توضیحات خطا مراجعه کنید.

مطمئن شوید که توکن JWT معتبر است و شامل ادعاهای صحیحی است.

بررسی کنید که حساب کاربری OAuth و سرویس به درستی پیکربندی شده باشند و از آدرس ایمیل صحیح استفاده می‌کنید.

بررسی کنید که توکن JWT صحیح است و برای شناسه کلاینت در درخواست صادر شده است.

deleted_client (هر مقداری)

کلاینت OAuth که برای ایجاد درخواست استفاده شده بود، حذف شده است. حذف می‌تواند به صورت دستی یا خودکار در مورد کلاینت‌های بلااستفاده انجام شود. کلاینت‌های حذف شده را می‌توان ظرف 30 روز از زمان حذف بازیابی کرد. اطلاعات بیشتر .

از یک شناسه کلاینت که هنوز فعال است استفاده کنید.

invalid_grant Not a valid email یا Invalid email or User ID. کاربر مورد نظر وجود ندارد. بررسی کنید که آدرس ایمیل در فیلد sub (ادعا) صحیح باشد.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

معمولاً، این بدان معناست که زمان سیستم محلی صحیح نیست. همچنین اگر مقدار exp بیش از ۶۵ دقیقه با مقدار iat فاصله داشته باشد، یا مقدار exp کمتر از مقدار iat باشد، ممکن است این اتفاق بیفتد.

مطمئن شوید که ساعت سیستمی که JWT در آن تولید شده است، صحیح است. در صورت لزوم، زمان خود را با Google NTP همگام‌سازی کنید.

invalid_grant Invalid JWT Signature.

ادعای JWT با یک کلید خصوصی امضا شده است که با حساب سرویس شناسایی شده توسط ایمیل کلاینت مرتبط نیست یا کلیدی که استفاده شده حذف، غیرفعال یا منقضی شده است.

از طرف دیگر، ممکن است عبارت JWT به اشتباه کدگذاری شده باشد - باید با Base64 کدگذاری شده باشد، بدون خط جدید یا علامت مساوی.

مجموعه ادعاهای JWT را رمزگشایی کنید و تأیید کنید که کلیدی که ادعا را امضا کرده است با حساب سرویس مرتبط است.

سعی کنید از یک کتابخانه OAuth ارائه شده توسط گوگل استفاده کنید تا مطمئن شوید JWT به درستی تولید می‌شود.

invalid_scope Invalid OAuth scope or ID token audience provided. هیچ محدوده‌ای درخواست نشده است (لیست خالی از محدوده‌ها)، یا یکی از محدوده‌های درخواستی وجود ندارد (یعنی نامعتبر است).

مطمئن شوید که ادعای scope (فیلد) JWT پر شده است، و محدوده‌هایی که در آن وجود دارد را با محدوده‌های مستند شده برای APIهایی که می‌خواهید استفاده کنید مقایسه کنید تا مطمئن شوید هیچ خطا یا غلط املایی وجود ندارد.

توجه داشته باشید که لیست محدوده‌ها در ادعای scope باید با فاصله از هم جدا شوند، نه با کاما.

disabled_client The OAuth client was disabled. کلید مورد استفاده برای امضای ادعای JWT غیرفعال است.

برو به Google API Consoleو در بخش IAM & Admin > Service Accounts ، حساب سرویسی را که حاوی «شناسه کلید» مورد استفاده برای امضای ادعا است، فعال کنید.

org_internal This client is restricted to users within its organization. شناسه کلاینت OAuth در درخواست، بخشی از پروژه‌ای است که دسترسی به حساب‌های گوگل را در یک سازمان ابری خاص گوگل محدود می‌کند.

از یک حساب کاربری سرویس از سازمان برای احراز هویت استفاده کنید. پیکربندی نوع کاربر را برای برنامه OAuth خود تأیید کنید.

ضمیمه: احراز هویت حساب کاربری سرویس بدون OAuth

با برخی از APIهای گوگل، می‌توانید فراخوانی‌های API مجاز را مستقیماً با استفاده از یک JWT امضا شده به عنوان یک توکن حامل، به جای یک توکن دسترسی OAuth 2.0، انجام دهید. در صورت امکان، می‌توانید از ارسال درخواست شبکه به سرور مجوز گوگل قبل از برقراری فراخوانی API جلوگیری کنید.

اگر API که می‌خواهید فراخوانی کنید، تعریف سرویسی دارد که در مخزن Google APIs GitHub منتشر شده است، می‌توانید فراخوانی‌های API مجاز را با استفاده از JWT به جای access token انجام دهید. برای انجام این کار:

  1. یک حساب کاربری سرویس ایجاد کنید . حتماً فایل JSON که هنگام ایجاد حساب کاربری دریافت می‌کنید را نگه دارید.
  2. با استفاده از هر کتابخانه استاندارد JWT، مانند کتابخانه‌ای که در jwt.io یافت می‌شود، یک JWT با هدر و payload مانند مثال زیر ایجاد کنید:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • برای فیلد kid در هدر، شناسه کلید خصوصی حساب سرویس خود را مشخص کنید. می‌توانید این مقدار را در فیلد private_key_id فایل JSON حساب سرویس خود پیدا کنید.
    • برای فیلدهای iss و sub ، آدرس ایمیل حساب سرویس خود را مشخص کنید. می‌توانید این مقدار را در فیلد client_email فایل JSON حساب سرویس خود پیدا کنید. این مقدار به طور منحصر به فرد، کلاینت را مشخص می‌کند و عملاً شناسه کلاینت است.
    • برای فیلد aud ، نقطه پایانی API را مشخص کنید. برای مثال: https:// SERVICE .googleapis.com/ .
    • برای فیلد iat ، زمان فعلی Unix epoch و برای فیلد exp ، زمان دقیقاً ۳۶۰۰ ثانیه بعد، زمانی که JWT منقضی می‌شود را مشخص کنید.

JWT را با استفاده از کلید خصوصی موجود در فایل JSON حساب سرویس خود، با RSA-256 امضا کنید.

برای مثال:

جاوا

استفاده از google-auth-library-java و java-jwt :

import com.google.auth.oauth2.ServiceAccountCredentials;
...
GoogleCredentials credentials =
        GoogleCredentials.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = ((ServiceAccountCredentials) credentials).getPrivateKey();
String privateKeyId = ((ServiceAccountCredentials) credentials).getPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

پایتون

استفاده از PyJWT :

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. با استفاده از JWT امضا شده به عنوان توکن حامل، API را فراخوانی کنید:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com

پیاده‌سازی حفاظت از حساب‌های کاربری متقابل

گام دیگری که باید برای محافظت از حساب‌های کاربران خود بردارید، پیاده‌سازی محافظت بین حساب‌های کاربری با استفاده از سرویس محافظت بین حساب‌های کاربری گوگل است. این سرویس به شما امکان می‌دهد در اعلان‌های رویدادهای امنیتی مشترک شوید که اطلاعاتی در مورد تغییرات عمده در حساب کاربری به برنامه شما ارائه می‌دهند. سپس می‌توانید بسته به نحوه واکنش خود به رویدادها، از این اطلاعات برای انجام اقدامات لازم استفاده کنید.

برخی از نمونه‌های انواع رویدادهایی که توسط سرویس حفاظت از حساب‌های کاربری متقابل گوگل به برنامه شما ارسال می‌شوند عبارتند از:

  • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
  • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
  • https://schemas.openid.net/secevent/risc/event-type/account-disabled

برای اطلاعات بیشتر در مورد نحوه پیاده‌سازی محافظت از حساب‌های کاربری بین‌حسابی و فهرست کامل رویدادهای موجود، به صفحه «محافظت از حساب‌های کاربری با محافظت از حساب‌های کاربری بین‌حسابی» مراجعه کنید.