Una biblioteca React Native bien escrita que brinda soporte para la autenticación de Apple en iOS y Android, incluido soporte para todas las variantes AppleButton
.
La biblioteca @invertase/react-native-apple-authentication
no funcionará si no garantiza lo siguiente:
Estás utilizando React Native versión 0.60
o superior.
(Solo iOS) Ha configurado el entorno de desarrollo iOS nativo de reacción en su máquina (solo funcionará en Mac). De lo contrario, siga la documentación oficial de React Native para comenzar: Documentación de introducción a React Native.
(Solo iOS) Estás utilizando Xcode versión 11
o superior. Esto le permitirá desarrollar con iOS versión 13
y superior, cuando las API para iniciar sesión con Apple estén disponibles.
Una vez que esté seguro de haber cumplido con lo anterior, siga nuestra guía de configuración del entorno de desarrollo inicial.
La versión 2 agregó soporte para Android e introdujo algunos cambios importantes en la forma en que se accede a los métodos. Consulte la Guía de migración.
yarn add @invertase/react-native-apple-authentication
(cd ios && pod install)
No tendrá que vincular manualmente este módulo, ya que admite el vínculo automático de React Native.
Para habilitar la capacidad Iniciar sesión con Apple en su aplicación, establezca la propiedad ios.usesAppleSignIn en verdadero en la configuración de la aplicación de su proyecto:
{
"expo" : {
"ios" : {
"usesAppleSignIn" : true
}
}
}
Es posible que también necesite ejecutar npx expo prebuild
.
A continuación se detallan pasos sencillos que le ayudarán a ponerse en marcha. La implementación difiere entre iOS y Android, por lo que si tiene problemas, asegúrese de consultar los documentos. Omita y diríjase a los ejemplos de código completos que se indican a continuación si prefiere ver una implementación más completa:
React Native Firebase
; consulte nuestra guía de Firebase Importe el módulo appleAuth
(documentación de API) y el elemento miembro exportado AppleButton
(documentación de API) de la biblioteca @invertase/react-native-apple-authentication
. Configure un controlador de eventos ( onPress
) para iniciar la solicitud de autenticación.
// App.js
import React from 'react' ;
import { View } from 'react-native' ;
import { AppleButton } from '@invertase/react-native-apple-authentication' ;
async function onAppleButtonPress ( ) {
}
function App ( ) {
return (
< View >
< AppleButton
buttonStyle = { AppleButton . Style . WHITE }
buttonType = { AppleButton . Type . SIGN_IN }
style = { {
width : 160 , // You must specify a width
height : 45 , // You must specify a height
} }
onPress = { ( ) => onAppleButtonPress ( ) }
/ >
< / View >
) ;
}
// App.js
import { appleAuth } from '@invertase/react-native-apple-authentication' ;
async function onAppleButtonPress ( ) {
// performs login request
const appleAuthRequestResponse = await appleAuth . performRequest ( {
requestedOperation : appleAuth . Operation . LOGIN ,
// Note: it appears putting FULL_NAME first is important, see issue #293
requestedScopes : [ appleAuth . Scope . FULL_NAME , appleAuth . Scope . EMAIL ] ,
} ) ;
// get current authentication state for user
// /! This method must be tested on a real device. On the iOS simulator it always throws an error.
const credentialState = await appleAuth . getCredentialStateForUser ( appleAuthRequestResponse . user ) ;
// use credentialState response to ensure the user is authenticated
if ( credentialState === appleAuth . State . AUTHORIZED ) {
// user is authenticated
}
}
Configure el detector de eventos para cuando se hayan revocado las credenciales del usuario.
// App.js
import React , { useEffect } from 'react' ;
import { View } from 'react-native' ;
import { appleAuth , AppleButton } from '@invertase/react-native-apple-authentication' ;
function App ( ) {
useEffect ( ( ) => {
// onCredentialRevoked returns a function that will remove the event listener. useEffect will call this function when the component unmounts
return appleAuth . onCredentialRevoked ( async ( ) => {
console . warn ( 'If this function executes, User Credentials have been Revoked' ) ;
} ) ;
} , [ ] ) ; // passing in an empty array as the second argument ensures this is only ran once when component mounts initially.
return (
< View >
< AppleButton onPress = { ( ) => onAppleButtonPress ( ) } / >
< / View >
) ;
}
Hay una operación appleAuth.Operation.LOGOUT
, sin embargo, no funciona como se esperaba y Apple ni siquiera la utiliza en su código de ejemplo. Consulte este número para obtener más información.
Por lo tanto, al cerrar sesión se recomienda borrar todos los datos que tiene de un usuario, recopilados durante appleAuth.Operation.LOGIN
.
Asegúrese de configurar correctamente su cuenta de desarrollador de Apple para permitir una autenticación adecuada en Android. Puede consultar nuestra guía para obtener más información.
// App.js
import React from 'react' ;
import { View } from 'react-native' ;
import { appleAuthAndroid , AppleButton } from '@invertase/react-native-apple-authentication' ;
async function onAppleButtonPress ( ) {
}
// Apple authentication requires API 19+, so we check before showing the login button
function App ( ) {
return (
< View >
{ appleAuthAndroid . isSupported && (
< AppleButton
buttonStyle = { AppleButton . Style . WHITE }
buttonType = { AppleButton . Type . SIGN_IN }
onPress = { ( ) => onAppleButtonPress ( ) }
/ >
) }
< / View >
) ;
}
// App.js
import { appleAuthAndroid } from '@invertase/react-native-apple-authentication' ;
import 'react-native-get-random-values' ;
import { v4 as uuid } from 'uuid'
async function onAppleButtonPress ( ) {
// Generate secure, random values for state and nonce
const rawNonce = uuid ( ) ;
const state = uuid ( ) ;
// Configure the request
appleAuthAndroid . configure ( {
// The Service ID you registered with Apple
clientId : 'com.example.client-android' ,
// Return URL added to your Apple dev console. We intercept this redirect, but it must still match
// the URL you provided to Apple. It can be an empty route on your backend as it's never called.
redirectUri : 'https://example.com/auth/callback' ,
// The type of response requested - code, id_token, or both.
responseType : appleAuthAndroid . ResponseType . ALL ,
// The amount of user information requested from Apple.
scope : appleAuthAndroid . Scope . ALL ,
// Random nonce value that will be SHA256 hashed before sending to Apple.
nonce : rawNonce ,
// Unique state value used to prevent CSRF attacks. A UUID will be generated if nothing is provided.
state ,
} ) ;
// Open the browser window for user sign in
const response = await appleAuthAndroid . signIn ( ) ;
// Send the authorization code to your backend for verification
}
Esta biblioteca funciona en MacOS 10.15+ si se usa junto con reaccionar-native-macos.
yarn add react-apple-signin-auth
en su proyecto web. import AppleSignin from 'react-apple-signin-auth' ;
/** Apple Signin button */
const MyAppleSigninButton = ( { ... rest } ) => (
< AppleSignin
/** Auth options passed to AppleID.auth.init() */
authOptions = { {
clientId : 'SAME AS ANDROID' ,
redirectURI : 'SAME AS ANDROID' ,
scope : 'email name' ,
state : 'state' ,
/** sha256 nonce before sending to apple to unify with native firebase behavior - https://github.com/invertase/react-native-apple-authentication/issues/28 */
nonce : sha256 ( 'nonce' ) ,
/** We have to usePopup since we need clientSide authentication */
usePopup : true ,
} }
onSuccess = { ( response ) => {
console . log ( response ) ;
// {
// "authorization": {
// "state": "[STATE]",
// "code": "[CODE]",
// "id_token": "[ID_TOKEN]"
// },
// "user": {
// "email": "[EMAIL]",
// "name": {
// "firstName": "[FIRST_NAME]",
// "lastName": "[LAST_NAME]"
// }
// }
// }
} }
/ >
) ;
export default MyAppleSigninButton ;
appleAuth.performRequest
(iOS) y appleAuthAndroid.configure
(Android) tiene automáticamente un hash SHA256. crypto . createHash ( 'sha256' ) . update ( nonce ) . digest ( 'hex' ) ;
import crypto from 'crypto' ;
import appleSigninAuth from 'apple-signin-auth' ;
appleIdTokenClaims = await appleSigninAuth . verifyIdToken ( id_token , {
/** sha256 hex hash of raw nonce */
nonce : nonce ? crypto . createHash ( 'sha256' ) . update ( nonce ) . digest ( 'hex' ) : undefined ,
} ) ;
Toda la documentación de la API es generada por typedoc y está disponible en la carpeta typedocs
.
¿Por qué full name
y email
son null
?
full name
y email
en el primer inicio de sesión; devolverá null
en el inicio de sesión siguiente, por lo que deberá guardar esos datos. const appleAuthRequestResponse = await appleAuth . performRequest ( {
requestedOperation : appleAuth . Operation . LOGIN ,
requestedScopes : [ appleAuth . Scope . FULL_NAME , appleAuth . Scope . EMAIL ] ,
} ) ;
Settings > Apple ID, iCloud, iTunes & App Store > Password & Security > Apps Using Your Apple ID
, toque su aplicación y toque Stop Using Apple ID
. Ahora puede iniciar sesión nuevamente y recibirá el full name
y el correo electrónico.email
del lado del servidor inspeccionando el id_token
devuelto por Apple al verificar al usuario.¿Cómo cambiar el idioma de los botones? (iOS)
< key >CFBundleDevelopmentRegion</ key >
< string >en</ string >
< key >CFBundleAllowMixedLocalizations</ key >
< string >true</ string >
¿Cómo recibo el correo electrónico después del primer inicio de sesión?
import { appleAuth } from '@invertase/react-native-apple-authentication' ;
import { jwtDecode } from 'jwt-decode' ;
const appleAuthRequestResponse = await appleAuth . performRequest ( {
requestedOperation : appleAuth . Operation . LOGIN ,
requestedScopes : [ appleAuth . Scope . EMAIL , appleAuth . Scope . FULL_NAME ]
} ) ;
// other fields are available, but full name is not
const { email , email_verified , is_private_email , sub } = jwtDecode ( appleAuthRequestResponse . identityToken )
The operation couldn’t be completed. (com.apple.AuthenticationServices.AuthorizationError error 1000.)
Compruebe que la configuración de conexión se haya realizado correctamente. La configuración se puede encontrar aquí: Configuración inicial
Si está utilizando la función getCredentialStateForUser
en un simulador, este error siempre se activará, ya que esta función verifica la autenticidad del dispositivo.
Debes probar tu código en un dispositivo real.
Si está utilizando un simulador, vaya a Administrar cuenta de Apple.
Busque "Dispositivos", seleccione "Simulador" y presione "Eliminar de la cuenta".
Debería funcionar bien.
"invalid_client" in Android webview
Asegúrese de leer los documentos de configuración de los servicios de Android.
El clientId
que pasó a appleAuthAndroid.configure
no coincide con el ID de servicio que configuró en su consola de desarrollador de Apple.
Su ID de servicio está adjunto a la ID de aplicación principal incorrecta y, por lo tanto, utiliza la clave de inicio de sesión con Apple incorrecta.
El redirectUri
que pasó a appleAuthAndroid.configure
no coincide con una de las URL de retorno o dominios/subdominios que agregó en su consola de desarrollador de Apple. La URL debe coincidir exactamente y no puede contener una cadena de consulta.
Construido y mantenido por Invertase.