احراز هویت با استفاده از OpenID Connect در پلتفرم های اپل

اگر به Firebase Authentication with Identity Platform ارتقا داده‌اید، می‌توانید کاربران خود را با Firebase و با استفاده از ارائه‌دهنده‌ی سازگار با OpenID Connect (OIDC) مورد نظر خود، احراز هویت کنید. این امر امکان استفاده از ارائه‌دهندگان هویتی را که به طور بومی توسط Firebase پشتیبانی نمی‌شوند، فراهم می‌کند.

قبل از اینکه شروع کنی

برای ورود کاربران با استفاده از ارائه‌دهنده OIDC، ابتدا باید اطلاعاتی را از ارائه‌دهنده جمع‌آوری کنید:

  • شناسه مشتری : رشته‌ای منحصر به فرد برای ارائه‌دهنده که برنامه شما را شناسایی می‌کند. ارائه‌دهنده شما ممکن است برای هر پلتفرمی که پشتیبانی می‌کنید، شناسه مشتری متفاوتی به شما اختصاص دهد. این یکی از مقادیر ادعای aud در توکن‌های شناسه صادر شده توسط ارائه‌دهنده شما است.

  • رمز کلاینت : یک رشته مخفی که ارائه دهنده برای تأیید مالکیت شناسه کلاینت از آن استفاده می‌کند. برای هر شناسه کلاینت، به یک رمز کلاینت منطبق نیاز خواهید داشت. (این مقدار فقط در صورتی لازم است که از جریان کد احراز هویت استفاده می‌کنید، که اکیداً توصیه می‌شود.)

  • صادرکننده : رشته‌ای که ارائه‌دهنده شما را شناسایی می‌کند. این مقدار باید یک URL باشد که وقتی با /.well-known/openid-configuration اضافه می‌شود، محل سند کشف OIDC ارائه‌دهنده باشد. برای مثال، اگر صادرکننده https://auth.example.com باشد، سند کشف باید در https://auth.example.com/.well-known/openid-configuration در دسترس باشد.

پس از اینکه اطلاعات فوق را در اختیار داشتید، OpenID Connect را به عنوان ارائه دهنده ورود به سیستم برای پروژه Firebase خود فعال کنید:

  1. فایربیس را به پروژه iOS خود اضافه کنید .

  2. اگر به Firebase Authentication with Identity Platform ارتقا نداده‌اید، این کار را انجام دهید. احراز هویت OpenID Connect فقط در پروژه‌های ارتقا یافته در دسترس است.

  3. در صفحه ارائه دهندگان ورود به سیستم کنسول Firebase ، روی افزودن ارائه دهنده جدید کلیک کنید و سپس روی OpenID Connect کلیک کنید.

  4. انتخاب کنید که آیا از جریان کد مجوز یا جریان اعطای ضمنی استفاده خواهید کرد.

    اگر ارائه‌دهنده شما از جریان کد پشتیبانی می‌کند، همیشه باید از آن استفاده کنید . جریان ضمنی امنیت کمتری دارد و استفاده از آن اکیداً توصیه نمی‌شود.

  5. به این ارائه‌دهنده یک نام بدهید. به شناسه ارائه‌دهنده‌ای که ایجاد می‌شود توجه کنید: چیزی شبیه به oidc.example-provider . هنگام افزودن کد ورود به برنامه خود به این شناسه نیاز خواهید داشت.

  6. شناسه مشتری و رمز مشتری و رشته صادرکننده ارائه دهنده خود را مشخص کنید. این مقادیر باید دقیقاً با مقادیری که ارائه دهنده شما به شما اختصاص داده است، مطابقت داشته باشند.

  7. تغییرات خود را ذخیره کنید.

مدیریت جریان ورود به سیستم با Firebase SDK

ساده‌ترین راه برای احراز هویت کاربران با Firebase با استفاده از ارائه‌دهنده OIDC، مدیریت کل جریان ورود به سیستم با Firebase SDK است.

