ตรวจสอบสิทธิ์โดยใช้ OpenID Connect บน Android

หากคุณอัปเกรดเป็น Firebase Authentication ด้วย Identity Platform แล้ว คุณจะตรวจสอบสิทธิ์ผู้ใช้ด้วย Firebase ได้โดยใช้ผู้ให้บริการที่สอดคล้องกับ OpenID Connect (OIDC) ที่คุณเลือก ซึ่งทำให้สามารถใช้ผู้ให้บริการข้อมูลประจำตัวที่ Firebase ไม่รองรับโดยกำเนิดได้

ก่อนที่คุณจะเริ่ม

หากต้องการลงชื่อเข้าใช้ผู้ใช้โดยใช้ผู้ให้บริการ OIDC คุณต้องรวบรวมข้อมูลบางอย่างจากผู้ให้บริการก่อน:

  • รหัสลูกค้า : สตริงเฉพาะของผู้ให้บริการที่ระบุแอปของคุณ ผู้ให้บริการของคุณอาจกำหนดรหัสลูกค้าที่แตกต่างกันให้กับแต่ละแพลตฟอร์มที่คุณรองรับ นี่เป็นหนึ่งในค่าของการอ้างสิทธิ์ aud ในโทเค็น ID ที่ออกโดยผู้ให้บริการของคุณ

  • รหัสลับไคลเอ็นต์ : สตริงลับที่ผู้ให้บริการใช้เพื่อยืนยันความเป็นเจ้าของรหัสไคลเอ็นต์ สำหรับทุกรหัสไคลเอ็นต์ คุณจะต้องมีรหัสลับไคลเอ็นต์ที่ตรงกัน (ค่านี้จำเป็นเฉพาะในกรณีที่คุณใช้ โฟลว์โค้ดรับรองความ ถูกต้อง ซึ่งขอแนะนำเป็นอย่างยิ่ง)

  • ผู้ออก : สตริงที่ระบุผู้ให้บริการของคุณ ค่านี้ต้องเป็น URL ที่เมื่อต่อท้ายด้วย /.well-known/openid-configuration คือตำแหน่งของเอกสารการค้นพบ OIDC ของผู้ให้บริการ ตัวอย่างเช่น หากผู้ออกคือ https://auth.example.com เอกสารการค้นพบจะต้องมีอยู่ที่ https://auth.example.com/.well-known/openid-configuration

หลังจากที่คุณมีข้อมูลข้างต้นแล้ว ให้เปิดใช้งาน OpenID Connect เป็นผู้ให้บริการลงชื่อเข้าใช้สำหรับโปรเจ็กต์ Firebase ของคุณ:

  1. เพิ่ม Firebase ในโครงการ Android ของคุณ

  2. หากคุณยังไม่ได้อัปเกรดเป็น Firebase Authentication ด้วย 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 โดยใช้ Builder พร้อมด้วย ID ของผู้ให้บริการ

    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 , response_type , การเปลี่ยนเส้นทาง_uri , state , ขอบเขต และ response_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. ตรวจสอบสิทธิ์กับ Firebase โดยใช้วัตถุผู้ให้บริการ OAuth โปรดทราบว่าการดำเนินการนี้จะแตกต่างจากการดำเนินการ FirebaseAuth อื่นๆ โดยจะควบคุม UI ของคุณโดยการเปิด แท็บ Chrome ที่กำหนดเองขึ้น มา ด้วยเหตุนี้ อย่าอ้างอิงกิจกรรมของคุณใน OnSuccessListener และ OnFailureListener ที่คุณแนบ เนื่องจากกิจกรรมเหล่านี้จะแยกออกทันทีเมื่อการดำเนินการเริ่ม UI

    คุณควรตรวจสอบก่อนว่าคุณได้รับการตอบกลับแล้วหรือไม่ การลงชื่อเข้าใช้ด้วยวิธีนี้จะทำให้กิจกรรมของคุณอยู่ในเบื้องหลัง ซึ่งหมายความว่าระบบสามารถเรียกคืนกิจกรรมได้ในระหว่างขั้นตอนการลงชื่อเข้าใช้ เพื่อให้แน่ใจว่าคุณไม่ให้ผู้ใช้ลองอีกครั้งหากเกิดเหตุการณ์เช่นนี้ คุณควรตรวจสอบว่ามีผลลัพธ์อยู่แล้วหรือไม่

    หากต้องการตรวจสอบว่ามีผลลัพธ์ที่ค้างอยู่หรือไม่ ให้โทร 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. แม้ว่าตัวอย่างข้างต้นจะเน้นไปที่ขั้นตอนการลงชื่อเข้าใช้ แต่คุณยังมีความสามารถในการลิงก์ผู้ให้บริการ OIDC กับผู้ใช้ที่มีอยู่โดยใช้ startActivityForLinkWithProvider ตัวอย่างเช่น คุณสามารถเชื่อมโยงผู้ให้บริการหลายรายกับผู้ใช้รายเดียวกันได้ โดยอนุญาตให้ผู้ให้บริการรายใดรายหนึ่งลงชื่อเข้าใช้ด้วยได้

    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 และ กฎความปลอดภัยของ พื้นที่เก็บข้อมูลบนคลาวด์ คุณสามารถรับ ID ผู้ใช้เฉพาะของผู้ใช้ที่ลงชื่อเข้าใช้จากตัวแปร auth และใช้เพื่อควบคุมข้อมูลที่ผู้ใช้สามารถเข้าถึงได้

คุณสามารถอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้แอปของคุณโดยใช้ผู้ให้บริการตรวจสอบสิทธิ์หลายรายได้โดย การเชื่อมโยงข้อมูลประจำตัวของผู้ให้บริการตรวจสอบสิทธิ์กับบัญชีผู้ใช้ที่มีอยู่

หากต้องการออกจากระบบผู้ใช้ ให้โทร signOut :

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();