>_ DevTrendspt

Idioma

Início

Linguagens

Seções

Frontend Backend Mobile DevOps AI / ML GameDev Blockchain Embarcados Segurança
JavaScript

Como Adicionar Login com Apple ao React Native Sem Enlouquecer

Se você já implantou um aplicativo móvel com login do Google ou redes sociais na App Store, provavelmente já encontrou a regra rígida dos revisores: se você adicionar login de terceiros, também deve incluir o Login com Apple. Caso contrário, a rejeição vem mais rápido do que um build de release consegue terminar de compilar.

A tarefa parece simples à primeira vista. Mas assim que você começa a se aprofundar em chamadas nativas, peculiaridades do simulador e excentricidades da API da Apple, uma série de armadilhas aparecem. A equipe do Invertase (as mesmas pessoas por trás do React Native Firebase) criou uma biblioteca chamada react-native-apple-authentication que lida com isso tanto para iOS quanto para Android.

apple-auth

O que está sob o capô e por que você precisa disso

A biblioteca fornece acesso completo ao mecanismo de autenticação da Apple. Funciona no React Native vanilla a partir da versão 0.60, é compatível com Expo (via prebuild e configuração de entitlements em app.json), suporta macOS e pode até autenticar usuários Android via fluxo de navegador.

O melhor é ter as definições TypeScript prontas para uso e o componente de botão nativo já preparado AppleButton. O design do botão é estritamente regulamentado pelas diretrizes da Apple. Se você desenhá-lo sozinho, os revisores vão rejeitar seu aplicativo com prazer. Aqui, os estilos e a localização são extraídos diretamente do sistema nativo.

Como funciona o fluxo básico no iOS

A instalação é padrão: instale o pacote via yarn ou npm, depois execute pod install na pasta ios. O módulo suporta autolinking, então você não precisará mexer no AppDelegate.

Para o botão e a lógica de login, você só precisa de alguns imports:

import React from 'react';
import { View } from 'react-native';
import { AppleButton, appleAuth } from '@invertase/react-native-apple-authentication';

export function LoginScreen() {
  async function handleAppleLogin() {
    // Запускаем нативный запрос авторизации
    const authResponse = await appleAuth.performRequest({
      requestedOperation: appleAuth.Operation.LOGIN,
      // Порядок скоупов имеет значение
      requestedScopes: [appleAuth.Scope.FULL_NAME, appleAuth.Scope.EMAIL],
    });

    // Проверяем статус пользователя
    const credentialState = await appleAuth.getCredentialStateForUser(authResponse.user);

    if (credentialState === appleAuth.State.AUTHORIZED) {
      // Пользователь подтвержден, отправляем токены на бэкенд
      console.log('User ID:', authResponse.user);
      console.log('Identity Token:', authResponse.identityToken);
    }
  }

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <AppleButton
        buttonStyle={AppleButton.Style.BLACK}
        buttonType={AppleButton.Type.SIGN_IN}
        style={{ width: 200, height: 45 }}
        onPress={handleAppleLogin}
      />
    </View>
  );
}

Armadilhas nas quais todos os iniciantes tropeçam

A autorização da Apple tem peculiaridades não óbvias que vale a pena conhecer antes de se ver depurando até as 3 da manhã.

Nome e email só aparecem uma vez

A Apple é obcecada por privacidade. No primeiro login, o usuário pode escolher ocultar seu email real ou compartilhá-lo. Os dados do perfil (fullName fullName e email email) são retornados pelo framework nativo exatamente uma vez — durante a primeira autorização bem-sucedida.

Em chamadas subsequentes, esses campos voltam vazios (null null). Se você não salvou o nome e email no seu banco de dados imediatamente, não pode recuperá-los novamente através da API do cliente.

Para redefinir o estado de teste em um iPhone e receber o perfil novamente, você precisa ir manualmente para as configurações do sistema: Ajustes → [Seu Nome] → Senha e Segurança → Logins do Apple ID Настройки > Apple ID > Пароль и безопасность > Приложения, использующие Apple ID, remover seu aplicativo de teste lá e fazer login novamente.

A propósito, o repositório do projeto observa especificamente um bug na própria API da Apple: os scopes devem ser passados exatamente na ordem [FULL_NAME, EMAIL]. Se você trocar a ordem, o nome pode ser perdido já na primeira requisição.

Simuladores e erro 1000

O método currentUser getCredentialStateForUser verifica a autenticidade do dispositivo. Nos simuladores iOS, ele falha regularmente com o erro 1000 com.apple.AuthenticationServices.AuthorizationError error 1000. Você só pode testar completamente a cadeia de autorização em um dispositivo físico.

Se o simulador estiver completamente travado nesse erro, os desenvolvedores recomendam ir ao site de gerenciamento de ID Apple, encontrar a lista de dispositivos associados e remover o simulador da sua conta.

show-devices

remove-from-manager

Logout é uma ilusão

Os enums do módulo incluem uma operação de logout appleAuth.Operation.LOGOUT, mas na prática o SDK nativo iOS não faz nada com ela. A Apple não fornece uma forma de forçar logout do sistema no nível do dispositivo. O logout do lado do cliente significa apenas apagar sua sessão local, tokens salvos e limpar o estado do aplicativo.

Revogando acesso

Os usuários podem a qualquer momento ir para os ajustes do iOS e revogar a permissão do seu aplicativo para fazer login. Para reagir a tempo e devolver o usuário à tela de login, a biblioteca fornece um listener de eventos:

useEffect(() => {
  const unsubscribe = appleAuth.onCredentialRevoked(async () => {
    // Токены больше не валидны, сбрасываем локальное состояние
    console.warn('Доступ отозван пользователем в настройках Apple ID');
  });

  return () => unsubscribe();
}, []);

E o Android

Muitos ficam surpresos, mas você também pode permitir que usuários Android façam login com Apple ID. A mecânica é diferente lá: em vez de um framework nativo, uma janela protegida do navegador abre via OAuth 2.0 Web Flow.

A biblioteca trata da rotina através do módulo ASWebAuthenticationSession appleAuthAndroid:

import { appleAuthAndroid } from '@invertase/react-native-apple-authentication';
import 'react-native-get-random-values';
import { v4 as uuid } from 'uuid';

async function handleAndroidAppleLogin() {
  const rawNonce = uuid();
  const state = uuid();

  appleAuthAndroid.configure({
    clientId: 'com.example.client-android', // Service ID из консоли Apple Developer
    redirectUri: 'https://example.com/auth/callback',
    responseType: appleAuthAndroid.ResponseType.ALL,
    scope: appleAuthAndroid.Scope.ALL,
    nonce: rawNonce,
    state,
  });

  const response = await appleAuthAndroid.signIn();
  // Отправляем response.code и response.id_token на сервер
}

Para Android, você precisará configurar um Service ID no Apple Developer Console e especificar uma Redirect URL. A regra principal: o link de redirecionamento deve corresponder caractere por caractere ao que está inserido no console do desenvolvedor — sem parâmetros de query permitidos.

Validação no servidor

Nunca confie no nonce user ID do lado do cliente cegamente. O cliente recebe identityToken identityToken (um JWT assinado). No servidor, você decodifica, verifica a assinatura com as chaves públicas da Apple e verifica o nonce nonce.

O módulo calcula automaticamente o hash SHA256 do nonce passado nonce antes de enviá-lo à Apple (similar ao que o Firebase Auth faz). Tenha isso em mente no backend: você precisa comparar o valor com hash.

Se seu objetivo é satisfazer rapidamente os requisitos de revisão da App Store ou oferecer aos usuários um login conveniente com um toque via Face ID, a biblioteca da Invertase é a escolha mais confiável no ecossistema React Native. Ela evita que você escreva sua própria bridge nativa em Swift/Objective-C, trata elegantemente o estilo do botão e é consistentemente atualizada pelos mantenedores. Instale, configure os certificados no Apple Developer Console, configure o handler — e seu release está pronto para enviar.

Projetos relacionados