* docs(react-native): create the basic expo project * docs(react-native): cross-platform Apple social sign-in * docs(react-native): cross-platform Google social sign-in * docs(react-native): fix typos * docs(react-native): remove wrong entry in the `Connection` component * Correct typos * Prettier * Draft * Draft * docs(react-native): use kebab-case file naming convention in Expo guide - use kebab-case file naming convention in Expo guide - add trailing semicolon to align with the standard Expo template conventions * docs(react-native): use kebab-case file naming convention in Expo social auth example * docs(react-native): update the packages of the Expo social auth example * Fix * Draft * Changes * Correct log message --------- Co-authored-by: Chris Chinchilla <chris.ward@supabase.io> Co-authored-by: Chris Chinchilla <chris@chrischinchilla.com>
69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
import { supabase } from '@/lib/supabase';
|
|
import type { SignInWithIdTokenCredentials } from '@supabase/supabase-js';
|
|
import { useEffect, useState } from 'react';
|
|
import AppleSignin, { type AppleAuthResponse } from 'react-apple-signin-auth';
|
|
import { Platform } from 'react-native';
|
|
|
|
/**
|
|
* This is the Apple sign in button for the web.
|
|
*/
|
|
export default function AppleSignInButton() {
|
|
const [nonce, setNonce] = useState('');
|
|
const [sha256Nonce, setSha256Nonce] = useState('');
|
|
|
|
async function onAppleButtonSuccess(appleAuthRequestResponse: AppleAuthResponse) {
|
|
console.debug('Apple sign in successful:', { appleAuthRequestResponse })
|
|
if (appleAuthRequestResponse.authorization && appleAuthRequestResponse.authorization.id_token && appleAuthRequestResponse.authorization.code) {
|
|
const signInWithIdTokenCredentials: SignInWithIdTokenCredentials = {
|
|
provider: 'apple',
|
|
token: appleAuthRequestResponse.authorization.id_token,
|
|
nonce,
|
|
access_token: appleAuthRequestResponse.authorization.code,
|
|
}
|
|
|
|
const { data, error } = await supabase.auth.signInWithIdToken(signInWithIdTokenCredentials)
|
|
|
|
if (error) {
|
|
console.error('Error signing in with Apple:', error)
|
|
}
|
|
|
|
if (data) {
|
|
console.log('Apple sign in successful:', data)
|
|
}
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
function generateNonce(): string {
|
|
const array = new Uint32Array(1);
|
|
window.crypto.getRandomValues(array);
|
|
return array[0].toString();
|
|
};
|
|
|
|
async function generateSha256Nonce(nonce: string): Promise<string> {
|
|
const buffer = await window.crypto.subtle.digest('sha-256', new TextEncoder().encode(nonce));
|
|
const array = Array.from(new Uint8Array(buffer));
|
|
return array.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
}
|
|
|
|
let nonce = generateNonce();
|
|
setNonce(nonce);
|
|
|
|
generateSha256Nonce(nonce)
|
|
.then((sha256Nonce) => { setSha256Nonce(sha256Nonce) });
|
|
}, []);
|
|
|
|
if (Platform.OS !== 'web') { return <></> }
|
|
|
|
return <AppleSignin
|
|
authOptions={{
|
|
clientId: process.env.EXPO_PUBLIC_APPLE_AUTH_SERVICE_ID ?? '',
|
|
redirectURI: process.env.EXPO_PUBLIC_APPLE_AUTH_REDIRECT_URI ?? '',
|
|
scope: 'email name',
|
|
state: 'state',
|
|
nonce: sha256Nonce,
|
|
usePopup: true,
|
|
}}
|
|
onSuccess={onAppleButtonSuccess}
|
|
/>;
|
|
} |