Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

با استفاده از لینک ایمیل در Android با Firebase احراز هویت شوید

شما می توانید از Firebase Authentication برای ورود به سیستم یک کاربر با ارسال یک ایمیل حاوی پیوند استفاده کنید ، که می تواند برای ورود به سیستم روی آن کلیک کند. در این فرایند ، آدرس ایمیل کاربر نیز تأیید می شود.

ورود به سیستم از طریق ایمیل مزایای زیادی دارد:

  • ثبت نام و ورود با اصطکاک کم.
  • کاهش خطر استفاده مجدد از رمز عبور در برنامه ها ، که می تواند امنیت حتی رمزهای عبور خوب را نیز تضعیف کند.
  • توانایی احراز هویت کاربر در عین حال تأیید اینکه کاربر مالک قانونی آدرس ایمیل است.
  • یک کاربر فقط برای ورود به سیستم به یک حساب ایمیل قابل دسترسی نیاز دارد. هیچگونه مالکیت شماره تلفن یا حساب رسانه اجتماعی لازم نیست.
  • یک کاربر می تواند بدون نیاز به ارائه گذرواژه (یا به خاطر سپردن) به صورت ایمن وارد سیستم شود ، که ممکن است در دستگاه تلفن همراه دشوار باشد.
  • کاربر فعلی که قبلاً با شناسه ایمیل (گذرواژه یا فدرال) وارد شده است ، می تواند ارتقا یابد تا فقط با ایمیل وارد شود. به عنوان مثال ، کاربری که رمز عبور خود را فراموش کرده است می تواند بدون نیاز به بازنشانی گذرواژه خود وارد سیستم شود.

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

