Explore
Auth
Instant comes with support for auth. We currently offer magic codes and Google OAuth. If you want to build your own flow, you can use the Admin SDK.
Magic Codes
Instant supports a "magic-code" flow for auth. Users provide their email, we send them a login code on your behalf, and they authenticate with your app. Here's how you can do it with react.
'use client'
import React, { useState } from 'react'
import { init } from '@instantdb/react'
const APP_ID = 'REPLACE ME'
const db = init({ appId: APP_ID })
function App() {
const { isLoading, user, error } = db.useAuth()
if (isLoading) {
return <div>Loading...</div>
}
if (error) {
return <div>Uh oh! {error.message}</div>
}
if (user) {
return <h1>Hello {user.email}!</h1>
}
return <Login />
}
function Login() {
const [sentEmail, setSentEmail] = useState('')
return (
<div style={authStyles.container}>
{!sentEmail ? (
<Email setSentEmail={setSentEmail} />
) : (
<MagicCode sentEmail={sentEmail} />
)}
</div>
)
}
function Email({ setSentEmail }) {
const [email, setEmail] = useState('')
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (!email) return
setSentEmail(email)
db.auth.sendMagicCode({ email }).catch((err) => {
alert('Uh oh :' + err.body?.message)
setSentEmail('')
})
}
return (
<form onSubmit={handleSubmit} style={authStyles.form}>
<h2 style={{ color: '#333', marginBottom: '20px' }}>Let's log you in!</h2>
<div>
<input
style={authStyles.input}
placeholder="Enter your email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<button type="submit" style={authStyles.button}>
Send Code
</button>
</div>
</form>
)
}
function MagicCode({ sentEmail }) {
const [code, setCode] = useState('')
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
db.auth.signInWithMagicCode({ email: sentEmail, code }).catch((err) => {
alert('Uh oh :' + err.body?.message)
setCode('')
})
}
return (
<form onSubmit={handleSubmit} style={authStyles.form}>
<h2 style={{ color: '#333', marginBottom: '20px' }}>
Okay, we sent you an email! What was the code?
</h2>
<div>
<input
style={authStyles.input}
type="text"
placeholder="123456..."
value={code}
onChange={(e) => setCode(e.target.value)}
/>
</div>
<button type="submit" style={authStyles.button}>
Verify
</button>
</form>
)
}
const authStyles: Record<string, React.CSSProperties> = {
container: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
},
form: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
fontFamily: 'Arial, sans-serif',
},
input: {
padding: '10px',
marginBottom: '15px',
border: '1px solid #ddd',
borderRadius: '5px',
width: '300px',
},
button: {
padding: '10px 20px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
},
}
export default App
This creates a Login
component to handle our auth flow. Of note is auth.sendMagicCode
and auth.signInWithMagicCode
.
On successful validation, Instant's backend will return a user object with a refresh token. The client SDK will then restart the websocket connection with Instant's sync layer and provide the refresh token.
When doing useQuery
or transact
, the refresh token will be used to hydrate auth
on the backend during permission checks.
On the client, useAuth
will set isLoading
to false
and populate user
-- huzzah!
useAuth
function App() {
const { isLoading, user, error } = db.useAuth()
if (isLoading) {
return <div>Loading...</div>
}
if (error) {
return <div>Uh oh! {error.message}</div>
}
if (user) {
return <Main />
}
return <Login />
}
Use useAuth
to fetch the current user. Here we guard against loading our Main
component until a user is logged in
auth.sendMagicCode
db.auth.sendMagicCode({ email }).catch((err) => {
alert('Uh oh :' + err.body?.message)
setState({ ...state, sentEmail: '' })
})
Use auth.sendMagicCode
to create a magic code on instant's backend and email a login code
auth.signInWithMagicCode
db.auth.signInWithMagicCode({ email: sentEmail, code }).catch((err) => {
alert('Uh oh :' + err.body?.message)
setState({ ...state, code: '' })
})
Use auth.signInWithMagicCode
to validate codes with instant's backend.
auth.signOut
db.auth.signOut()
Use auth.signOut
to sign out users. This will restart the websocket connection and clear out the current user refresh token.
Log in with Google
Instant supports logging in your users with their Google account. We support flows for Web and React Native. Follow the steps below to get started.
Step 1: Create an OAuth client for Google
Go to the Google Console.
Click "+ CREATE CREDENTIALS"
If you haven't already, configure your OAuth consent screen for External users. Once this is done, click "+ CREATE CREDENTIALS" again.
Select "OAuth client ID"
Select "Web application" as the application type.
Add https://api.instantdb.com/runtime/oauth/callback
as an Authorized redirect URI.
Step 2: Register your OAuth client with Instant
Go to the Instant dashboard and select the Auth
tab for your app.
Register a Google client and enter the client id and client secret from the OAuth client that you created.
Step 3: Register your website with Instant
In the Auth
tab, add the url of the websites where you are using Instant to the Redirect Origins.
If you're creating a React Native app, add your app scheme as an "App scheme" type origin. Add exp://
if you're using expo in development.
The next sections will show you how to use your configured OAuth client with Instant.
Native button for Web
You can use Google's Sign in Button with Instant. You'll use db.auth.SignInWithIdToken
to authenticate your user. The benefit of using Google's button is that you can display your app's name in the consent screen.
First, make sure that your website is in the list of "Authorized JavaScript origins" for your Google client on the Google console.
If you're testing from localhost, add both http://localhost
and http://localhost:3000
on the Google console, replacing 3000
with the port you use.
If you're using React, the easiest way to include the signin button is through the @react-oauth/google
package.
npm install @react-oauth/google
Include the button and use db.auth.signInWithIdToken
to complete sign in:
import { GoogleOAuthProvider, GoogleLogin } from '@react-oauth/google'
// e.g. 89602129-cuf0j.apps.googleusercontent.com
const GOOGLE_CLIENT_ID = 'YOUR_GOOGLE_CLIENT_ID'
function LoginButton() {
const [nonce] = useState(crypto.randomUUID())
return (
<GoogleOAuthProvider clientId={GOOGLE_CLIENT_ID}>
<GoogleLogin
nonce={nonce}
onError={() => alert('Login failed')}
onSuccess={({ credential }) => {
db.auth
.signInWithIdToken({
// Use the name you created when you registered the client
// on the Instant dashboad
clientName: 'google-web',
idToken: credential,
// Make sure this is the same nonce you passed as a prop
// to the GoogleLogin button
nonce,
})
.catch((err) => {
alert('Uh oh: ' + err.body?.message)
})
}}
/>
</GoogleOAuthProvider>
)
}
If you're not using React or prefer to embed the button yourself, refer to Google's docs on how to create the button and load their client library. When creating your button, make sure to set the data-ux_mode="popup"
. Your data-callback
function should look like:
async function handleSignInWithGoogle(response) {
await db.auth.signInWithIdToken({
// Use the name you created when you registered the client
// on the Instant dashboad
clientName: 'google-web',
idToken: response.credential,
// make sure this is the same nonce you set in data-nonce
nonce: 'YOUR_NONCE',
})
}
Redirect flow for Web
If you don't want to use the google styled buttons, you can use the redirect flow instead.
Simply create an authorization URL via db.auth.createAuthorizationURL
const url = db.auth.createAuthorizationURL({
// The name of the client you chose when you created it on the
// Instant dashboard
clientName: 'google-web',
redirectURL: window.location.href,
})
And then use the url to create a link:
<a href={url}>Log in with Google</a>
When your users clicks on the link, they'll be redirected to Google to start the OAuth flow and then back to your site.
Instant will automatically log them in to your app when they are redirected.
You can also use this to create a button:
Webview flow on React Native
Instant comes with support for Expo's AuthSession library. If you haven't already, follow the AuthSession installation instructions from the Expo docs.
Next, add the following dependencies:
npx expo install expo-auth-session expo-crypto
Update your app.json with your scheme:
{
"expo": {
"scheme": "mycoolredirect"
}
}
From the Auth tab on the Instant dashboard, add a redirect origin of type "App scheme". For development with expo add exp://
and your scheme, e.g. mycoolredirect://
.
Now you're ready to add a login button to your expo app:
import { Button } from "react-native";
import { init } from "@instantdb/react-native";
import {
makeRedirectUri,
useAuthRequest,
useAutoDiscovery,
} from "expo-auth-session";
const APP_ID = "YOUR_APP_ID";
const db = init({ appId: APP_ID });
function LoginButton() {
const discovery = useAutoDiscovery(db.auth.issuerURI());
const [request, _response, promptAsync] = useAuthRequest(
{
// The unique name you gave the OAuth client when you
// registered it on the Instant dashboard
clientId: "google-web",
redirectUri: makeRedirectUri(),
},
discovery,
);
return (
<Button
title="Log in"
disabled={!request}
onPress={async () => {
try {
const res = await promptAsync();
if (res.type === 'error') {
alert(res.error || 'Something went wrong');
}
if (res.type === 'success') {
await db.auth
.exchangeOAuthCode({
code: res.params.code,
codeVerifier: request.codeVerifier,
})
.catch((e) => alert(e.body?.message || 'Something went wrong'));
} else {
}
} catch (e) {
console.error(e);
}
}}
></Button>
);
}
Custom Auth
Want to do something more custom? You can roll your own authentication flows using the Admin SDK!
More methods coming
In the future we will provide more mechanisms for auth. If you have any requests, we're all ears!