Хорошо типизированная библиотека React Native, обеспечивающая поддержку Apple Authentication на iOS и Android, включая поддержку всех вариантов AppleButton
.
Библиотека @invertase/react-native-apple-authentication
не будет работать, если вы не обеспечите следующее:
Вы используете React Native версии 0.60
или выше.
(Только для iOS) На вашем компьютере установлена собственная среда разработки iOS (будет работать только на Mac). Если нет, для начала работы следуйте официальной документации React Native: Документация по началу работы с React Native.
(Только для iOS) Вы используете Xcode версии 11
или выше. Это позволит вам разрабатывать приложения с использованием iOS версии 13
и выше, когда станут доступны API для входа в систему с помощью Apple.
Если вы уверены, что выполнили все вышеперечисленное, следуйте нашему руководству по начальной настройке среды разработки.
В версии 2 добавлена поддержка Android и внесено несколько кардинальных изменений в способах доступа к методам. Пожалуйста, ознакомьтесь с Руководством по миграции.
yarn add @invertase/react-native-apple-authentication
(cd ios && pod install)
Вам не придется вручную связывать этот модуль, поскольку он поддерживает автоматическое связывание React Native.
Чтобы включить в своем приложении возможность входа с помощью Apple, установите для свойства ios.usesAppleSignIn значение true в конфигурации приложения вашего проекта:
{
"expo" : {
"ios" : {
"usesAppleSignIn" : true
}
}
}
Вам также может потребоваться запустить npx expo prebuild
.
Ниже приведены простые шаги, которые помогут вам приступить к работе. Реализация различается в iOS и Android, поэтому если у вас возникли проблемы, обязательно просмотрите документацию. Пожалуйста, пропустите и перейдите к полным примерам кода, указанным ниже, если вы предпочитаете увидеть более полную реализацию:
React Native Firebase
; см. наше руководство по Firebase Импортируйте модуль appleAuth
(документация API) и экспортированный элемент AppleButton
(документация API) из библиотеки @invertase/react-native-apple-authentication
. Настройте обработчик событий ( onPress
), чтобы запустить запрос аутентификации.
// 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
}
}
Настройте прослушиватель событий на случай отзыва учетных данных пользователя.
// 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 >
) ;
}
Существует операция appleAuth.Operation.LOGOUT
, однако она не работает должным образом и даже не используется Apple в своем примере кода. См. этот выпуск для получения дополнительной информации.
Поэтому рекомендуется при выходе из системы просто удалить все данные пользователя, собранные во время appleAuth.Operation.LOGIN
.
Обязательно правильно настройте свою учетную запись разработчика Apple, чтобы обеспечить правильную аутентификацию на Android. Вы можете ознакомиться с нашим руководством для получения дополнительной информации.
// 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
}
Эта библиотека работает на MacOS 10.15+ при использовании совместно с response-native-macos.
yarn add react-apple-signin-auth
в свой веб-проект. 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) и appleAuthAndroid.configure
(Android), автоматически хешируется по 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 ,
} ) ;
Вся документация по API создается typedoc и доступна в папке typedocs
.
Почему full name
и email
возвращают null
?
full name
и email
только при первом входе в систему, при последующем входе она вернет null
, поэтому вам необходимо сохранить эти данные. 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
, коснитесь своего приложения и коснитесь Stop Using Apple ID
. Теперь вы можете снова войти в систему и получите full name
и адрес электронной почты.email
, проверив id_token
возвращенный Apple при проверке пользователя.Как изменить язык кнопок? (iOS)
< key >CFBundleDevelopmentRegion</ key >
< string >en</ string >
< key >CFBundleAllowMixedLocalizations</ key >
< string >true</ string >
Как получить письмо после первого входа в систему?
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.)
Убедитесь, что настройки подключения выполнены правильно. Установку можно найти здесь: Первоначальная настройка.
Если вы используете функцию getCredentialStateForUser
в симуляторе, эта ошибка будет вызываться всегда, поскольку эта функция проверяет подлинность устройства.
Вы должны протестировать свой код на реальном устройстве.
Если вы используете симулятор, перейдите в «Управление учетной записью Apple».
Найдите «Устройства», выберите «Симулятор» и нажмите «Удалить из учетной записи».
Все должно работать нормально.
"invalid_client" in Android webview
Обязательно прочтите документацию по настройке служб Android.
clientId
который вы передали в appleAuthAndroid.configure
не соответствует идентификатору службы, который вы установили в консоли разработчика Apple.
Ваш идентификатор службы привязан к неправильному основному идентификатору приложения и поэтому использует неверный ключ входа с помощью Apple.
redirectUri
который вы передали в appleAuthAndroid.configure
не соответствует ни одному из возвращаемых URL-адресов или доменов/поддоменов, которые вы добавили в консоль разработчика Apple. URL-адрес должен точно совпадать и не может содержать строку запроса.
Создан и поддерживается Invertase.