برای مدیریت جریان ورود به سیستم با SDK پلتفرم‌های اپل فایربیس، این مراحل را دنبال کنید:

  1. طرح‌های URL سفارشی را به پروژه Xcode خود اضافه کنید:

    1. پیکربندی پروژه خود را باز کنید: روی نام پروژه در نمای درختی سمت چپ دوبار کلیک کنید. برنامه خود را از بخش TARGETS انتخاب کنید، سپس تب Info را انتخاب کنید و بخش URL Types را باز کنید.
    2. روی دکمه + کلیک کنید و شناسه برنامه رمزگذاری شده خود را به عنوان یک طرح URL اضافه کنید. می‌توانید شناسه برنامه رمزگذاری شده خود را در صفحه تنظیمات عمومی کنسول Firebase، در بخش برنامه iOS خود پیدا کنید. سایر فیلدها را خالی بگذارید.

      پس از تکمیل، پیکربندی شما باید چیزی شبیه به موارد زیر باشد (اما با مقادیر خاص برنامه شما):

      تصویری از رابط کاربری تنظیم طرح URL سفارشی Xcode
  2. با استفاده از شناسه ارائه‌دهنده‌ای که در کنسول Firebase دریافت کرده‌اید، یک نمونه از OAuthProvider ایجاد کنید.

    سویفت

    var provider = OAuthProvider(providerID: "oidc.example-provider")
    

    هدف-سی

    FIROAuthProvider *provider = [FIROAuthProvider providerWithProviderID:@"oidc.example-provider"];
    
  3. اختیاری : پارامترهای سفارشی اضافی OAuth را که می‌خواهید با درخواست OAuth ارسال کنید، مشخص کنید.

    سویفت

    provider.customParameters = [
      "login_hint": "user@example.com"
    ]
    

    هدف-سی

    [provider setCustomParameters:@{@"login_hint": @"user@example.com"}];
    

    با ارائه‌دهنده‌ی سرویس خود در مورد پارامترهایی که پشتیبانی می‌کند، مشورت کنید. توجه داشته باشید که نمی‌توانید پارامترهای مورد نیاز Firebase را با setCustomParameters ارسال کنید. این پارامترها عبارتند از client_id ، response_type ، redirect_uri ، state ، scope و response_mode .

  4. اختیاری : محدوده‌های اضافی OAuth 2.0 فراتر از پروفایل پایه که می‌خواهید از ارائه‌دهنده احراز هویت درخواست کنید را مشخص کنید.

    سویفت

    provider.scopes = ["mail.read", "calendars.read"]
    

    هدف-سی

    [provider setScopes:@[@"mail.read", @"calendars.read"]];
    

    با ارائه دهنده خود در مورد محدوده‌هایی که پشتیبانی می‌کند، مشورت کنید.

  5. اختیاری : اگر می‌خواهید نحوه نمایش SFSafariViewController یا UIWebView توسط برنامه خود را هنگام نمایش reCAPTCHA به کاربر سفارشی کنید، یک کلاس سفارشی ایجاد کنید که با پروتکل AuthUIDelegate مطابقت داشته باشد.

  6. با استفاده از شیء ارائه دهنده OAuth، با Firebase احراز هویت کنید.

    سویفت

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    provider.getCredentialWith(nil) { credential, error in
      if error != nil {
        // Handle error.
      }
      if credential != nil {
        Auth().signIn(with: credential) { authResult, error in
          if error != nil {
            // Handle error.
          }
          // User is signed in.
          // IdP data available in authResult.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.accessToken
          // OAuth ID token can also be retrieved:
          // (authResult.credential as? OAuthCredential)?.idToken
        }
      }
    }
    

    هدف-سی

    // If you created a custom class that conforms to AuthUIDelegate,
    // pass it instead of nil:
    [provider getCredentialWithUIDelegate:nil
                                completion:^(FIRAuthCredential *_Nullable credential, NSError *_Nullable error) {
      if (error) {
        // Handle error.
      }
      if (credential) {
        [[FIRAuth auth] signInWithCredential:credential
                                  completion:^(FIRAuthDataResult *_Nullable authResult, NSError *_Nullable error) {
          if (error) {
            // Handle error.
          }
          // User is signed in.
          // IdP data available in authResult.additionalUserInfo.profile.
          // OAuth access token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).accessToken
          // OAuth ID token can also be retrieved:
          // ((FIROAuthCredential *)authResult.credential).idToken
        }];
      }
    }];
    
  7. در حالی که مثال‌های بالا بر جریان‌های ورود به سیستم تمرکز دارند، شما همچنین می‌توانید با استفاده از linkWithCredential یک ارائه‌دهنده OIDC را به یک کاربر موجود پیوند دهید. به عنوان مثال، می‌توانید چندین ارائه‌دهنده را به یک کاربر پیوند دهید و به آنها اجازه دهید با هر یک از آنها وارد سیستم شوند.

    سویفت

    Auth().currentUser.link(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    هدف-سی

    [[FIRAuth auth].currentUser
        linkWithCredential:credential
                completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // OIDC credential is linked to the current user.
      // IdP data available in authResult.additionalUserInfo.profile.
      // OAuth access token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    
  8. همین الگو را می‌توان با reauthenticateWithCredential نیز استفاده کرد که می‌تواند برای بازیابی اعتبارنامه‌های جدید برای عملیات حساسی که نیاز به ورود اخیر دارند، استفاده شود.

    سویفت

    Auth().currentUser.reauthenticateWithCredential(withCredential: credential) { authResult, error in
      if error != nil {
        // Handle error.
      }
      // User is re-authenticated with fresh tokens minted and
      // should be able to perform sensitive operations like account
      // deletion and email or password update.
      // IdP data available in result.additionalUserInfo.profile.
      // Additional OAuth access token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.accessToken
      // OAuth ID token can also be retrieved:
      // (authResult.credential as? OAuthCredential)?.idToken
    }
    

    هدف-سی

    [[FIRAuth auth].currentUser
        reauthenticateWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      if (error) {
        // Handle error.
      }
      // User is re-authenticated with fresh tokens minted and
      // should be able to perform sensitive operations like account
      // deletion and email or password update.
      // IdP data available in result.additionalUserInfo.profile.
      // Additional OAuth access token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).accessToken
      // OAuth ID token can also be retrieved:
      // ((FIROAuthCredential *)authResult.credential).idToken
    }];
    

جریان ورود به سیستم را به صورت دستی مدیریت کنید

اگر قبلاً جریان ورود به سیستم OpenID Connect را در برنامه خود پیاده‌سازی کرده‌اید، می‌توانید مستقیماً از توکن ID برای تأیید اعتبار با Firebase استفاده کنید:

سویفت

let credential = OAuthProvider.credential(
    withProviderID: "oidc.example-provider",  // As registered in Firebase console.
    idToken: idToken,  // ID token from OpenID Connect flow.
    rawNonce: nil
)
Auth.auth().signIn(with: credential) { authResult, error in
    if error {
        // Handle error.
        return
    }
    // User is signed in.
    // IdP data available in authResult?.additionalUserInfo?.profile
}

هدف-سی

FIROAuthCredential *credential =
    [FIROAuthProvider credentialWithProviderID:@"oidc.example-provider"  // As registered in Firebase console.
                                       IDToken:idToken  // ID token from OpenID Connect flow.
                                      rawNonce:nil];
[[FIRAuth auth] signInWithCredential:credential
                          completion:^(FIRAuthDataResult * _Nullable authResult,
                                      NSError * _Nullable error) {
    if (error != nil) {
        // Handle error.
        return;
    }
    // User is signed in.
    // IdP data available in authResult.additionalUserInfo.profile
}];

مراحل بعدی

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

  • در برنامه‌های خود، می‌توانید اطلاعات اولیه پروفایل کاربر را از شیء User دریافت کنید. به بخش مدیریت کاربران مراجعه کنید.

  • در قوانین امنیتی پایگاه داده و Cloud Storage Firebase Realtime Database ، می‌توانید شناسه کاربری منحصر به فرد کاربر وارد شده را از متغیر auth دریافت کنید و از آن برای کنترل داده‌هایی که کاربر می‌تواند به آنها دسترسی داشته باشد، استفاده کنید.

شما می‌توانید با پیوند دادن اعتبارنامه‌های ارائه‌دهنده‌ی احراز هویت به یک حساب کاربری موجود، به کاربران اجازه دهید با استفاده از چندین ارائه‌دهنده‌ی احراز هویت به برنامه‌ی شما وارد شوند.

برای خروج از سیستم کاربر، تابع signOut: را فراخوانی کنید.

سویفت

let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}

هدف-سی

NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

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