Mobile é diferente — por quê SecureStore?
Em apps mobile não existe localStorage nem cookies do browser. O Expo oferece o expo-secure-store, que armazena dados criptografados no Keychain (iOS) ou EncryptedSharedPreferences (Android) — o equivalente seguro para tokens JWT em dispositivos móveis.
O SDK @superdb/auth-js aceita qualquer storage adapter que implemente getItem, setItem e removeItem, então é direto plugar o SecureStore.
Expo Go vs build nativo: expo-secure-store funciona no Expo Go e em builds nativas. Para OAuth com deep linking, você precisa de uma build nativa (EAS Build ou npx expo run:ios/android).
Passo a passo
1Criar o projeto Expo
Use o template TypeScript blank do Expo. Ele configura tudo — Metro bundler, TypeScript, configuração base do app.json.
npx create-expo-app meu-app --template blank-typescript
cd meu-app
2Instalar dependências
Use npx expo install (não npm install) para as libs do Expo — ele garante versões compatíveis com o seu SDK.
npx expo install expo-secure-store expo-linking expo-web-browser
npm install @superdb/auth-js
3Configurar scheme para deep linking
Adicione um scheme no app.json. Ele é necessário para o OAuth redirecionar de volta ao app após login no browser.
{
"expo": {
"name": "Meu App",
"slug": "meu-app",
"scheme": "meuapp",
"ios": { "bundleIdentifier": "com.exemplo.meuapp" },
"android": { "package": "com.exemplo.meuapp" }
}
}
4Criar o cliente com SecureStore
Crie o adapter que conecta o expo-secure-store ao SDK. Note o detectSessionInUrl: false — importante para mobile, onde não há URL de callback do browser.
As variáveis de ambiente no Expo usam prefixo EXPO_PUBLIC_.
import { createClient } from '@superdb/auth-js'
import * as SecureStore from 'expo-secure-store'
// Adapter que traduz a interface do SecureStore para o SDK
const ExpoSecureStoreAdapter = {
getItem: (key: string) => SecureStore.getItemAsync(key),
setItem: (key: string, value: string) => SecureStore.setItemAsync(key, value),
removeItem: (key: string) => SecureStore.deleteItemAsync(key),
}
export const superdb = createClient(
process.env.EXPO_PUBLIC_SUPERDB_URL!,
process.env.EXPO_PUBLIC_SUPERDB_ANON_KEY!,
{
auth: {
storage: ExpoSecureStoreAdapter,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false, // ← obrigatório em mobile
}
}
)
EXPO_PUBLIC_SUPERDB_URL=https://auth.superdb.com.br
EXPO_PUBLIC_SUPERDB_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
5Tela de login nativa
Use componentes nativos do React Native — TextInput, TouchableOpacity. Sem HTML, sem browser.
import { useState } from 'react'
import { View, TextInput, TouchableOpacity, Text, Alert } from 'react-native'
import { superdb } from '../lib/superdb'
export default function LoginScreen() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
async function handleLogin() {
const { error } = await superdb.auth.signInWithPassword({ email, password })
if (error) Alert.alert('Erro', error.message)
}
async function handleSignUp() {
const { error } = await superdb.auth.signUp({ email, password })
if (error) Alert.alert('Erro', error.message)
else Alert.alert('Sucesso', 'Confirme seu email para continuar.')
}
return (
<View style={{ flex: 1, justifyContent: 'center', padding: 24 }}>
<TextInput
value={email} onChangeText={setEmail}
placeholder="Email" keyboardType="email-address"
autoCapitalize="none"
style={{ borderWidth: 1, borderColor: '#ccc', borderRadius: 8,
padding: 12, marginBottom: 12 }}
/>
<TextInput
value={password} onChangeText={setPassword}
placeholder="Senha" secureTextEntry
style={{ borderWidth: 1, borderColor: '#ccc', borderRadius: 8,
padding: 12, marginBottom: 16 }}
/>
<TouchableOpacity onPress={handleLogin}
style={{ backgroundColor: '#0a0a0a', padding: 14, borderRadius: 8, marginBottom: 8 }}>
<Text style={{ color: '#fff', textAlign: 'center', fontWeight: '600' }}>Entrar</Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleSignUp}>
<Text style={{ textAlign: 'center', color: '#666' }}>Criar conta</Text>
</TouchableOpacity>
</View>
)
}
6OAuth com deep linking (opcional)
Para OAuth (Google, GitHub), o SDK abre o browser nativo via expo-web-browser. Após o login, o OS redireciona de volta ao app via o scheme configurado no passo 3.
OAuth com deep linking requer build nativa. Não funciona no Expo Go. Use npx expo run:ios ou EAS Build.
Cadastre o redirect URL no dashboard SuperDB: app.superdb.com.br → Settings → Auth Providers → OAuth Redirect URLs → adicione meuapp://auth/callback.
import * as Linking from 'expo-linking'
import * as WebBrowser from 'expo-web-browser'
// Necessário para fechar o browser de volta ao app no Android
WebBrowser.maybeCompleteAuthSession()
async function handleGoogleLogin() {
const redirectUrl = Linking.createURL('auth/callback')
const { data, error } = await superdb.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: redirectUrl,
skipBrowserRedirect: true,
}
})
if (data?.url) {
const result = await WebBrowser.openAuthSessionAsync(data.url, redirectUrl)
if (result.type === 'success' && result.url) {
await superdb.auth.exchangeCodeForSession(result.url)
}
}
}
7Iniciar o app
Rode no simulador ou escaneie o QR code com o Expo Go no celular.
npx expo start
# Para build nativa (necessário pro OAuth):
npx expo run:ios # macOS com Xcode
npx expo run:android
Próximos passos
- Ativar MFA TOTP
- Configurar Row Level Security
- Referência completa do SDK
- iOS nativo (Swift/URLSession)