Autenticar usando OpenID Connect en Android

Si actualizó a Firebase Authentication con Identity Platform, puede autenticar a sus usuarios con Firebase utilizando el proveedor compatible con OpenID Connect (OIDC) de su elección. Esto hace posible utilizar proveedores de identidades que Firebase no admite de forma nativa.

Antes de que empieces

Para iniciar sesión como usuario utilizando un proveedor OIDC, primero debe recopilar cierta información del proveedor:

  • ID de cliente : una cadena exclusiva del proveedor que identifica su aplicación. Su proveedor podría asignarle una ID de cliente diferente para cada plataforma que admita. Este es uno de los valores del reclamo aud en tokens de identificación emitidos por su proveedor.

  • Secreto del cliente : una cadena secreta que el proveedor utiliza para confirmar la propiedad de un ID de cliente. Para cada ID de cliente, necesitará un secreto de cliente coincidente. (Este valor es obligatorio solo si utiliza el flujo de código de autenticación , lo cual es muy recomendable).

  • Emisor : una cadena que identifica a su proveedor. Este valor debe ser una URL que, cuando se añade /.well-known/openid-configuration , sea la ubicación del documento de descubrimiento OIDC del proveedor. Por ejemplo, si el emisor es https://auth.example.com , el documento de descubrimiento debe estar disponible en https://auth.example.com/.well-known/openid-configuration .

Una vez que tenga la información anterior, habilite OpenID Connect como proveedor de inicio de sesión para su proyecto de Firebase:

  1. Agrega Firebase a tu proyecto de Android .

  2. Si no has actualizado a Firebase Authentication con Identity Platform, hazlo. La autenticación OpenID Connect solo está disponible en proyectos actualizados.

  3. En la página Proveedores de inicio de sesión de Firebase console, haga clic en Agregar nuevo proveedor y luego haga clic en OpenID Connect .

  4. Seleccione si utilizará el flujo de código de autorización o el flujo de concesión implícito .

    Debe utilizar siempre el flujo de código si su proveedor lo admite . El flujo implícito es menos seguro y se desaconseja su uso.

  5. Dé un nombre a este proveedor. Tenga en cuenta el ID del proveedor que se genera: algo así como oidc.example-provider . Necesitará esta identificación cuando agregue el código de inicio de sesión a su aplicación.

  6. Especifique su ID de cliente y secreto de cliente, y la cadena del emisor de su proveedor. Estos valores deben coincidir exactamente con los valores que le asignó su proveedor.

  7. Guarde sus cambios.

Maneja el flujo de inicio de sesión con el SDK de Firebase

Si está creando una aplicación para Android, la forma más sencilla de autenticar a sus usuarios con Firebase utilizando su proveedor OIDC es manejar todo el flujo de inicio de sesión con el SDK de Firebase para Android.

Para manejar el flujo de inicio de sesión con el SDK de Firebase para Android, siga estos pasos:

  1. Construya una instancia de un OAuthProvider usando su Builder con el ID del proveedor

    Kotlin+KTX

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

    Java

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

  2. Opcional : especifique parámetros OAuth personalizados adicionales que desee enviar con la solicitud 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");

    Consulte con su proveedor de OIDC los parámetros que admite. Ten en cuenta que no puedes pasar los parámetros requeridos por Firebase con setCustomParameters() . Estos parámetros son client_id , tipo_respuesta , redirección_uri , estado , alcance y modo_respuesta .

  3. Opcional : especifique alcances de OAuth 2.0 adicionales más allá del perfil básico que desea solicitar al proveedor de autenticación.

    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);

    Consulte con su proveedor de OIDC los alcances que utilizan.

  4. Autentíquese con Firebase utilizando el objeto proveedor de OAuth. Tenga en cuenta que, a diferencia de otras operaciones de FirebaseAuth, esto tomará el control de su interfaz de usuario al abrir una pestaña personalizada de Chrome . Como resultado, no haga referencia a su actividad en OnSuccessListener y OnFailureListener que adjunte, ya que se desconectarán inmediatamente cuando la operación inicie la interfaz de usuario.

    Primero debes verificar si ya has recibido una respuesta. Iniciar sesión con este método coloca su actividad en segundo plano, lo que significa que el sistema puede reclamarla durante el flujo de inicio de sesión. Para asegurarse de que no haga que el usuario vuelva a intentarlo si esto sucede, debe verificar si ya hay un resultado presente.

    Para comprobar si hay un resultado pendiente, llame 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.
    }

    Para iniciar el flujo de inicio de sesión, llame a 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. Si bien los ejemplos anteriores se centran en los flujos de inicio de sesión, también tiene la posibilidad de vincular un proveedor de OIDC a un usuario existente mediante startActivityForLinkWithProvider . Por ejemplo, puede vincular varios proveedores al mismo usuario, permitiéndoles iniciar sesión con cualquiera de ellos.

    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. Se puede usar el mismo patrón con startActivityForReauthenticateWithProvider , que se puede usar para recuperar credenciales nuevas para operaciones confidenciales que requieren un inicio de sesión reciente.

    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.
                        }
                    });

Manejar el flujo de inicio de sesión manualmente

Si ya implementaste el flujo de inicio de sesión de OpenID Connect en tu aplicación, puedes usar el token de ID directamente para autenticarte con 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.
            }
        });

Próximos pasos

Después de que un usuario inicia sesión por primera vez, se crea una nueva cuenta de usuario y se vincula a las credenciales (es decir, el nombre de usuario y la contraseña, el número de teléfono o la información del proveedor de autenticación) con las que el usuario inició sesión. Esta nueva cuenta se almacena como parte de su proyecto de Firebase y se puede usar para identificar a un usuario en cada aplicación de su proyecto, independientemente de cómo inicie sesión el usuario.

  • En tus aplicaciones, puedes obtener la información básica del perfil del usuario desde el objeto FirebaseUser . Consulte Administrar usuarios .

  • En las reglas de seguridad de Firebase Realtime Database y Cloud Storage, puede obtener el ID de usuario único del usuario que inició sesión a partir de la variable auth y usarlo para controlar a qué datos puede acceder un usuario.

Puede permitir que los usuarios inicien sesión en su aplicación utilizando múltiples proveedores de autenticación vinculando las credenciales del proveedor de autenticación a una cuenta de usuario existente.

Para cerrar la sesión de un usuario, llame signOut :

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();