Вы можете разрешить своим пользователям проходить аутентификацию в Firebase, используя их Apple ID, используя Firebase SDK для выполнения сквозного процесса входа в систему OAuth 2.0.
Прежде чем начать
Чтобы войти в систему с помощью Apple, сначала настройте «Вход через Apple» на сайте разработчика Apple, а затем включите Apple в качестве поставщика входа в систему для вашего проекта Firebase.
Присоединяйтесь к программе разработчиков Apple
Вход с Apple могут настроить только участники программы Apple Developer Program .
Настройте вход с помощью Apple
На сайте разработчика Apple выполните следующие действия:
Свяжите свой веб-сайт со своим приложением, как описано в первом разделе статьи «Настройка входа с помощью Apple для Интернета» . При появлении запроса зарегистрируйте следующий URL-адрес в качестве URL-адреса возврата:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
Вы можете получить идентификатор проекта Firebase на странице настроек консоли Firebase .
Когда вы закончите, запишите свой новый идентификатор службы, который вам понадобится в следующем разделе.
- Создайте вход с помощью закрытого ключа Apple . В следующем разделе вам понадобится новый закрытый ключ и идентификатор ключа.
Если вы используете какие-либо функции Firebase Authentication , которые отправляют электронные письма пользователям, включая вход по ссылке электронной почты, проверку адреса электронной почты, отзыв изменений учетной записи и другие, настройте службу частной ретрансляции электронной почты Apple и зарегистрируйте
noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com
(или ваш собственный домен шаблона электронной почты), чтобы Apple могла ретранслировать электронные письма, отправленные с помощью Firebase Authentication на анонимные адреса электронной почты Apple.
Включить Apple в качестве поставщика услуг входа
- Добавьте Firebase в свой проект .
- В консоли Firebase откройте раздел Auth . На вкладке «Метод входа » включите поставщика Apple . Укажите идентификатор службы, который вы создали в предыдущем разделе. Кроме того, в разделе конфигурации потока кода OAuth укажите свой Apple Team ID, а также закрытый ключ и идентификатор ключа, которые вы создали в предыдущем разделе.
Соблюдайте требования Apple к анонимным данным.
Вход с Apple дает пользователям возможность анонимизировать свои данные, включая адрес электронной почты, при входе в систему. Пользователи, выбравшие этот вариант, получают адреса электронной почты с доменом privaterelay.appleid.com
. Когда вы используете «Вход через Apple» в своем приложении, вы должны соблюдать все применимые политики или условия разработчиков Apple в отношении этих анонимных идентификаторов Apple ID.
Это включает в себя получение любого необходимого согласия пользователя, прежде чем вы свяжете любую личную информацию, непосредственно идентифицирующую вас, с анонимным Apple ID. При использовании аутентификации Firebase это может включать в себя следующие действия:
- Свяжите адрес электронной почты с анонимным Apple ID или наоборот.
- Привяжите номер телефона к анонимному Apple ID или наоборот.
- Свяжите неанонимные учетные данные социальных сетей (Facebook, Google и т. д.) с анонимным Apple ID или наоборот.
Приведенный выше список не является исчерпывающим. Ознакомьтесь с Лицензионным соглашением программы разработчиков Apple в разделе «Членство» вашей учетной записи разработчика, чтобы убедиться, что ваше приложение соответствует требованиям Apple.
Управляйте процессом входа в систему с помощью Firebase SDK
Если вы создаете веб-приложение, самый простой способ аутентификации ваших пользователей в Firebase с использованием их учетных записей Apple — это обработка всего процесса входа в систему с помощью Firebase JavaScript SDK.
Чтобы обработать процесс входа с помощью Firebase JavaScript SDK, выполните следующие действия:
Создайте экземпляр OAuthProvider, используя соответствующий идентификатор поставщика apple.com .
Web
import { OAuthProvider } from "firebase/auth"; const provider = new OAuthProvider('apple.com');
Web
var provider = new firebase.auth.OAuthProvider('apple.com');
Необязательно: укажите дополнительные области OAuth 2.0 помимо области по умолчанию, которую вы хотите запросить у поставщика аутентификации.
Web
provider.addScope('email'); provider.addScope('name');
Web
provider.addScope('email'); provider.addScope('name');
По умолчанию, когда включена одна учетная запись на адрес электронной почты , Firebase запрашивает области электронной почты и имени. Если вы измените этот параметр на «Несколько учетных записей на один адрес электронной почты» , Firebase не запрашивает у Apple никаких областей, если вы их не укажете.
Необязательно: если вы хотите, чтобы экран входа в систему Apple отображался на языке, отличном от английского, установите параметр
locale
. Список поддерживаемых языков см. в документации «Вход с помощью Apple» .Web
provider.setCustomParameters({ // Localize the Apple authentication screen in French. locale: 'fr' });
Web
provider.setCustomParameters({ // Localize the Apple authentication screen in French. locale: 'fr' });
Аутентификация в Firebase с использованием объекта провайдера OAuth. Вы можете предложить своим пользователям войти в систему с помощью своих учетных записей Apple, открыв всплывающее окно или перенаправив на страницу входа. Метод перенаправления предпочтителен на мобильных устройствах.
Чтобы войти в систему с помощью всплывающего окна, вызовите
signInWithPopup()
:Web
import { getAuth, signInWithPopup, OAuthProvider } from "firebase/auth"; const auth = getAuth(); signInWithPopup(auth, provider) .then((result) => { // The signed-in user info. const user = result.user; // Apple credential const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; const idToken = credential.idToken; // IdP data available using getAdditionalUserInfo(result) // ... }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
Web
firebase .auth() .signInWithPopup(provider) .then((result) => { /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // The signed-in user info. var user = result.user; // You can also get the Apple OAuth Access and ID Tokens. var accessToken = credential.accessToken; var idToken = credential.idToken; // IdP data available using getAdditionalUserInfo(result) // ... }) .catch((error) => { // Handle Errors here. var errorCode = error.code; var errorMessage = error.message; // The email of the user's account used. var email = error.email; // The firebase.auth.AuthCredential type that was used. var credential = error.credential; // ... });
Чтобы войти в систему путем перенаправления на страницу входа, вызовите
signInWithRedirect()
:
Следуйте рекомендациям при использовании
signInWithRedirect
,linkWithRedirect
илиreauthenticateWithRedirect
.Web
import { getAuth, signInWithRedirect } from "firebase/auth"; const auth = getAuth(); signInWithRedirect(auth, provider);
Web
firebase.auth().signInWithRedirect(provider);
После того как пользователь завершит вход и вернется на страницу, вы можете получить результат входа, вызвав
getRedirectResult()
:Web
import { getAuth, getRedirectResult, OAuthProvider } from "firebase/auth"; // Result from Redirect auth flow. const auth = getAuth(); getRedirectResult(auth) .then((result) => { const credential = OAuthProvider.credentialFromResult(result); if (credential) { // You can also get the Apple OAuth Access and ID Tokens. const accessToken = credential.accessToken; const idToken = credential.idToken; } // The signed-in user info. const user = result.user; }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
Web
// Result from Redirect auth flow. firebase .auth() .getRedirectResult() .then((result) => { if (result.credential) { /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // You can get the Apple OAuth Access and ID Tokens. var accessToken = credential.accessToken; var idToken = credential.idToken; // IdP data available in result.additionalUserInfo.profile. // ... } // The signed-in user info. var user = result.user; }) .catch((error) => { // Handle Errors here. var errorCode = error.code; var errorMessage = error.message; // The email of the user's account used. var email = error.email; // The firebase.auth.AuthCredential type that was used. var credential = error.credential; // ... });
Здесь также можно ловить и обрабатывать ошибки. Список кодов ошибок см. в справочнике по API .
В отличие от других провайдеров, поддерживающих Firebase Auth, Apple не предоставляет URL-адрес фотографии.
Кроме того, когда пользователь решает не делиться своей электронной почтой с приложением, Apple предоставляет этому пользователю уникальный адрес электронной почты (в форме
xyz@privaterelay.appleid.com
), который она использует совместно с вашим приложением. Если вы настроили службу частной ретрансляции электронной почты, Apple перенаправляет электронные письма, отправленные на анонимный адрес, на реальный адрес электронной почты пользователя.Apple передает информацию о пользователе, такую как отображаемое имя, приложениям только при первом входе пользователя в систему. Обычно Firebase сохраняет отображаемое имя при первом входе пользователя в систему Apple, которое вы можете получить с помощью
firebase.auth().currentUser.displayName
. Однако если вы ранее использовали Apple для входа пользователя в приложение без использования Firebase, Apple не предоставит Firebase отображаемое имя пользователя.
Повторная аутентификация и привязка учетной записи
Тот же шаблон можно использовать с reauthenticateWithPopup()
и reauthenticateWithRedirect()
, которые можно использовать для получения новых учетных данных для конфиденциальных операций, требующих недавнего входа в систему:
Web
import { getAuth, reauthenticateWithPopup, OAuthProvider } from "firebase/auth"; // Result from Redirect auth flow. const auth = getAuth(); const provider = new OAuthProvider('apple.com'); reauthenticateWithPopup(auth.currentUser, provider) .then((result) => { // User is re-authenticated with fresh tokens minted and can perform // sensitive operations like account deletion, or updating their email // address or password. // The signed-in user info. const user = result.user; // You can also get the Apple OAuth Access and ID Tokens. const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; const idToken = credential.idToken; // ... }) .catch((error) => { // Handle Errors here. const errorCode = error.code; const errorMessage = error.message; // The email of the user's account used. const email = error.customData.email; // The credential that was used. const credential = OAuthProvider.credentialFromError(error); // ... });
Web
const provider = new firebase.auth.OAuthProvider('apple.com'); firebase .auth() .currentUser .reauthenticateWithPopup(provider) .then((result) => { // User is re-authenticated with fresh tokens minted and can perform // sensitive operations like account deletion, or updating their email // address or password. /** @type {firebase.auth.OAuthCredential} */ var credential = result.credential; // The signed-in user info. var user = result.user; // You can also get the Apple OAuth Access and ID Tokens. var accessToken = credential.accessToken; var idToken = credential.idToken; // IdP data available in result.additionalUserInfo.profile. // ... }) .catch((error) => { // Handle Errors here. var errorCode = error.code; var errorMessage = error.message; // The email of the user's account used. var email = error.email; // The firebase.auth.AuthCredential type that was used. var credential = error.credential; // ... });
И вы можете использовать linkWithPopup()
и linkWithRedirect()
, чтобы связать разных поставщиков удостоверений с существующими учетными записями.
Обратите внимание: Apple требует, чтобы вы получили явное согласие пользователей, прежде чем связывать их учетные записи Apple с другими данными.
Например, чтобы связать учетную запись Facebook с текущей учетной записью Firebase, используйте токен доступа, полученный при входе пользователя в Facebook:
Web
import { getAuth, linkWithPopup, FacebookAuthProvider } from "firebase/auth"; const auth = getAuth(); const provider = new FacebookAuthProvider(); provider.addScope('user_birthday'); // Assuming the current user is an Apple user linking a Facebook provider. linkWithPopup(auth.currentUser, provider) .then((result) => { // Facebook credential is linked to the current Apple user. // ... // The user can now sign in to the same account // with either Apple or Facebook. }) .catch((error) => { // Handle error. });
Web
const provider = new firebase.auth.FacebookAuthProvider(); provider.addScope('user_birthday'); // Assuming the current user is an Apple user linking a Facebook provider. firebase.auth().currentUser.linkWithPopup(provider) .then((result) => { // Facebook credential is linked to the current Apple user. // Facebook additional data available in result.additionalUserInfo.profile, // Additional Facebook OAuth access token can also be retrieved. // result.credential.accessToken // The user can now sign in to the same account // with either Apple or Facebook. }) .catch((error) => { // Handle error. });
Аутентификация с помощью Firebase в расширении Chrome
Если вы создаете приложение-расширение Chrome, см. руководство по Offscreen Documents .
Обратите внимание, что вам все равно необходимо подтвердить личный домен в Apple, аналогично домену firebaseapp.com по умолчанию:
http://auth.custom.example.com/.well-known/apple-developer-domain-association.txt
Отзыв токена
Apple требует, чтобы приложения, поддерживающие создание учетной записи, позволяли пользователям инициировать удаление своей учетной записи в приложении, как описано в Руководстве по проверке App Store.
Чтобы удовлетворить этому требованию, выполните следующие шаги:
Убедитесь, что вы заполнили раздел конфигурации идентификатора службы и потока кода OAuth в конфигурации поставщика «Вход с Apple», как описано в разделе «Настройка входа с Apple» .
Поскольку Firebase не хранит токены пользователей, когда пользователи создаются с помощью функции «Вход через Apple», вы должны попросить пользователя войти в систему еще раз, прежде чем отзывать его токен и удалять учетную запись.
Затем получите токен доступа Apple OAuth из
OAuthCredential
и используйте его для вызоваrevokeAccessToken(auth, token)
для отзыва токена доступа Apple OAuth.const provider = new OAuthProvider('apple.com'); provider.addScope('email'); provider.addScope('name'); const auth = getAuth(); signInWithPopup(auth, provider).then(result => { // Get the Apple OAuth access token. const credential = OAuthProvider.credentialFromResult(result); const accessToken = credential.accessToken; // Revoke the Apple OAuth access token. revokeAccessToken(auth, accessToken) .then(() => { // Token revoked. // Delete the user account. // ... }) .catch(error => { // An error happened. // ... }); });
Наконец, удалите учетную запись пользователя (и все связанные с ней данные).
Дополнительно: аутентификация с помощью Firebase в Node.js
Чтобы пройти аутентификацию с помощью Firebase в приложении Node.js:
Войдите в систему пользователя, используя его учетную запись Apple, и получите токен Apple ID пользователя. Вы можете сделать это несколькими способами. Например, если ваше приложение Node.js имеет интерфейс браузера:
На своем сервере сгенерируйте случайную строку («nonce») и вычислите ее хэш SHA256. Nonce — это одноразовое значение, которое вы используете для проверки одного обратного пути между вашим сервером и серверами аутентификации Apple.
Web
const crypto = require("crypto"); const string_decoder = require("string_decoder"); // Generate a new random string for each sign-in const generateNonce = (length) => { const decoder = new string_decoder.StringDecoder("ascii"); const buf = Buffer.alloc(length); let nonce = ""; while (nonce.length < length) { crypto.randomFillSync(buf); nonce = decoder.write(buf); } return nonce.slice(0, length); }; const unhashedNonce = generateNonce(10); // SHA256-hashed nonce in hex const hashedNonceHex = crypto.createHash('sha256') .update(unhashedNonce).digest().toString('hex');
Web
const crypto = require("crypto"); const string_decoder = require("string_decoder"); // Generate a new random string for each sign-in const generateNonce = function(length) { const decoder = new string_decoder.StringDecoder("ascii"); const buf = Buffer.alloc(length); var nonce = ""; while (nonce.length < length) { crypto.randomFillSync(buf); nonce = decoder.write(buf); } return nonce.slice(0, length); }; const unhashedNonce = generateNonce(10); // SHA256-hashed nonce in hex const hashedNonceHex = crypto.createHash('sha256') .update(unhashedNonce).digest().toString('hex');
На странице входа укажите хешированный одноразовый номер в конфигурации «Вход через Apple»:
<script src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script> <div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div> <script> AppleID.auth.init({ clientId: YOUR_APPLE_CLIENT_ID, scope: 'name email', redirectURI: URL_TO_YOUR_REDIRECT_HANDLER, // See the next step. state: '[STATE]', // Optional value that Apple will send back to you // so you can return users to the same context after // they sign in. nonce: HASHED_NONCE // The hashed nonce you generated in the previous step. }); </script>
Получите токен Apple ID из ответа POSTed на стороне сервера:
app.post('/redirect', (req, res) => { const savedState = req.cookies.__session; const code = req.body.code; const state = req.body.state; const appleIdToken = req.body.id_token; if (savedState !== state || !code) { res.status(403).send('403: Permission denied'); } else { // Sign in with Firebase using appleIdToken. (See next step). } });
Также см. Настройка веб-страницы для входа в систему с помощью Apple .
Получив токен Apple ID пользователя, используйте его для создания объекта Credential, а затем войдите в систему пользователя с учетными данными:
Web
import { getAuth, signInWithCredential, OAuthProvider } from "firebase/auth"; const auth = getAuth(); // Build Firebase credential with the Apple ID token. const provider = new OAuthProvider('apple.com'); const authCredential = provider.credential({ idToken: appleIdToken, rawNonce: unhashedNonce, }); // Sign in with credential form the Apple user. signInWithCredential(auth, authCredential) .then((result) => { // User signed in. }) .catch((error) => { // An error occurred. If error.code == 'auth/missing-or-invalid-nonce', // make sure you're sending the SHA256-hashed nonce as a hex string // with your request to Apple. console.log(error); });
Web
// Build Firebase credential with the Apple ID token. const provider = new firebase.auth.OAuthProvider('apple.com'); const authCredential = provider.credential({ idToken: appleIdToken, rawNonce: unhashedNonce, }); // Sign in with credential form the Apple user. firebase.auth().signInWithCredential(authCredential) .then((result) => { // User signed in. }) .catch((error) => { // An error occurred. If error.code == 'auth/missing-or-invalid-nonce', // make sure you're sending the SHA256-hashed nonce as a hex string // with your request to Apple. console.log(error); });
Следующие шаги
После того, как пользователь входит в систему в первый раз, создается новая учетная запись пользователя, которая связывается с учетными данными (то есть именем пользователя и паролем, номером телефона или информацией поставщика аутентификации), с которыми пользователь вошел в систему. Эта новая учетная запись хранится как часть вашего проекта Firebase и может использоваться для идентификации пользователя в каждом приложении вашего проекта, независимо от того, как пользователь входит в систему.
В ваших приложениях рекомендуемый способ узнать статус аутентификации вашего пользователя — установить наблюдателя на объекте
Auth
. Затем вы можете получить базовую информацию профиля пользователя из объектаUser
. См. Управление пользователями .В правилах безопасности базы данных реального времени и Cloud Storage Firebase Realtime Database вы можете получить уникальный идентификатор пользователя, вошедшего в систему, из переменной
auth
и использовать его для управления тем, к каким данным пользователь может получить доступ.
Вы можете разрешить пользователям входить в ваше приложение с использованием нескольких поставщиков аутентификации, связав учетные данные поставщика аутентификации с существующей учетной записью пользователя.
Чтобы выйти из системы, вызовите signOut
:
Web
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });