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

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

به طور معمول، یک برنامه زمانی از حساب سرویس استفاده می کند که برنامه از API های Google برای کار با داده های خود به جای داده های کاربر استفاده می کند. به عنوان مثال، برنامه‌ای که از 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 استفاده کند.

ایجاد یک حساب کاربری خدمات

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

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

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

اگر برنامه شما در 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. اختیاری: در بخش Grant this service account access to project ، نقش های IAM را برای اعطای به حساب سرویس انتخاب کنید.
  6. روی Continue کلیک کنید.
  7. اختیاری: در بخش دسترسی کاربران به این حساب سرویس ، کاربران یا گروه‌هایی را اضافه کنید که مجاز به استفاده و مدیریت حساب سرویس هستند.
  8. روی Done کلیک کنید.

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

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

جفت کلید عمومی/خصوصی جدید شما تولید و در دستگاه شما دانلود می شود. به عنوان تنها کپی کلید خصوصی عمل می کند. شما مسئول نگهداری ایمن آن هستید. اگر این جفت کلید را گم کنید، باید یک جفت کلید جدید ایجاد کنید.

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

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

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

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

برای واگذاری اختیارات دامنه به یک حساب سرویس، یک سرپرست فوق العاده دامنه Google Workspace باید مراحل زیر را انجام دهد:

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

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

در حال آماده شدن برای برقراری تماس API واگذار شده

جاوا

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

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

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

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

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

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("workspace-user@example.com");

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

پایتون

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

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

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

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

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

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

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

HTTP/REST

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

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

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

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

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

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

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

ایجاد JWT

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

یک JWT به شرح زیر تشکیل شده است:

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

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

{Base64url encoded header}.{Base64url encoded claim set}
تشکیل هدر JWT

سرصفحه شامل سه فیلد است که الگوریتم امضا، قالب ادعا و [شناسه کلید کلید حساب سرویس] را نشان می‌دهد (https://cloud.google.com/iam/docs/reference/rest/v1/ projects.serviceAccounts.keys) که برای امضای JWT استفاده شد. الگوریتم و قالب اجباری است و هر فیلد فقط یک مقدار دارد. با معرفی الگوریتم‌ها و فرمت‌های اضافی، این هدر بر این اساس تغییر می‌کند. شناسه کلید اختیاری است و اگر شناسه کلید نادرستی مشخص شده باشد، GCP تمام کلیدهای مرتبط با حساب سرویس را برای تأیید نشانه امتحان می کند و اگر کلید معتبری پیدا نشد، رمز را رد می کند. Google این حق را برای خود محفوظ می‌دارد که در آینده توکن‌هایی با شناسه‌های کلید نادرست را رد کند.

حساب های سرویس بر الگوریتم 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، 1 ژانویه 1970 مشخص شده است. این مقدار حداکثر 1 ساعت پس از زمان صادر شده است.
iat زمان صدور این ادعا، از ساعت 00:00:00 UTC، 1 ژانویه 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، مجموعه ادعای JWT باید به UTF-8 و Base64url-safe کدگذاری شود. در زیر نمونه ای از نمایش JSON از مجموعه ادعای 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 Web Signature (JWS) مشخصاتی است که مکانیزم تولید امضا را برای JWT راهنمایی می کند. ورودی امضا آرایه بایتی از محتوای زیر است:

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

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

نمایش UTF-8 ورودی را با استفاده از SHA256withRSA (همچنین با نام RSASSA-PKCS1-V1_5-SIGN با تابع هش SHA-256 نیز شناخته می شود) با کلید خصوصی به دست آمده از 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 کدگذاری شده است. 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 استفاده مجدد کرد.

فراخوانی Google API

جاوا

با انجام مراحل زیر از شی GoogleCredential برای فراخوانی APIهای Google استفاده کنید:

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

پایتون

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

  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 اعطا شده باشد، می توانید از این رمز برای برقراری تماس با Google API از طرف یک حساب سرویس یا حساب کاربری خاص استفاده کنید. برای انجام این کار، توکن دسترسی را با درج یک پارامتر query access_token یا یک مقدار Authorization HTTP header Bearer در درخواست API قرار دهید. در صورت امکان، هدر HTTP ترجیح داده می شود، زیرا رشته های پرس و جو در گزارش های سرور قابل مشاهده هستند. در بیشتر موارد می‌توانید از کتابخانه سرویس گیرنده برای تنظیم تماس‌های خود با Google API استفاده کنید (به عنوان مثال، هنگام تماس با Drive Files API ).

می‌توانید همه APIهای Google را امتحان کنید و دامنه آنها را در OAuth 2.0 Playground مشاهده کنید.

نمونه های HTTP GET

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

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

در اینجا یک فراخوانی به همان API برای کاربر تأیید شده با استفاده از پارامتر رشته query 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

یا، گزینه پارامتر query string:

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. اگر می‌خواهید از تفویض اختیار در سطح دامنه استفاده کنید، حساب سرویس در کنسول مدیریت دامنه کاربر مجاز نیست.

اطمینان حاصل کنید که حساب سرویس در صفحه اعطای نمایندگی در سطح دامنه کنسول مدیریت برای کاربر در ادعای sub (فیلد) مجاز است.

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

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 (فیلد) مجاز است و شامل همه دامنه‌هایی است که در ادعای scope JWT خود درخواست می‌کنید.

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

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

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

invalid_client (هر ارزشی)

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

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

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

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

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

invalid_grant Not a valid email. کاربر وجود ندارد بررسی کنید که آدرس ایمیل در ادعای 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 در آینده بیش از 65 دقیقه از مقدار iat باشد یا مقدار exp کمتر از مقدار iat باشد، ممکن است اتفاق بیفتد.

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

invalid_grant Invalid JWT Signature.

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

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

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

سعی کنید از کتابخانه OAuth ارائه شده توسط Google استفاده کنید تا مطمئن شوید که 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 > حساب‌های سرویس ، حساب سرویس را فعال کنید که حاوی «شناسه کلید» است که برای امضای ادعا استفاده می‌شود.

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

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

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

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

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

  1. همانطور که در بالا توضیح داده شد یک حساب کاربری ایجاد کنید . حتماً فایل JSON را که هنگام ایجاد حساب دریافت می‌کنید نگه دارید.
  2. با استفاده از هر کتابخانه استاندارد JWT، مانند کتابخانه ای که در jwt.io یافت می شود، یک JWT با هدر و بارگذاری مانند مثال زیر ایجاد کنید:
    {
      "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 ، زمان فعلی یونیکس و برای فیلد exp ، زمان را دقیقاً 3600 ثانیه بعد، زمانی که JWT منقضی می شود، مشخص کنید.

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

مثلا:

جاوا

با استفاده از google-api-java-client و java-jwt :

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

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