پروژه Android خود را تنظیم کنید

  1. اگر شما در حال حاضر، اضافه فایربیس به پروژه آندروید خود را .

  2. با استفاده از فایربیس آندروید BOM ، اعلام وابستگی برای کتابخانه فایربیس احراز هویت آندروید در ماژول خود را (در سطح برنامه) فایل Gradle (معمولا app/build.gradle ).

    همچنین ، به عنوان بخشی از تنظیم احراز هویت Firebase ، باید SDK خدمات Google Play را به برنامه خود اضافه کنید.

    جاوا

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

    با استفاده از فایربیس آندروید BOM ، برنامه شما همیشه نسخه های سازگار با کتابخانه فایربیس آندروید استفاده خواهد کرد.

    (جایگزین) اعلام فایربیس وابستگی کتابخانه بدون استفاده از BOM

    در صورت عدم استفاده از Firebase BoM ، باید هر نسخه کتابخانه Firebase را در خط وابستگی مشخص کنید.

    توجه داشته باشید که در صورت استفاده از کتابخانه فایربیس های متعدد در برنامه شما، ما به شدت توصیه با استفاده از BOM به مدیریت نسخه های کتابخانه، که تضمین می کند که تمام نسخه های سازگار است.

    dependencies {
        // Declare the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth:21.0.1'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth-ktx'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

    با استفاده از فایربیس آندروید BOM ، برنامه شما همیشه نسخه های سازگار با کتابخانه فایربیس آندروید استفاده خواهد کرد.

    (جایگزین) اعلام فایربیس وابستگی کتابخانه بدون استفاده از BOM

    در صورت عدم استفاده از Firebase BoM ، باید هر نسخه کتابخانه Firebase را در خط وابستگی مشخص کنید.

    توجه داشته باشید که در صورت استفاده از کتابخانه فایربیس های متعدد در برنامه شما، ما به شدت توصیه با استفاده از BOM به مدیریت نسخه های کتابخانه، که تضمین می کند که تمام نسخه های سازگار است.

    dependencies {
        // Declare the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-auth-ktx:21.0.1'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:19.2.0'
    }

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

  1. در فایربیس کنسول ، باز کردن بخش تایید.
  2. بر روی ثبت نام در تب روش، فعال کردن ارائه دهنده ایمیل / رمز عبور. توجه داشته باشید که ورود به سیستم ایمیل/رمز عبور باید برای استفاده از ورود به سیستم پیوند ایمیل فعال باشد.
  3. در همان بخش، لینک ایمیل (passwordless ورود به سیستم) ثبت نام در روش فعال کنید.
  4. ذخیره کلیک کنید.

برای شروع جریان احراز هویت، در حال حاضر کاربر با رابط دهید که کاربر به ارائه آدرس ایمیل خود و سپس پاسخ sendSignInLinkToEmail به درخواست که فایربیس ارسال لینک به احراز هویت به ایمیل کاربر.

  1. ساخت ActionCodeSettings شی، فراهم می کند که فایربیس با دستورالعمل در مورد چگونگی ساخت لینک ایمیل. فیلدهای زیر را تنظیم کنید:

    • url : لینک عمیق برای قراردادن و هر دولت های اضافی را به توان همراه منتقل می شود. دامنه پیوند باید در لیست مجاز دامنه های مجاز Firebase Console قرار گیرد ، که می توانید با رفتن به برگه روش ورود به سیستم (احراز هویت-> روش ورود) را پیدا کنید. پیوند کاربر را به این نشانی اینترنتی هدایت می کند در صورتی که برنامه بر روی دستگاه او نصب نشده باشد و برنامه نتواند نصب شود.
    • androidPackageName و IOSBundleId : برنامه های به هنگام استفاده از ورود به سیستم، لینک بر روی یک دستگاه iOS یا Android را باز کرد. بیشتر در مورد چگونگی یادگیری پیکربندی فایربیس پویا لینک به لینک اقدام ایمیل باز از طریق برنامه های تلفن همراه.
    • handleCodeInApp : تنظیم کنید تا درست است. عملیات ورود به سیستم باید بر خلاف سایر اقدامات ایمیل خارج از گروه (بازنشانی رمز عبور و تأیید ایمیل) همیشه در برنامه تکمیل شود. این به این دلیل است که ، در پایان جریان ، انتظار می رود که کاربر وارد سیستم شود و وضعیت Auth او در برنامه باقی بماند.
    • dynamicLinkDomain : هنگامی که چندین دامین پیوند پویا سفارشی برای یک پروژه، مشخص کنید که کدام یک برای استفاده از زمانی لینک به طریق برنامه تلفن همراه مشخص باز می شود (به عنوان مثال، تعریف example.page.link ). در غیر این صورت اولین دامنه به طور خودکار انتخاب می شود.

    جاوا

    ActionCodeSettings actionCodeSettings =
            ActionCodeSettings.newBuilder()
                    // URL you want to redirect back to. The domain (www.example.com) for this
                    // URL must be whitelisted in the Firebase Console.
                    .setUrl("https://www.example.com/finishSignUp?cartId=1234")
                    // This must be true
                    .setHandleCodeInApp(true)
                    .setIOSBundleId("com.example.ios")
                    .setAndroidPackageName(
                            "com.example.android",
                            true, /* installIfNotAvailable */
                            "12"    /* minimumVersion */)
                    .build();

    Kotlin+KTX

    val actionCodeSettings = actionCodeSettings {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url = "https://www.example.com/finishSignUp?cartId=1234"
        // This must be true
        handleCodeInApp = true
        setIOSBundleId("com.example.ios")
        setAndroidPackageName(
                "com.example.android",
                true, /* installIfNotAvailable */
                "12" /* minimumVersion */)
    }

    برای کسب اطلاعات بیشتر در ActionCodeSettings، به مراجعه در عملیات ایمیل دولت از گذشت بخش.

  2. ایمیل خود را از کاربر بخواهید.

  3. پیوند احراز هویت را به ایمیل کاربر ارسال کنید و ایمیل کاربر را در صورت تکمیل ورود به سیستم ایمیل در همان دستگاه ذخیره کنید.

    جاوا

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.sendSignInLinkToEmail(email, actionCodeSettings)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Email sent.");
                    }
                }
            });

    Kotlin+KTX

    Firebase.auth.sendSignInLinkToEmail(email, actionCodeSettings)
            .addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    Log.d(TAG, "Email sent.")
                }
            }

نگرانی های امنیتی

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

شما می توانید این جریان را برای کاربرانی که پیوند ورود به سیستم را در همان دستگاهی که پیوند را درخواست می کنند باز می کنند ، با ذخیره آدرس ایمیل خود به صورت محلی - برای مثال با استفاده از SharedPreferences - هنگام ارسال ایمیل ورود به سیستم ، ساده کنید. سپس ، از این آدرس برای تکمیل جریان استفاده کنید. ایمیل کاربر را در پارامترهای URL تغییر مسیر ارسال نکنید و دوباره از آن استفاده کنید زیرا ممکن است تزریق جلسه فعال شود.

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

همچنین اطمینان حاصل کنید که از URL HTTPS در تولید استفاده می کنید تا از سرورهای واسطه به طور بالقوه پیوند شما جلوگیری شود.

تکمیل ورود به سیستم در برنامه Android

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

