mirror of
https://github.com/better-auth/better-auth.git
synced 2026-05-26 00:46:44 -05:00
API
This commit is contained in:
@@ -268,9 +268,9 @@ bun migration.ts # or use node, ts-node, etc.
|
||||
<Step>
|
||||
### Update your code
|
||||
|
||||
Update your codebase from supabase auth calls to Better Auth api.
|
||||
Update your codebase from supabase auth calls to Better Auth API.
|
||||
|
||||
Here's a list of the supabase auth api calls and their Better Auth counterparts.
|
||||
Here's a list of the supabase auth API calls and their Better Auth counterparts.
|
||||
|
||||
- `supabase.auth.signUp` -> `authClient.signUp.email`
|
||||
- `supabase.auth.signInWithPassword` -> `authClient.signIn.email`
|
||||
|
||||
@@ -228,7 +228,7 @@ You can use even more authentication methods like [passkey](/docs/plugins/passke
|
||||
|
||||
<Step>
|
||||
### Mount Handler
|
||||
To handle api requests, you need to set up a route handler on your server.
|
||||
To handle API requests, you need to set up a route handler on your server.
|
||||
|
||||
Create a new file or route in your framework's designated catch-all route handler. This route should handle requests for the path `/api/auth/*` (unless you've configured a different base path).
|
||||
|
||||
|
||||
@@ -535,7 +535,7 @@ console.log(apiKey.metadata.plan); // "premium"
|
||||
|
||||
`apiKeyHeaders` <span className="opacity-70">`string | string[];`</span>
|
||||
|
||||
The header name to check for api key. Default is `x-api-key`.
|
||||
The header name to check for API key. Default is `x-api-key`.
|
||||
|
||||
|
||||
`customAPIKeyGetter` <span className="opacity-70">`(ctx: GenericEndpointContext) => string | null`</span>
|
||||
@@ -656,7 +656,7 @@ Customize the rate-limiting.
|
||||
|
||||
`schema` <span className="opacity-70">`InferOptionSchema<ReturnType<typeof apiKeySchema>>`</span>
|
||||
|
||||
Custom schema for the api key plugin.
|
||||
Custom schema for the API key plugin.
|
||||
|
||||
`disableSessionForAPIKeys` <span className="opacity-70">`boolean`</span>
|
||||
|
||||
@@ -687,7 +687,7 @@ Table: `apiKey`
|
||||
{
|
||||
name: "id",
|
||||
type: "string",
|
||||
description: "The ID of the api key.",
|
||||
description: "The ID of the API key.",
|
||||
isUnique: true,
|
||||
isPrimaryKey: true,
|
||||
},
|
||||
|
||||
@@ -170,7 +170,7 @@ const res = await authClient.signIn.sso({
|
||||
});
|
||||
```
|
||||
|
||||
To use the server api you can use `signInSSO`
|
||||
To use the server API you can use `signInSSO`
|
||||
|
||||
```ts title="sign-in-org.ts"
|
||||
const res = await auth.api.signInSSO({
|
||||
|
||||
@@ -519,7 +519,7 @@ describe("api-key", async () => {
|
||||
expect(apiKey.metadata.test).toEqual(metadata.test);
|
||||
});
|
||||
|
||||
it("create api key with with metadata when metadata is disabled (should fail)", async () => {
|
||||
it("create API key with with metadata when metadata is disabled (should fail)", async () => {
|
||||
const { client, auth, signInWithTestUser } = await getTestInstance(
|
||||
{
|
||||
plugins: [
|
||||
@@ -674,7 +674,7 @@ describe("api-key", async () => {
|
||||
// VERIFY API KEY
|
||||
// =========================================================================
|
||||
|
||||
it("verify api key without key and userId", async () => {
|
||||
it("verify API key without key and userId", async () => {
|
||||
const apiKey = await auth.api.verifyApiKey({
|
||||
body: {
|
||||
userId: user.id,
|
||||
@@ -685,7 +685,7 @@ describe("api-key", async () => {
|
||||
expect(apiKey.valid).toBe(true);
|
||||
});
|
||||
|
||||
it("verify api key with invalid key (should fail)", async () => {
|
||||
it("verify API key with invalid key (should fail)", async () => {
|
||||
const apiKey = await auth.api.verifyApiKey({
|
||||
body: {
|
||||
key: "invalid",
|
||||
@@ -722,7 +722,7 @@ describe("api-key", async () => {
|
||||
|
||||
const { headers: rateLimitUserHeaders } = await rateLimitTestUser();
|
||||
|
||||
it("should fail to verify api key 20 times in a row due to rate-limit", async () => {
|
||||
it("should fail to verify API key 20 times in a row due to rate-limit", async () => {
|
||||
const { data: apiKey2 } = await rateLimitClient.apiKey.create(
|
||||
{},
|
||||
{ headers: rateLimitUserHeaders },
|
||||
@@ -745,7 +745,7 @@ describe("api-key", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("should allow us to verify api key after rate-limit window has passed", async () => {
|
||||
it("should allow us to verify API key after rate-limit window has passed", async () => {
|
||||
vi.useFakeTimers();
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
const response = await rateLimitAuth.api.verifyApiKey({
|
||||
@@ -758,7 +758,7 @@ describe("api-key", async () => {
|
||||
expect(response?.valid).toBe(true);
|
||||
});
|
||||
|
||||
it("should check if verifying an api key's remaining count does go down", async () => {
|
||||
it("should check if verifying an API key's remaining count does go down", async () => {
|
||||
const remaining = 10;
|
||||
const { data: apiKey } = await client.apiKey.create(
|
||||
{
|
||||
@@ -785,7 +785,7 @@ describe("api-key", async () => {
|
||||
expect(afterVerificationTwice?.key?.remaining).toEqual(remaining - 2);
|
||||
});
|
||||
|
||||
it("should fail if the api key has no remaining", async () => {
|
||||
it("should fail if the API key has no remaining", async () => {
|
||||
const apiKey = await auth.api.createApiKey({
|
||||
body: {
|
||||
remaining: 1,
|
||||
@@ -809,7 +809,7 @@ describe("api-key", async () => {
|
||||
expect(afterVerification.error?.code).toBe("USAGE_EXCEEDED");
|
||||
});
|
||||
|
||||
it("should fail if the api key is expired", async () => {
|
||||
it("should fail if the API key is expired", async () => {
|
||||
vi.useRealTimers();
|
||||
const { headers } = await signInWithTestUser();
|
||||
const apiKey2 = await client.apiKey.create(
|
||||
@@ -834,7 +834,7 @@ describe("api-key", async () => {
|
||||
// UPDATE API KEY
|
||||
// =========================================================================
|
||||
|
||||
it("should fail to update api key name without headers or userId", async () => {
|
||||
it("should fail to update API key name without headers or userId", async () => {
|
||||
let error: APIError | null = null;
|
||||
await auth.api
|
||||
.updateApiKey({
|
||||
@@ -850,7 +850,7 @@ describe("api-key", async () => {
|
||||
expect(error).toBeInstanceOf(APIError);
|
||||
});
|
||||
|
||||
it("should update api key name with headers", async () => {
|
||||
it("should update API key name with headers", async () => {
|
||||
const newName = "Hello World";
|
||||
const apiKey = await auth.api.updateApiKey({
|
||||
body: {
|
||||
@@ -864,7 +864,7 @@ describe("api-key", async () => {
|
||||
expect(apiKey.name).toEqual(newName);
|
||||
});
|
||||
|
||||
it("should fail to update api key name with a length larger than the allowed maximum", async () => {
|
||||
it("should fail to update API key name with a length larger than the allowed maximum", async () => {
|
||||
let error: APIError | null = null;
|
||||
await auth.api
|
||||
.updateApiKey({
|
||||
@@ -884,7 +884,7 @@ describe("api-key", async () => {
|
||||
expect(error).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should fail to update api key name with a length smaller than the allowed minimum", async () => {
|
||||
it("should fail to update API key name with a length smaller than the allowed minimum", async () => {
|
||||
let error: APIError | null = null;
|
||||
await auth.api
|
||||
.updateApiKey({
|
||||
@@ -904,7 +904,7 @@ describe("api-key", async () => {
|
||||
expect(error).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should fail to update api key with no values to update", async () => {
|
||||
it("should fail to update API key with no values to update", async () => {
|
||||
let error: APIError | null = null;
|
||||
await auth.api
|
||||
.updateApiKey({
|
||||
@@ -923,7 +923,7 @@ describe("api-key", async () => {
|
||||
expect(error).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should update api key expiresIn value", async () => {
|
||||
it("should update API key expiresIn value", async () => {
|
||||
const expiresIn = 60 * 60 * 24 * 7; // 7 days
|
||||
const expectedResult = new Date().getTime() + expiresIn;
|
||||
const apiKey = await auth.api.updateApiKey({
|
||||
@@ -1160,7 +1160,7 @@ describe("api-key", async () => {
|
||||
expect(apiKey.refillAmount).toEqual(refillAmount);
|
||||
});
|
||||
|
||||
it("should update api key enable value", async () => {
|
||||
it("should update API key enable value", async () => {
|
||||
const newValue = false;
|
||||
const apiKey = await auth.api.updateApiKey({
|
||||
body: {
|
||||
@@ -1215,7 +1215,7 @@ describe("api-key", async () => {
|
||||
expect(apiKey.metadata).toEqual(metadata);
|
||||
});
|
||||
|
||||
it("update api key's returned metadata should be an object", async () => {
|
||||
it("update API key's returned metadata should be an object", async () => {
|
||||
const metadata = {
|
||||
test: "test-12345",
|
||||
};
|
||||
@@ -1338,7 +1338,7 @@ describe("api-key", async () => {
|
||||
expect(session?.session).toBeDefined();
|
||||
});
|
||||
|
||||
it("should get session from an API key with custom api key getter", async () => {
|
||||
it("should get session from an API key with custom API key getter", async () => {
|
||||
const { client, auth, signInWithTestUser } = await getTestInstance(
|
||||
{
|
||||
plugins: [
|
||||
@@ -1371,7 +1371,7 @@ describe("api-key", async () => {
|
||||
expect(session?.session).toBeDefined();
|
||||
});
|
||||
|
||||
it("should fail to get session from an API key with invalid api key", async () => {
|
||||
it("should fail to get session from an API key with invalid API key", async () => {
|
||||
const headers = new Headers();
|
||||
headers.set("x-api-key", "invalid");
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ export function verifyApiKey({
|
||||
],
|
||||
});
|
||||
|
||||
// No api key found
|
||||
// No API key found
|
||||
if (!apiKey) {
|
||||
return ctx.json({
|
||||
valid: false,
|
||||
|
||||
@@ -3,16 +3,16 @@ import type { Statements } from "../access";
|
||||
import type { apiKeySchema } from "./schema";
|
||||
export interface ApiKeyOptions {
|
||||
/**
|
||||
* The header name to check for api key
|
||||
* The header name to check for API key
|
||||
* @default "x-api-key"
|
||||
*/
|
||||
apiKeyHeaders?: string | string[];
|
||||
/**
|
||||
* The function to get the api key from the context
|
||||
* The function to get the API key from the context
|
||||
*/
|
||||
customAPIKeyGetter?: (ctx: GenericEndpointContext) => string | null;
|
||||
/**
|
||||
* A custom function to validate the api key
|
||||
* A custom function to validate the API key
|
||||
*/
|
||||
customAPIKeyValidator?: (options: {
|
||||
ctx: GenericEndpointContext;
|
||||
@@ -154,7 +154,7 @@ export interface ApiKeyOptions {
|
||||
maxRequests?: number;
|
||||
};
|
||||
/**
|
||||
* custom schema for the api key plugin
|
||||
* custom schema for the API key plugin
|
||||
*/
|
||||
schema?: InferOptionSchema<ReturnType<typeof apiKeySchema>>;
|
||||
/**
|
||||
@@ -242,7 +242,7 @@ export type ApiKey = {
|
||||
*/
|
||||
requestCount: number;
|
||||
/**
|
||||
* Remaining requests (every time api key is used this should updated and should be updated on refill as well)
|
||||
* Remaining requests (every time API key is used this should updated and should be updated on refill as well)
|
||||
*/
|
||||
remaining: number | null;
|
||||
/**
|
||||
@@ -266,7 +266,7 @@ export type ApiKey = {
|
||||
*/
|
||||
metadata: Record<string, any> | null;
|
||||
/**
|
||||
* Permissions for the api key
|
||||
* Permissions for the API key
|
||||
*/
|
||||
permissions?: {
|
||||
[key: string]: string[];
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("open-api", async (it) => {
|
||||
plugins: [openAPI()],
|
||||
});
|
||||
|
||||
it("should generate open api schema", async () => {
|
||||
it("should generate OpenAPI schema", async () => {
|
||||
const schema = await auth.api.generateOpenAPISchema();
|
||||
expect(schema).toBeDefined();
|
||||
});
|
||||
|
||||
@@ -657,7 +657,7 @@ describe("organization", async (it) => {
|
||||
name: "name",
|
||||
};
|
||||
|
||||
// test api method
|
||||
// test API method
|
||||
const newUser = await auth.api.signUpEmail({
|
||||
body: {
|
||||
email: userOverLimit.email,
|
||||
|
||||
@@ -424,7 +424,7 @@ describe("two factor", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("two factor auth api", async () => {
|
||||
describe("two factor auth API", async () => {
|
||||
let OTP = "";
|
||||
const sendOTP = vi.fn();
|
||||
const { auth, signInWithTestUser, testUser } = await getTestInstance({
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createAuthMiddleware } from "better-auth/api";
|
||||
|
||||
export interface ExpoOptions {
|
||||
/**
|
||||
* Override origin header for expo api routes
|
||||
* Override origin header for expo API routes
|
||||
*/
|
||||
overrideOrigin?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user