mirror of
https://github.com/better-auth/better-auth.git
synced 2026-06-03 04:46:19 -05:00
473 lines
13 KiB
Plaintext
473 lines
13 KiB
Plaintext
---
|
|
title: Basic Usage
|
|
description: Getting started with Better Auth
|
|
---
|
|
|
|
Better Auth provides built-in authentication support for:
|
|
|
|
- **Email and password**
|
|
- **Social provider (Google, Github, Apple, and more)**
|
|
|
|
<Callout>
|
|
You can extend authentication options using plugins, such as: Username-based login, Passkeys, Email magic links, and more.
|
|
</Callout>
|
|
|
|
## Email & Password
|
|
|
|
To enable email and password authentication:
|
|
|
|
```ts title="auth.ts"
|
|
import { betterAuth } from "better-auth"
|
|
|
|
export const auth = betterAuth({
|
|
//...rest of the options
|
|
emailAndPassword: { // [!code highlight]
|
|
enabled: true // [!code highlight]
|
|
} // [!code highlight]
|
|
})
|
|
```
|
|
|
|
### Signup
|
|
|
|
Before a user can sign in, they need to sign up. To sign up a user using email and password, you need to call the client method `signUp.email` with the user's information.
|
|
|
|
|
|
**Example: Using React**
|
|
|
|
```tsx title="SignUp.tsx"
|
|
import { authClient } from '@/auth'; //import the auth client
|
|
|
|
export default function SignUp() {
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [name, setName] = useState('');
|
|
const [image, setImage] = useState<File | null>(null);
|
|
|
|
const signUp = async () => {
|
|
const res = await authClient.signUp.email({
|
|
email,
|
|
password,
|
|
name,
|
|
image: image ? convertImageToBase64(image) : undefined,
|
|
}, {
|
|
onRequest: (ctx) => {
|
|
//show loading
|
|
},
|
|
onsSuccess: (ctx) => {
|
|
//redirect to the dashboard
|
|
},
|
|
onError: (ctx) => {
|
|
alert(ctx.error.message);
|
|
},
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<input type="name" value={email} onChange={(e) => setEmail(e.target.value)} />
|
|
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
|
|
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
|
|
<input type="file" onChange={(e) => setImage(e.target.files?.[0])} />
|
|
<button onClick={signUp}>Sign Up</button>
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
### Signin
|
|
|
|
To signin a user, you can use the `signIn.email` function provided by the client. The `signIn` function takes an object with the following properties:
|
|
|
|
**Example: Using Svlete**
|
|
|
|
```svelte title="signin.svelte"
|
|
<script lang="ts">
|
|
import { client } from "$lib/auth-client"; //import the auth client
|
|
import { writable } from "svelte/store";
|
|
|
|
const email = writable("");
|
|
const password = writable("");
|
|
|
|
const handleSignIn = async () => {
|
|
await client.signIn.email({
|
|
email: $email,
|
|
password: $password
|
|
}, {
|
|
onRequest: () => {
|
|
//show loading
|
|
},
|
|
onSuccess: () => {
|
|
//redirect to dashboard
|
|
},
|
|
onError: (ctx) => {
|
|
alert(ctx.error.message)
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<div>
|
|
<input type="email" bind:value={$email} />
|
|
<input type="password" bind:value={$password} />
|
|
<button on:click={handleSignIn}>
|
|
Sign In
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
## Social Sign-On
|
|
|
|
Better Auth supports multiple social providers, including Google, Github, Apple, Discord, and more. To use a social provider, you need to configure the ones you need in the `socialProvider` option on your `auth` object.
|
|
|
|
```ts title="auth.ts"
|
|
import { betterAuth } from "better-auth"
|
|
import { github } from "better-auth/social-providers"
|
|
|
|
export const auth = betterAuth({
|
|
//...rest of the options
|
|
socialProviders: { // [!code highlight]
|
|
github: { // [!code highlight]
|
|
clientId: GITHUB_CLIENT_ID, // [!code highlight]
|
|
clientSecret: GITHUB_CLIENT_SECRET, // [!code highlight]
|
|
} // [!code highlight]
|
|
}, // [!code highlight]
|
|
})
|
|
```
|
|
|
|
### Signin with social providers
|
|
|
|
To sign in using a social provider you need to calle `signIn.social` method and pass the `provider`.
|
|
|
|
It also takes `callbackURL` property which is the url the user will be redirected after they signIn.
|
|
|
|
**Example: Using Vue**
|
|
|
|
```vue title="signin.vue"
|
|
<template>
|
|
<div>
|
|
<h2>Sign In</h2>
|
|
<button @click="handleSignIn">Sign In with GitHub</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { client } from "@/auth-client"; //import the auth client
|
|
|
|
export default {
|
|
name: "SignIn",
|
|
methods: {
|
|
async handleSignIn() {
|
|
await client.signIn.social({
|
|
provider: "github",
|
|
callbackURL: "/dashboard", //redirect to dashboard after sign in
|
|
});
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
```
|
|
|
|
## Session Mangemnt
|
|
|
|
Once a user is signed in, you'll want to access their session. Better auth allows you easily to access the session data from the server and client side.
|
|
|
|
### Client Side
|
|
|
|
Better Auth provides a `useSession` hook to easily access session data on the client side. This hook is implemented in a reactive way for each supported framework, ensuring that any changes to the session (such as signing out) are immediately reflected in your UI.
|
|
|
|
It has the following properties:
|
|
- **data**: the actual session data which includes `session` and `user` object.
|
|
- **isPending**: a boolean that indicates whether the session is being loaded.
|
|
- **error**: an error object that contains any errors that occurred while loading the session.
|
|
|
|
<Tabs items={["Vanilla","React", "Vue","Svelte", "Solid"]} defaultValue="React">
|
|
<Tab value="React">
|
|
```tsx title="user.tsx"
|
|
//make sure you're using the react client
|
|
import { createAuthClient } from "better-auth/react"
|
|
const { useSession } = createAuthClient() // [!code highlight]
|
|
|
|
export function User(){
|
|
const {
|
|
data: session,
|
|
isPending, //loading state
|
|
error //error object
|
|
} = useSession()
|
|
returns (
|
|
//...
|
|
)
|
|
}
|
|
```
|
|
</Tab>
|
|
|
|
<Tab value="Vue">
|
|
```vue title="index.vue"
|
|
<script setup lang="ts">
|
|
import { client } from "~/lib/client"
|
|
const session = client.useSession()
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<button v-if="!session?.data" @click="() => client.signIn.social({
|
|
provider: 'github'
|
|
})">
|
|
Continue with github
|
|
</button>
|
|
<div>
|
|
<pre>{{ session.data }}</pre>
|
|
<button v-if="session.data" @click="client.signOut()">
|
|
Sign out
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
```
|
|
</Tab>
|
|
|
|
<Tab value="Svelte">
|
|
```svelte title="user.svelte"
|
|
<script lang="ts">
|
|
import { client } from "$lib/client";
|
|
const session = client.useSession();
|
|
</script>
|
|
|
|
<div
|
|
style="display: flex; flex-direction: column; gap: 10px; border-radius: 10px; border: 1px solid #4B453F; padding: 20px; margin-top: 10px;"
|
|
>
|
|
<div>
|
|
{#if $session}
|
|
<div>
|
|
<p>
|
|
{$session?.user.name}
|
|
</p>
|
|
<p>
|
|
{$session?.user.email}
|
|
</p>
|
|
<button
|
|
on:click={async () => {
|
|
await client.signOut();
|
|
}}
|
|
>
|
|
Signout
|
|
</button>
|
|
</div>
|
|
{:else}
|
|
<button
|
|
on:click={async () => {
|
|
await client.signIn.social({
|
|
provider: "github",
|
|
});
|
|
}}
|
|
>
|
|
Continue with github
|
|
</button>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
```
|
|
</Tab>
|
|
<Tab value="Vanilla">
|
|
```ts title="user.svelte"
|
|
import { client } from "~/lib/client";
|
|
clinet.useSession.subscribe((value)=>{
|
|
//do something with the session
|
|
})
|
|
```
|
|
</Tab>
|
|
|
|
<Tab value="Solid">
|
|
```tsx title="user.tsx"
|
|
import { client } from "~/lib/client";
|
|
import { Show } from 'solid-js';
|
|
|
|
export default function Home() {
|
|
const session = client.useSession()
|
|
return (
|
|
<Show
|
|
when={session()}
|
|
fallback={<button onClick={toggle}>Log in</button>}
|
|
>
|
|
<button onClick={toggle}>Log out</button>
|
|
</Show>
|
|
);
|
|
}
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
<Callout>
|
|
For more details check [session-management](/docs/concepts/session-management) documentation.
|
|
</Callout>
|
|
|
|
### Server Side
|
|
|
|
The server provides a `session` object that you can use to access the session data. It requires request headers object to be passed to the `getSession` method.
|
|
|
|
**Example: Using some popular frameworks**
|
|
|
|
<Tabs items={["NextJs", "NuxtJs", "Svelte", "Astro", "Hono"]}>
|
|
<Tab value="NextJs">
|
|
```ts title="server.ts"
|
|
import { auth } from "./auth";
|
|
import { headers } from "next/headers";
|
|
|
|
const session = await auth.api.getSession({
|
|
headers: headers() // you need to pass the headers object.
|
|
})
|
|
```
|
|
</Tab>
|
|
<Tab value="Astro">
|
|
```astro title="index.astro"
|
|
---
|
|
import { auth } from "./auth";
|
|
|
|
const session = await auth.api.getSession({
|
|
headers: Astro.request.headers,
|
|
});
|
|
---
|
|
<!-- Your Astro Template -->
|
|
```
|
|
</Tab>
|
|
<Tab value="Svelte">
|
|
```ts title="+page.ts"
|
|
import { auth } from "./auth";
|
|
|
|
export async function load({ request }) {
|
|
const session = await auth.api.getSession({
|
|
headers: request.headers
|
|
})
|
|
return {
|
|
props: {
|
|
session
|
|
}
|
|
}
|
|
}
|
|
```
|
|
</Tab>
|
|
<Tab value="Hono">
|
|
```ts title="index.ts"
|
|
import { auth } from "./auth";
|
|
|
|
const app = new Hono();
|
|
|
|
app.get("/path", async (c) => {
|
|
const session = auth.api.getSession({
|
|
headers: c.req.raw.headers
|
|
})
|
|
});
|
|
```
|
|
</Tab>
|
|
|
|
<Tab value="Nuxt">
|
|
```ts title="server/session.ts"
|
|
import { auth } from "~/utils/auth";
|
|
|
|
export default defineEventHandler((event) => {
|
|
const session = await auth.api.getSession({
|
|
headers: event.headers,
|
|
})
|
|
});
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
## Using Plugins
|
|
|
|
One of the unique features of better auth is a plugins ecosystem. It allows you to add complex auth realted functionilty with small lines of code.
|
|
|
|
Below is an example of how to add two factor authentication using two factor plugin.
|
|
|
|
<Steps>
|
|
|
|
<Step>
|
|
### Server Configuration
|
|
|
|
To add a plugin, you need to import the plugin and pass it to the `plugins` option of the auth instance. For example, to add two facor authentication, you can use the following code:
|
|
|
|
```ts title="auth.ts"
|
|
import { betterAuth } from "better-auth"
|
|
import { twoFactor } from "better-auth/plugins"
|
|
|
|
export const auth = betterAuth({
|
|
//...rest of the options
|
|
plugins: [ // [!code highlight]
|
|
twoFactor({
|
|
issuer: "my app" //your application name
|
|
}) // [!code highlight]
|
|
] // [!code highlight]
|
|
})
|
|
```
|
|
now two factor related routes and method will be available on the server.
|
|
|
|
</Step>
|
|
<Step>
|
|
### Migrate Database
|
|
|
|
once you have added the plugin, you need to migrate your database to add the necessary tables and fields. You can do this by running the following command:
|
|
|
|
```bash
|
|
npx better-auth migrate
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Client Configuration
|
|
|
|
Once we're done with the server, we need to add the plugin to the client. To do this, you need to import the plugin and pass it to the `plugins` option of the auth client. For example, to add two facor authentication, you can use the following code:
|
|
|
|
```ts title="client.ts" /
|
|
import { createAuthClient } from "better-auth/client";
|
|
import { twoFactorClient } from "better-auth/client/plugins";
|
|
|
|
const client = createAuthClient({
|
|
plugins: [ // [!code highlight]
|
|
twoFactorClient({ // [!code highlight]
|
|
twoFactorPage: "/two-factor" // [!code highlight]
|
|
}) // [!code highlight]
|
|
] // [!code highlight]
|
|
})
|
|
```
|
|
|
|
now two factor related methods will be available on the client.
|
|
|
|
```ts title="profile.ts"
|
|
import { client } from "./client"
|
|
|
|
const enableTwoFactor = async() => {
|
|
const data = await client.twoFactor.enable({
|
|
password // the user password is required
|
|
}) // this will enable two factor
|
|
}
|
|
|
|
const disableTwoFactor = async() => {
|
|
const data = await client.twoFactor.disable({
|
|
password // the user password is required
|
|
}) // this will disable two factor
|
|
}
|
|
|
|
const signInWith2Factor = async() => {
|
|
const data = await client.signIn.email({
|
|
//...
|
|
})
|
|
//if the user has two factor enabled, it will redirect to the two factor page
|
|
}
|
|
|
|
const verifyTOTP = async() => {
|
|
const data = await client.twoFactor.verifyTOTP({
|
|
code: "123456", // the code entered by the user
|
|
/**
|
|
* If the device is trusted, the user won't
|
|
* need to pass 2FA again on the same device
|
|
*/
|
|
trustDevice: true
|
|
})
|
|
}
|
|
```
|
|
</Step>
|
|
|
|
<Step>
|
|
Next step: See the <Link href="/docs/plugins/2fa">the two factor plugin documentation</Link>.
|
|
</Step>
|
|
</Steps>
|