فایربیس تایید استفاده از فایربیس پویا لینک در هنگام ارسال یک لینک است که به معنای در یک برنامه تلفن همراه باز می شود. به منظور استفاده از این ویژگی، پویا لینک باید در کنسول فایربیس پیکربندی شود.

  1. پیوندهای پویای Firebase را فعال کنید:

    1. در فایربیس کنسول ، باز کردن بخش پویا لینک.
    2. اگر هنوز شرایط پیوندهای پویا را نپذیرفته اید و دامنه پیوندهای پویا ایجاد نکرده اید ، همین حالا این کار را انجام دهید.

      اگر قبلاً دامنه Dynamic Links ایجاد کرده اید ، به آن توجه داشته باشید. دامنه پیوندهای پویا معمولاً شبیه مثال زیر است:

      example.page.link

      هنگامی که برنامه iOS یا Android خود را برای پیوند پیوند ورودی پیکربندی می کنید ، به این مقدار نیاز خواهید داشت.

  2. پیکربندی برنامه های Android:

    1. برای مدیریت این پیوندها از برنامه Android خود ، نام بسته Android باید در تنظیمات پروژه Firebase Console مشخص شود. علاوه بر این ، SHA-1 و SHA-256 گواهی برنامه باید ارائه شود.
    2. اکنون که دامنه پیوند پویا را اضافه کرده اید و مطمئن شده اید که برنامه Android شما به درستی پیکربندی شده است ، پیوند پویا با شروع راه اندازی به برنامه شما هدایت می شود.
    3. اگر می خواهید از لینک پویا به تغییر مسیر به یک فعالیت خاص، شما نیاز به پیکربندی یک فیلتر intent را در فایل AndroidManifest.xml. این کار را می توان با تعیین دامنه پیوند پویا یا کنترل کننده عملکرد ایمیل در فیلتر هدف انجام داد. : به طور پیش فرض، کنترل عمل ایمیل در دامنه ای مانند مثال زیر به میزبانی
      PROJECT_ID.firebaseapp.com/
    4. هشدارها:
      1. نشانی اینترنتی را که در actionCodeSettings تنظیم کرده اید در فیلتر قصد خود مشخص نکنید.
      2. هنگام ایجاد دامنه پیوند پویا ، ممکن است یک پیوند URL کوتاه نیز ایجاد کرده باشید. این نشانی اینترنتی کوتاه ارسال نخواهد شد. انجام فیلتر قصد خود را پیکربندی کنید به آن را گرفتن با android:pathPrefix ویژگی. این بدان معناست که شما نمی توانید پیوندهای پویای مختلف را در قسمت های مختلف برنامه خود بگیرید. با این حال، شما می توانید بررسی کنید mode پارامتر جستجو در لینک به ببینید که چه عملیات میخواهد انجام شود، و یا استفاده از روش های SDK مانند isSignInWithEmailLink برای دیدن اگر یک لینک است که برنامه خود را دریافت کرده است آنچه شما می خواهید.
    5. برای اطلاعات بیشتر در دریافت لینک پویا، برای اشاره دریافت دستورالعمل پویا لینک آندروید .

پس از دریافت پیوندی که در بالا توضیح داده شد ، بررسی کنید که منظور احراز هویت پیوند ایمیل است و ورود به سیستم را تکمیل کنید.

جاوا

FirebaseAuth auth = FirebaseAuth.getInstance();
Intent intent = getIntent();
String emailLink = intent.getData().toString();

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    String email = "someemail@domain.com";

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Successfully signed in with email link!");
                        AuthResult result = task.getResult();
                        // You can access the new user via result.getUser()
                        // Additional user info profile *not* available via:
                        // result.getAdditionalUserInfo().getProfile() == null
                        // You can check if the user is new or existing:
                        // result.getAdditionalUserInfo().isNewUser()
                    } else {
                        Log.e(TAG, "Error signing in with email link", task.getException());
                    }
                }
            });
}

Kotlin+KTX

val auth = Firebase.auth
val intent = intent
val emailLink = intent.data.toString()

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    val email = "someemail@domain.com"

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
            .addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    Log.d(TAG, "Successfully signed in with email link!")
                    val result = task.result
                    // You can access the new user via result.getUser()
                    // Additional user info profile *not* available via:
                    // result.getAdditionalUserInfo().getProfile() == null
                    // You can check if the user is new or existing:
                    // result.getAdditionalUserInfo().isNewUser()
                } else {
                    Log.e(TAG, "Error signing in with email link", task.exception)
                }
            }
}

