Add Sign in with Apple sorta

This commit is contained in:
2025-03-05 12:58:18 -06:00
parent 06471f688a
commit c62926b8f2
35 changed files with 1458 additions and 620 deletions

View File

@ -1,21 +1,43 @@
import { createClient } from "@supabase/supabase-js";
import AsyncStorage from "@react-native-async-storage/async-storage";
// lib/supabase.ts
import { createClient } from '@supabase/supabase-js';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as SecureStore from 'expo-secure-store';
import * as aesjs from 'aes-js';
import 'react-native-get-random-values';
import { Platform } from 'react-native';
// As Expo's SecureStore does not support values larger than 2048
// bytes, an AES-256 key is generated and stored in SecureStore, while
// it is used to encrypt/decrypt values stored in AsyncStorage.
// Create a web-compatible storage implementation
class WebStorage {
async getItem(key: string) {
// In SSR context, return null
if (typeof window === 'undefined') {
return null;
}
return localStorage.getItem(key);
}
async removeItem(key: string) {
if (typeof window === 'undefined') {
return;
}
localStorage.removeItem(key);
}
async setItem(key: string, value: string) {
if (typeof window === 'undefined') {
return;
}
localStorage.setItem(key, value);
}
}
// Original LargeSecureStore implementation for native platforms
class LargeSecureStore {
private async _encrypt(key: string, value: string) {
const encryptionKey = crypto.getRandomValues(new Uint8Array(256 / 8));
const cipher = new aesjs.ModeOfOperation.ctr(encryptionKey, new aesjs.Counter(1));
const encryptedBytes = cipher.encrypt(aesjs.utils.utf8.toBytes(value));
await SecureStore.setItemAsync(key, aesjs.utils.hex.fromBytes(encryptionKey));
return aesjs.utils.hex.fromBytes(encryptedBytes);
}
@ -24,17 +46,19 @@ class LargeSecureStore {
if (!encryptionKeyHex) {
return encryptionKeyHex;
}
const cipher = new aesjs.ModeOfOperation.ctr(aesjs.utils.hex.toBytes(encryptionKeyHex), new aesjs.Counter(1));
const cipher = new aesjs.ModeOfOperation.ctr(
aesjs.utils.hex.toBytes(encryptionKeyHex),
new aesjs.Counter(1),
);
const decryptedBytes = cipher.decrypt(aesjs.utils.hex.toBytes(value));
return aesjs.utils.utf8.fromBytes(decryptedBytes);
}
async getItem(key: string) {
const encrypted = await AsyncStorage.getItem(key);
if (!encrypted) { return encrypted; }
if (!encrypted) {
return encrypted;
}
return await this._decrypt(key, encrypted);
}
@ -45,17 +69,18 @@ class LargeSecureStore {
async setItem(key: string, value: string) {
const encrypted = await this._encrypt(key, value);
await AsyncStorage.setItem(key, encrypted);
}
}
// Choose the appropriate storage implementation based on platform
const storage = Platform.OS === 'web' ? new WebStorage() : new LargeSecureStore();
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL as string;
const supabaseAnonKey = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY as string;
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
auth: {
storage: new LargeSecureStore(),
storage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,