Uma biblioteca React Native bem digitada que fornece suporte para autenticação Apple em iOS e Android, incluindo suporte para todas as variantes AppleButton
.
A biblioteca @invertase/react-native-apple-authentication
não funcionará se você não garantir o seguinte:
Você está usando o React Native versão 0.60
ou superior.
(somente iOS) Você configurou o ambiente de desenvolvimento iOS react-nativo em sua máquina (funcionará apenas no Mac). Caso contrário, siga a documentação oficial do React Native para começar: Documentação de primeiros passos do React Native.
(somente iOS) Você está usando o Xcode versão 11
ou superior. Isso permitirá que você desenvolva usando o iOS versão 13
e superior, quando as APIs para Sign In with Apple estiverem disponíveis.
Quando tiver certeza de que atendeu aos itens acima, siga nosso guia de configuração inicial do ambiente de desenvolvimento.
A versão 2 adicionou suporte ao Android e introduziu algumas mudanças importantes na forma como os métodos são acessados. Consulte o Guia de Migração.
yarn add @invertase/react-native-apple-authentication
(cd ios && pod install)
Você não precisará vincular manualmente este módulo, pois ele oferece suporte à vinculação automática do React Native.
Para ativar o recurso Sign In with Apple no seu aplicativo, defina a propriedade ios.usesAppleSignIn como true na configuração do aplicativo do seu projeto:
{
"expo" : {
"ios" : {
"usesAppleSignIn" : true
}
}
}
Você também pode precisar executar npx expo prebuild
.
Abaixo estão etapas simples para ajudá-lo a começar a trabalhar. A implementação difere entre iOS e Android, portanto, se você estiver com problemas, consulte a documentação. Pule e vá para os exemplos de código completos indicados abaixo se preferir ver uma implementação mais completa:
React Native Firebase
; veja nosso guia do Firebase Importe o módulo appleAuth
(documentação da API) e o elemento membro exportado AppleButton
(documentação da API) da biblioteca @invertase/react-native-apple-authentication
. Configure um manipulador de eventos ( onPress
) para iniciar a solicitação de autenticação.
// 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 o ouvinte de eventos para quando as credenciais do usuário forem revogadas.
// 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 >
) ;
}
Existe uma operação appleAuth.Operation.LOGOUT
, porém ela não funciona como esperado e nem está sendo usada pela Apple em seu código de exemplo. Consulte esta edição para obter mais informações
Portanto, é recomendado, ao sair, apenas limpar todos os dados que você possui de um usuário, coletados durante appleAuth.Operation.LOGIN
.
Certifique-se de configurar corretamente sua conta de desenvolvedor Apple para permitir a autenticação adequada no Android. Você pode verificar nosso guia para mais informações.
// 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 no MacOS 10.15+ se for usada em conjunto com react-native-macos.
yarn add react-apple-signin-auth
em seu projeto da 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) e appleAuthAndroid.configure
(Android) é automaticamente com 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 a documentação da API é gerada pelo typedoc e está disponível na pasta typedocs
Por que full name
e email
retornam null
?
full name
e email
no primeiro login; retornará null
no login seguinte, portanto, você precisará salvar esses dados. 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 em seu aplicativo e toque em Stop Using Apple ID
. Agora você pode fazer login novamente e receberá o full name
e o `e-mail.email
no servidor inspecionando o id_token
retornado pela Apple ao verificar o usuário.Como alterar o idioma dos botões? (iOS)
< key >CFBundleDevelopmentRegion</ key >
< string >en</ string >
< key >CFBundleAllowMixedLocalizations</ key >
< string >true</ string >
Como recebo o e-mail após o primeiro login?
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.)
Verifique se as configurações de conexão foram feitas corretamente. A configuração pode ser encontrada aqui: Configuração inicial
Se você estiver utilizando a função getCredentialStateForUser
em um simulador, este erro sempre será disparado, pois esta função verifica a autenticidade do dispositivo.
Você deve testar seu código em um dispositivo real.
Se você estiver usando um simulador, vá para Gerenciar conta Apple.
Procure por “Dispositivos”, selecione “Simulador” e pressione “Remover da conta”.
Deve funcionar bem.
"invalid_client" in Android webview
Certifique-se de ler os documentos de configuração dos serviços Android.
O clientId
que você passou para appleAuthAndroid.configure
não corresponde ao ID de serviço configurado no console do desenvolvedor Apple.
Seu ID de serviço está anexado ao ID do aplicativo principal errado e, portanto, usa a chave Sign In with Apple incorreta.
O redirectUri
que você passou para appleAuthAndroid.configure
não corresponde a um dos URLs de retorno ou domínios/subdomínios adicionados no console do desenvolvedor da Apple. O URL deve corresponder exatamente e não pode conter uma string de consulta.
Construído e mantido pela Invertase.