mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-10 12:27:44 +00:00
docs: v1.3 announcement changelog (#3476)
* v1.3 init anouncement changelog docs * revamp on guide * stale * saml * code block * update * update * revamp and update * feat: changelog image * docs and og image * revert * update * v1.3 * cont * init * update * chore add count method * update og * update og --------- Co-authored-by: Kinfe123 <kinfishtech@gmail.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import Link from "next/link";
|
||||
import { useId } from "react";
|
||||
|
||||
import clsx from "clsx";
|
||||
import { DiscordLogoIcon } from "@radix-ui/react-icons";
|
||||
@@ -91,21 +90,6 @@ export function IntroFooter() {
|
||||
);
|
||||
}
|
||||
|
||||
export function SignUpForm() {
|
||||
let id = useId();
|
||||
|
||||
return (
|
||||
<form className="relative isolate mt-8 flex items-center pr-1">
|
||||
<label htmlFor={id} className="sr-only">
|
||||
Email address
|
||||
</label>
|
||||
|
||||
<div className="absolute inset-0 -z-10 rounded-lg transition peer-focus:ring-4 peer-focus:ring-sky-300/15" />
|
||||
<div className="absolute inset-0 -z-10 rounded-lg bg-white/2.5 ring-1 ring-white/15 transition peer-focus:ring-sky-300" />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export function IconLink({
|
||||
children,
|
||||
className,
|
||||
|
||||
@@ -11,7 +11,17 @@ interface BlogLayoutProps {
|
||||
|
||||
export default function BlogLayout({ children }: BlogLayoutProps) {
|
||||
return (
|
||||
<div className="relative flex min-h-screen flex-col">
|
||||
<div
|
||||
className="relative flex min-h-screen flex-col"
|
||||
style={{
|
||||
scrollbarWidth: "none",
|
||||
scrollbarColor: "transparent transparent",
|
||||
//@ts-expect-error
|
||||
"&::-webkit-scrollbar": {
|
||||
display: "none",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<main className="flex-1">{children}</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -18,10 +18,9 @@ import { Pre } from "fumadocs-ui/components/codeblock";
|
||||
import { DocsBody } from "fumadocs-ui/page";
|
||||
import ChangelogPage, { Glow } from "../_components/default-changelog";
|
||||
import { IconLink } from "../_components/changelog-layout";
|
||||
import { BookIcon, GitHubIcon, XIcon } from "../_components/icons";
|
||||
import { DiscordLogoIcon } from "@radix-ui/react-icons";
|
||||
import { XIcon } from "../_components/icons";
|
||||
import { StarField } from "../_components/stat-field";
|
||||
import { CalendarClockIcon } from "lucide-react";
|
||||
import { GridPatterns } from "../_components/grid-pattern";
|
||||
|
||||
const metaTitle = "Changelogs";
|
||||
const metaDescription = "Latest changes , fixes and updates.";
|
||||
@@ -49,44 +48,21 @@ export default async function Page({
|
||||
<div className="bg-gradient-to-tr hidden md:block overflow-hidden px-12 py-24 md:py-0 -mt-[100px] md:h-dvh relative md:sticky top-0 from-transparent dark:via-stone-950/5 via-stone-100/30 to-stone-200/20 dark:to-transparent/10">
|
||||
<StarField className="top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2" />
|
||||
<Glow />
|
||||
|
||||
<div className="flex flex-col md:justify-center max-w-xl mx-auto h-full">
|
||||
<h1 className="mt-14 font-sans font-semibold tracking-tighter text-5xl">
|
||||
<GridPatterns />
|
||||
<div className="z-20 flex flex-col md:justify-center max-w-xl mx-auto h-full">
|
||||
<div className="mt-14 mb-2 text-gray-600 dark:text-gray-300 flex items-center gap-x-1">
|
||||
<p className="text-[12px] uppercase font-mono">
|
||||
{formatDate(date)}
|
||||
</p>
|
||||
</div>
|
||||
<h1 className=" font-sans mb-2 font-semibold tracking-tighter text-5xl">
|
||||
{title}{" "}
|
||||
</h1>
|
||||
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">
|
||||
<p className="text-sm text-gray-600 mb-2 dark:text-gray-300">
|
||||
{description}
|
||||
</p>
|
||||
<div className="text-gray-600 dark:text-gray-300 flex items-center gap-x-1">
|
||||
<CalendarClockIcon className="w-4 h-4" />
|
||||
<p>{formatDate(date)}</p>
|
||||
</div>
|
||||
<hr className="h-px bg-gray-300 mt-5" />
|
||||
<div className="mt-8 flex flex-wrap text-gray-600 dark:text-gray-300 gap-x-1 gap-y-3 sm:gap-x-2">
|
||||
<IconLink
|
||||
href="/docs"
|
||||
icon={BookIcon}
|
||||
className="flex-none text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
Documentation
|
||||
</IconLink>
|
||||
<IconLink
|
||||
href="https://github.com/better-auth/better-auth"
|
||||
icon={GitHubIcon}
|
||||
className="flex-none text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
GitHub
|
||||
</IconLink>
|
||||
<IconLink
|
||||
href="https://discord.gg/better-auth"
|
||||
icon={DiscordLogoIcon}
|
||||
className="flex-none text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
Community
|
||||
</IconLink>
|
||||
</div>
|
||||
<p className="flex items-baseline absolute bottom-4 max-md:left-1/2 max-md:-translate-x-1/2 gap-x-2 text-[0.8125rem]/6 text-gray-500">
|
||||
<hr className="mt-4" />
|
||||
<p className="absolute bottom-10 text-[0.8125rem]/6 text-gray-500">
|
||||
<IconLink href="https://x.com/better_auth" icon={XIcon} compact>
|
||||
BETTER-AUTH.
|
||||
</IconLink>
|
||||
@@ -95,7 +71,7 @@ export default async function Page({
|
||||
</div>
|
||||
<div className="px-4 relative md:px-8 pb-12 md:py-12">
|
||||
<div className="absolute top-0 left-0 h-full -translate-x-full w-px bg-gradient-to-b from-black/5 dark:from-white/10 via-black/3 dark:via-white/5 to-transparent"></div>
|
||||
<DocsBody>
|
||||
<DocsBody className="pt-8 md:pt-0">
|
||||
<MDX
|
||||
components={{
|
||||
...defaultMdxComponents,
|
||||
|
||||
22
docs/app/changelogs/_components/grid-pattern.tsx
Normal file
22
docs/app/changelogs/_components/grid-pattern.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function GridPatterns() {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"pointer-events-none",
|
||||
"fixed inset-y-0 left-0 z-0",
|
||||
"w-1/2 h-full",
|
||||
"overflow-hidden",
|
||||
)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div className="absolute opacity-40 inset-0 w-full h-full bg-[radial-gradient(circle_at_center,rgba(0,0,0,0.04)_1px,transparent_1px)] dark:bg-[radial-gradient(circle_at_center,rgba(255,255,255,0.04)_1px,transparent_1px)] bg-[length:8px_8px]" />
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-br opacity-40 from-white/40 via-transparent to-white/10 dark:from-white/10 dark:to-transparent mix-blend-screen" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { GridPatterns };
|
||||
335
docs/content/blogs/1-3.mdx
Normal file
335
docs/content/blogs/1-3.mdx
Normal file
@@ -0,0 +1,335 @@
|
||||
---
|
||||
title: "Better Auth 1.3"
|
||||
description: "SSO with SAML, Multi Team Support, Additional Fields for Organization, Performance and more."
|
||||
date: 2025-07-19
|
||||
author:
|
||||
name: "Bereket Engida"
|
||||
avatar: "/blogs/bereket.png"
|
||||
twitter: "iambereket"
|
||||
image: "/release-og/1-3.png"
|
||||
tags: ["1.3", "authentication", "oidc", "mcp", "sso", "organization"]
|
||||
---
|
||||
|
||||
## Better Auth 1.3 Release
|
||||
|
||||
We're excited to announce the release of Better Auth 1.3. This release includes a lot of new features and improvements.
|
||||
|
||||
To upgrade, run:
|
||||
|
||||
```package-install
|
||||
npm install better-auth@1.3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Highlights
|
||||
|
||||
### **SSO Plugin**
|
||||
|
||||
The SSO plugin has been moved to its own package and now supports both **OIDC** and **SAML 2.0**.
|
||||
|
||||
👉 [Read the SSO docs](/docs/plugins/sso)
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
import { sso } from "@better-auth/sso";
|
||||
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
sso({
|
||||
oidc: {
|
||||
clientId: process.env.OIDC_CLIENT_ID!,
|
||||
clientSecret: process.env.OIDC_CLIENT_SECRET!,
|
||||
},
|
||||
saml: {
|
||||
entryPoint: "https://example.com/saml",
|
||||
issuer: "better-auth-example",
|
||||
certificate: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
|
||||
},
|
||||
providersLimit: async (user) => {
|
||||
const plan = await getUserPlan(user);
|
||||
return plan.name === "pro" ? 10 : 1;
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **OIDC & MCP Plugins – Now Stable**
|
||||
|
||||
Both OIDC and MCP plugins are production‑ready.
|
||||
|
||||
✅ Features:
|
||||
|
||||
* Refresh token support in discovery & token endpoints
|
||||
* JWKs and PKCE for public clients
|
||||
* Trusted clients
|
||||
* Encrypted & hashed client secrets
|
||||
|
||||
👉 [Read OIDC docs](/docs/plugins/oidc)
|
||||
👉 [Read MCP docs](/docs/plugins/mcp)
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { mcp } from "better-auth/plugins";
|
||||
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
mcp({
|
||||
loginPage: "/login",
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Stripe Plugin is now production ready**
|
||||
|
||||
The Stripe plugin is now stable and usage based pricing is coming very soon.
|
||||
|
||||
👉 [Read Stripe docs](/docs/plugins/stripe)
|
||||
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
import { stripe } from "@better-auth/stripe";
|
||||
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
stripe({
|
||||
// ...
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
### **SIWE Plugin**
|
||||
|
||||
Native support for **Sign‑In with Ethereum**.
|
||||
|
||||
👉 [Read SIWE docs](/docs/plugins/siwe)
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { siwe } from "better-auth/plugins";
|
||||
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
siwe(),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **New Social Providers**
|
||||
|
||||
We’ve added providers for **Notion, Slack, Linear, and Faceit**.
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
|
||||
export const auth = betterAuth({
|
||||
socialProviders: {
|
||||
notion: { /* ... */ },
|
||||
slack: { /* ... */ },
|
||||
linear: { /* ... */ },
|
||||
faceit: { /* ... */ },
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **SvelteKit Cookie Helper Plugin**
|
||||
|
||||
Utilities for handling cookies in SvelteKit server actions.
|
||||
|
||||
<Callout type="warn">
|
||||
Breaking change: `building` and `getRequestEvent()` must now be passed in as props.
|
||||
</Callout>
|
||||
|
||||
```ts title="auth.ts"
|
||||
import { betterAuth } from "better-auth";
|
||||
import { sveltekitCookies } from "better-auth/svelte-kit";
|
||||
import { getRequestEvent } from "$app/server";
|
||||
|
||||
export const auth = betterAuth({
|
||||
plugins: [sveltekitCookies(getRequestEvent)],
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Email Verification on Sign‑In**
|
||||
|
||||
```ts title="auth.ts"
|
||||
export const auth = betterAuth({
|
||||
emailVerification: {
|
||||
sendOnSignIn: true, // sends a verification email on sign‑in if the user isn’t verified
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Multi‑Team Support**
|
||||
|
||||
The organization plugin now supports members belonging to multiple teams.
|
||||
|
||||
**Breaking change:**
|
||||
`teamId` has been removed from the `member` table. A new `teamMembers` table is required.
|
||||
|
||||
```ts title="auth.ts"
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
organization({
|
||||
// ...
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Additional Organization Fields**
|
||||
|
||||
Add custom fields to `organization`, `member`, and `invitation` models.
|
||||
|
||||
```ts title="auth.ts"
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
organization({
|
||||
schema: {
|
||||
organization: { additionalFields: { /* ... */ } },
|
||||
member: { additionalFields: { /* ... */ } },
|
||||
invitation: { additionalFields: { /* ... */ } },
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
Other new options:
|
||||
|
||||
* `MaximumMembersPerTeam` – set team member limits
|
||||
* `listUserInvitations` – list all invitations for a user
|
||||
|
||||
---
|
||||
|
||||
### **Generic OAuth Improvements**
|
||||
|
||||
* Added support for extra token URL params
|
||||
* OAuth token encryption options
|
||||
|
||||
```ts title="auth.ts"
|
||||
export const auth = betterAuth({
|
||||
plugins: [
|
||||
genericOAuth({
|
||||
// ...
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **API Keys**
|
||||
|
||||
* `requireName` option for key creation
|
||||
* `verifyKey` now supports async functions
|
||||
|
||||
---
|
||||
|
||||
### **Username**
|
||||
|
||||
* Availability checks
|
||||
* Custom normalization
|
||||
|
||||
---
|
||||
|
||||
### ✨ More Features
|
||||
|
||||
* Migrated to **Zod 4** for better type safety and performance
|
||||
* CLI supports custom adapter `createSchema`
|
||||
* `inferAuth` utility to infer types from the client
|
||||
* Improved docs with `auth` and `authClient` examples
|
||||
* `rememberMe` support in `signUp`
|
||||
* `afterEmailVerification` hook
|
||||
* `freshAge` and custom `errorURL` respected properly
|
||||
* OAuth2 tokens now include `refresh_token_expires_in`
|
||||
|
||||
---
|
||||
|
||||
### 🐛 Bug Fixes & Improvements
|
||||
|
||||
#### Plugins
|
||||
|
||||
* Expo: Fixed type path import
|
||||
* SSO: Fixed SAML redirection & type checks
|
||||
* Dropbox: Token access type support
|
||||
* Stripe:
|
||||
|
||||
* Prevent duplicate customers
|
||||
* Allow upgrading incomplete subscriptions
|
||||
* Admin:
|
||||
|
||||
* Fixed missing `ctx` in hooks
|
||||
* Proper error when removing invalid user IDs
|
||||
|
||||
#### OAuth & Providers
|
||||
|
||||
* Fixed duplicate OAuth registration
|
||||
* Improved Google/Microsoft scope handling
|
||||
* Fixed malformed error URLs in generic OAuth
|
||||
* Facebook: Better detection for limited token JWT
|
||||
* Twitter: Improved email verification logic
|
||||
|
||||
#### Core Authentication
|
||||
|
||||
* Exclude current user from username uniqueness check
|
||||
* Support `callbackURL` in `signInUsername`
|
||||
* Allow account linking without email
|
||||
* Fixed missing `null` type in `/get-session` response
|
||||
* Global `onSuccess` hook now works
|
||||
* JWT: Alternate algorithms supported in JWKS
|
||||
* `origin-check`: Wildcard trusted origins supported
|
||||
|
||||
#### CLI, DB, and Adapters
|
||||
|
||||
* CLI: Improved Drizzle schema formatting
|
||||
* MongoAdapter: Works with `create-adapter`
|
||||
* Schema generation respects `useNumberId`
|
||||
* Postgres: Better varchar normalization and type comparison
|
||||
* Drizzle CLI: Uses `serial` as PK if `useNumberId` is enabled
|
||||
|
||||
#### Email & OTP
|
||||
|
||||
* OTPs now encrypted
|
||||
* Fixed `onEmailVerification` not firing
|
||||
* Proper error when sign‑up is disabled
|
||||
* Phone number: Reset clears verification values
|
||||
|
||||
#### Two-Factor Auth
|
||||
|
||||
* Default OTP period fix
|
||||
* URI generation doesn’t require enabling 2FA
|
||||
* Fixed OTP URI separator mismatch
|
||||
|
||||
#### Miscellaneous
|
||||
|
||||
* Delete organization if member not found
|
||||
* Correct error codes for API key rate limits
|
||||
* Additional fields now show in OpenAPI
|
||||
* Fixed FK constraint generation for MySQL
|
||||
* Various improvements to account linking
|
||||
* OIDC `offline_access` no longer requires `prompt=consent`
|
||||
* Fixed malformed base64 encoding for token validation
|
||||
|
||||
---
|
||||
|
||||
A lot of refinements to make everything smoother, faster, and more reliable.
|
||||
👉 [Check the full changelog](https://github.com/better-auth/better-auth/releases/tag/v1.3.0)
|
||||
|
||||
---
|
||||
BIN
docs/public/release-og/1-3.png
Normal file
BIN
docs/public/release-og/1-3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 654 KiB |
@@ -599,7 +599,15 @@ export const getOrgAdapter = <O extends OrganizationOptions>(
|
||||
|
||||
return members;
|
||||
},
|
||||
|
||||
countMembers: async (data: {
|
||||
organizationId: string;
|
||||
}) => {
|
||||
const count = await adapter.count({
|
||||
model: "member",
|
||||
where: [{ field: "organizationId", value: data.organizationId }],
|
||||
});
|
||||
return count;
|
||||
},
|
||||
listTeamsByUser: async (data: {
|
||||
userId: string;
|
||||
}) => {
|
||||
|
||||
@@ -131,9 +131,9 @@ export const addMember = <O extends OrganizationOptions>(option: O) => {
|
||||
}
|
||||
|
||||
const membershipLimit = ctx.context.orgOptions?.membershipLimit || 100;
|
||||
const members = await adapter.listMembers({ organizationId: orgId });
|
||||
const count = await adapter.countMembers({ organizationId: orgId });
|
||||
|
||||
if (members.length >= membershipLimit) {
|
||||
if (count >= membershipLimit) {
|
||||
throw new APIError("FORBIDDEN", {
|
||||
message:
|
||||
ORGANIZATION_ERROR_CODES.ORGANIZATION_MEMBERSHIP_LIMIT_REACHED,
|
||||
|
||||
Reference in New Issue
Block a user