برای کسب اطلاعات بیشتر در مورد نحوه رسیدگی ورود به سیستم با لینک ایمیل در نرم افزار IOS، به مراجعه راهنمای در iOS .

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

همچنین می توانید این روش احراز هویت را به یک کاربر موجود پیوند دهید. برای مثال ، کاربری که قبلاً با ارائه دهنده دیگری احراز هویت شده است ، مانند شماره تلفن ، می تواند این روش ورود به حساب موجود خود را اضافه کند.

تفاوت در نیمه دوم عملیات خواهد بود:

جاوا

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Link the credential to the current user.
auth.getCurrentUser().linkWithCredential(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "Successfully linked emailLink credential!");
                    AuthResult result = task.getResult();
                    // You can access the new user via result.getUser()
                    // Additional user info profile *not* available via:
                    // result.getAdditionalUserInfo().getProfile() == null
                    // You can check if the user is new or existing:
                    // result.getAdditionalUserInfo().isNewUser()
                } else {
                    Log.e(TAG, "Error linking emailLink credential", task.getException());
                }
            }
        });

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Link the credential to the current user.
Firebase.auth.currentUser!!.linkWithCredential(credential)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Successfully linked emailLink credential!")
                val result = task.result
                // You can access the new user via result.getUser()
                // Additional user info profile *not* available via:
                // result.getAdditionalUserInfo().getProfile() == null
                // You can check if the user is new or existing:
                // result.getAdditionalUserInfo().isNewUser()
            } else {
                Log.e(TAG, "Error linking emailLink credential", task.exception)
            }
        }

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

جاوا

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Re-authenticate the user with this credential.
auth.getCurrentUser().reauthenticateAndRetrieveData(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // User is now successfully reauthenticated
                } else {
                    Log.e(TAG, "Error reauthenticating", task.getException());
                }
            }
        });

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Re-authenticate the user with this credential.
Firebase.auth.currentUser!!.reauthenticateAndRetrieveData(credential)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                // User is now successfully reauthenticated
            } else {
                Log.e(TAG, "Error reauthenticating", task.exception)
            }
        }

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

در مورد هر دو رمز عبور و ورود به سیستم مبتنی بر لینک شما را در با ایمیل، به افتراق روش ورود به سیستم برای یک کاربر رمز عبور / لینک، با استفاده از fetchSignInMethodsForEmail . این برای جریانهای شناسه مفید است-ابتدا جایی که از کاربر خواسته می شود ایمیل خود را ارائه دهد و سپس روش ورود به سیستم ارائه شود:

جاوا

auth.fetchSignInMethodsForEmail(email)
        .addOnCompleteListener(new OnCompleteListener<SignInMethodQueryResult>() {
            @Override
            public void onComplete(@NonNull Task<SignInMethodQueryResult> task) {
                if (task.isSuccessful()) {
                    SignInMethodQueryResult result = task.getResult();
                    List<String> signInMethods = result.getSignInMethods();
                    if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
                        // User can sign in with email/password
                    } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
                        // User can sign in with email/link
                    }
                } else {
                    Log.e(TAG, "Error getting sign in methods for user", task.getException());
                }
            }
        });

Kotlin+KTX

Firebase.auth.fetchSignInMethodsForEmail(email)
        .addOnSuccessListener { result ->
            val signInMethods = result.signInMethods!!
            if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
                // User can sign in with email/password
            } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
                // User can sign in with email/link
            }
        }
        .addOnFailureListener { exception ->
            Log.e(TAG, "Error getting sign in methods for user", exception)
        }

همانطور که در بالا ایمیل / رمز عبور و ایمیل / لینک توصیف در نظر گرفته همان EmailAuthProvider (همان PROVIDER_ID ) با روش های مختلف ثبت نام در.

مراحل بعدی

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

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

  • در خود پایگاه فایربیس بیدرنگ و ابر ذخیره سازی قوانین امنیتی ، شما می توانید دریافت امضا در شناسه کاربری منحصر به فرد کاربر را از auth متغیر، و استفاده از آن برای کنترل آنچه داده دسترسی کاربر می تواند.

شما می توانید اجازه به کاربران برای ورود به سیستم برنامه خود را با استفاده از ارائه دهندگان تأیید هویت چندگانه توسط ارتباط تایید اعتبار ارائه دهنده به یک حساب کاربری موجود.

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

جاوا

FirebaseAuth.getInstance().signOut();

Kotlin+KTX

Firebase.auth.signOut()