احراز هویت با استفاده از OpenID Connect در Android

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

قبل از شروع

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

برای مدیریت جریان ورود به سیستم با Firebase Android SDK، این مراحل را دنبال کنید:

  1. یک نمونه از یک OAuthProvider با استفاده از سازنده آن با شناسه ارائه دهنده بسازید

    Kotlin+KTX

    val providerBuilder = OAuthProvider.newBuilder("oidc.example-provider")

    Java

    OAuthProvider.Builder providerBuilder = OAuthProvider.newBuilder("oidc.example-provider");

  2. اختیاری : پارامترهای سفارشی OAuth اضافی را که می خواهید با درخواست OAuth ارسال کنید، مشخص کنید.

    Kotlin+KTX

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "user@example.com")

    Java

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "user@example.com");

    با ارائه دهنده OIDC خود برای پارامترهایی که پشتیبانی می کند بررسی کنید. توجه داشته باشید که نمی‌توانید پارامترهای مورد نیاز Firebase را با setCustomParameters() ارسال کنید. این پارامترها عبارتند از client_id , answer_type , redirect_uri , state , scope و answer_mode .

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

    Kotlin+KTX

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    providerBuilder.scopes = listOf("mail.read", "calendars.read")

    Java

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    List<String> scopes =
            new ArrayList<String>() {
                {
                    add("mail.read");
                    add("calendars.read");
                }
            };
    providerBuilder.setScopes(scopes);

    با ارائه‌دهنده OIDC خود برای دامنه‌هایی که استفاده می‌کنند، تماس بگیرید.

  4. با استفاده از شی ارائه دهنده OAuth با Firebase احراز هویت کنید. توجه داشته باشید که برخلاف سایر عملیات FirebaseAuth، با باز کردن یک برگه سفارشی Chrome ، رابط کاربری شما را کنترل می‌کند. در نتیجه، فعالیت خود را در OnSuccessListener و OnFailureListener که پیوست می‌کنید ارجاع ندهید، زیرا با شروع عملیات رابط کاربری، فوراً جدا می‌شوند.

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

    برای بررسی اینکه آیا نتیجه معلقی وجود دارد، با getPendingAuthResult تماس بگیرید:

    Kotlin+KTX

    val pendingResultTask = firebaseAuth.pendingAuthResult
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
            .addOnSuccessListener {
                // User is signed in.
                // IdP data available in
                // authResult.getAdditionalUserInfo().getProfile().
                // The OAuth access token can also be retrieved:
                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                // The OAuth secret can be retrieved by calling:
                // ((OAuthCredential)authResult.getCredential()).getSecret().
            }
            .addOnFailureListener {
                // Handle failure.
            }
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    Java

    Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                // User is signed in.
                                // IdP data available in
                                // authResult.getAdditionalUserInfo().getProfile().
                                // The OAuth access token can also be retrieved:
                                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                                // The OAuth secret can be retrieved by calling:
                                // ((OAuthCredential)authResult.getCredential()).getSecret().
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // Handle failure.
                            }
                        });
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    برای شروع جریان ورود به سیستم، startActivityForSignInWithProvider را فراخوانی کنید:

    Kotlin+KTX

    firebaseAuth
        .startActivityForSignInWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is signed in.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // ((OAuthCredential)authResult.getCredential()).getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    firebaseAuth
            .startActivityForSignInWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is signed in.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // ((OAuthCredential)authResult.getCredential()).getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

  5. در حالی که مثال‌های بالا بر جریان‌های ورود به سیستم تمرکز دارند، شما همچنین می‌توانید با استفاده از startActivityForLinkWithProvider یک ارائه‌دهنده OIDC را به یک کاربر موجود پیوند دهید. برای مثال، می‌توانید چندین ارائه‌دهنده را به یک کاربر پیوند دهید و به آنها اجازه دهید با هر یک از آنها وارد سیستم شوند.

    Kotlin+KTX

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForLinkWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // Provider credential is linked to the current user.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // authResult.getCredential().getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // authResult.getCredential().getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForLinkWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // Provider credential is linked to the current user.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // authResult.getCredential().getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // authResult.getCredential().getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

  6. همین الگو را می توان با startActivityForReauthenticateWithProvider استفاده کرد که می تواند برای بازیابی اعتبارنامه های جدید برای عملیات حساسی که نیاز به ورود اخیر دارند استفاده شود.

    Kotlin+KTX

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForReauthenticateWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is re-authenticated with fresh tokens and
            // should be able to perform sensitive operations
            // like account deletion and email or password
            // update.
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is re-authenticated with fresh tokens and
                            // should be able to perform sensitive operations
                            // like account deletion and email or password
                            // update.
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

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

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

Kotlin+KTX

val providerId = "oidc.example-provider" // As registered in Firebase console.
val credential = oAuthCredential(providerId) {
    setIdToken(idToken) // ID token from OpenID Connect flow.
}
Firebase.auth
    .signInWithCredential(credential)
    .addOnSuccessListener { authResult ->
        // User is signed in.

        // IdP data available in:
        //    authResult.additionalUserInfo.profile
    }
    .addOnFailureListener { e ->
        // Handle failure.
    }

Java

AuthCredential credential = OAuthProvider
        .newCredentialBuilder("oidc.example-provider")  // As registered in Firebase console.
        .setIdToken(idToken)  // ID token from OpenID Connect flow.
        .build();
FirebaseAuth.getInstance()
        .signInWithCredential(credential)
        .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                // User is signed in.

                // IdP data available in:
                //    authResult.getAdditionalUserInfo().getProfile()
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Handle failure.
            }
        });

مراحل بعدی

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

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

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

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

برای خروج از سیستم کاربر، signOut تماس بگیرید:

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();