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

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

به طور معمول، یک برنامه زمانی از حساب سرویس استفاده می کند که برنامه از 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 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. در زیر جزئیات حساب خدمات، نام، ID، و شرح برای حساب سرویس، سپس با کلیک ایجاد و ادامه.
  5. اختیاری: تحت گرانت این سرویس دسترسی به حساب را به پروژه ها نقش IAM به کمک مالی به حساب خدمات.
  6. روی ادامه کلیک کنید.
  7. اختیاری: تحت گرانت کاربران دسترسی به این حساب سرویس، اضافه کردن کاربران و یا گروه هایی که مجاز به استفاده از و مدیریت حساب خدمات.
  8. کلیک کنید انجام می شود.
  9. کلیک کنید درست کلید، سپس روی Create کلیک کنید.

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

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

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

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

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

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

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

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

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

برنامه شما اکنون این اختیار را دارد که به عنوان کاربران دامنه شما (برای «جعل هویت» کاربران) تماس های 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("user@example.com");

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

پایتون

پس از اینکه آدرس ایمیل مشتری و کلید خصوصی را از 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

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

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

{"alg":"RS256","typ":"JWT"}

نمایش Base64url این به شرح زیر است:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
تشکیل مجموعه ادعای 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 در RS256 در هدر JWT بیان می alg .

نمایش 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 ، شیء سرویس aa را می‌سازید. برای مثال، برای فراخوانی نسخه 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 ترجیح داده می شود، زیرا رشته های پرس و جو در گزارش های سرور قابل مشاهده هستند. در بیشتر موارد می‌توانید از کتابخانه سرویس گیرنده برای تنظیم تماس‌های خود با APIهای Google استفاده کنید (به عنوان مثال، هنگام تماس با 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 شما منتشر شود.

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 > Service Accounts ، حساب سرویس را فعال کنید که حاوی "شناسه کلید" است که برای امضای ادعا استفاده می شود.

ضمیمه: مجوز حساب سرویس بدون 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