Explore

Auth

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.

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('')
  return (
    <div 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
          style={authStyles.button}
          onClick={() => {
            if (!email) return
            setSentEmail(email)
            db.auth.sendMagicCode({ email }).catch((err) => {
              alert('Uh oh :' + err.body?.message)
              setSentEmail('')
            })
          }}
        >
          Send Code
        </button>
      </div>
    </div>
  )
}

function MagicCode({ sentEmail }) {
  const [code, setCode] = useState('')
  return (
    <div 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
        style={authStyles.button}
        onClick={() => {
          db.auth
            .signInWithMagicCode({ email: sentEmail, code })
            .catch((err) => {
              alert('Uh oh :' + err.body?.message)
              setCode('')
            })
        }}
      >
        Verify
      </button>
    </div>
  )
}

const authStyles = {
  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.

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!

Previous
Reading data