@neondatabase/auth 0.1.0-beta.15 → 0.1.0-beta.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/{adapter-core-ChIlSbGg.mjs → adapter-core-BQ6ga1zK.mjs} +2 -28
- package/dist/{better-auth-react-adapter-C3_WRaIy.mjs → better-auth-react-adapter-BLKXYcWM.mjs} +1 -1
- package/dist/{better-auth-react-adapter-AucJqubr.d.mts → better-auth-react-adapter-BWH-XVdf.d.mts} +1 -1
- package/dist/constants-2bpp2_-f.mjs +30 -0
- package/dist/index-B4dy0AqC.d.mts +49 -0
- package/dist/index.d.mts +5 -105
- package/dist/index.mjs +2 -2
- package/dist/middleware-DPLYghmx.mjs +303 -0
- package/dist/{neon-auth-sSiNq4zM.mjs → neon-auth-ClDZNB9a.mjs} +1 -1
- package/dist/neon-auth-DDPaciiS.d.mts +105 -0
- package/dist/next/index.d.mts +63 -98
- package/dist/next/index.mjs +26 -301
- package/dist/next/server/index.d.mts +389 -0
- package/dist/next/server/index.mjs +432 -0
- package/dist/react/adapters/index.d.mts +4 -4
- package/dist/react/adapters/index.mjs +2 -2
- package/dist/react/index.d.mts +5 -5
- package/dist/react/index.mjs +4 -5
- package/dist/react/ui/index.d.mts +1 -1
- package/dist/react/ui/index.mjs +2 -3
- package/dist/react/ui/server.mjs +2 -2
- package/dist/{supabase-adapter-DhlcXYb9.mjs → supabase-adapter-Bl576usk.mjs} +2 -1
- package/dist/{supabase-adapter-Bbn88gZj.d.mts → supabase-adapter-k8RBezY9.d.mts} +1 -1
- package/dist/types/index.d.mts +2 -2
- package/dist/ui-DLtIc4wi.mjs +4 -0
- package/dist/vanilla/adapters/index.d.mts +4 -4
- package/dist/vanilla/adapters/index.mjs +2 -2
- package/dist/vanilla/index.d.mts +4 -4
- package/dist/vanilla/index.mjs +2 -2
- package/package.json +5 -1
- package/dist/chunk-5DLVHPZS-Bxj7snpZ-EhdAQJMu.mjs +0 -533
- package/dist/ui-C1IRQzLY.mjs +0 -9449
- /package/dist/{adapter-core-CtcS7ex8.d.mts → adapter-core-Sx7jkLdB.d.mts} +0 -0
- /package/dist/{adapters-D0mxG3F-.mjs → adapters-CUvhsAvY.mjs} +0 -0
- /package/dist/{adapters-Df6Dd3KK.mjs → adapters-CivF9wql.mjs} +0 -0
- /package/dist/{better-auth-types-VqadyqlG.d.mts → better-auth-types-Kq3kGuiz.d.mts} +0 -0
- /package/dist/{index-ClXLQ1fw.d.mts → index-D8dPsry7.d.mts} +0 -0
- /package/dist/{index-BXlAjlSt.d.mts → index-D_HDtZfY.d.mts} +0 -0
- /package/dist/{index-DCQ5Y2ED.d.mts → index-OEBbnNdr.d.mts} +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { r as SupportedBetterAuthClientPlugins } from "./adapter-core-Sx7jkLdB.mjs";
|
|
2
|
+
import { r as BetterAuthReactAdapterInstance } from "./better-auth-react-adapter-BWH-XVdf.mjs";
|
|
3
|
+
import { r as SupabaseAuthAdapterInstance, s as BetterAuthVanillaAdapterInstance } from "./supabase-adapter-k8RBezY9.mjs";
|
|
4
|
+
import { createAuthClient } from "better-auth/react";
|
|
5
|
+
import { createAuthClient as createAuthClient$1 } from "better-auth/client";
|
|
6
|
+
|
|
7
|
+
//#region src/neon-auth.d.ts
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Type representing the Better Auth React client
|
|
11
|
+
*/
|
|
12
|
+
type ReactBetterAuthClient = ReturnType<typeof createAuthClient<{
|
|
13
|
+
plugins: SupportedBetterAuthClientPlugins;
|
|
14
|
+
}>>;
|
|
15
|
+
/**`
|
|
16
|
+
* Type representing the Better Auth Vanilla client
|
|
17
|
+
*/
|
|
18
|
+
type VanillaBetterAuthClient = ReturnType<typeof createAuthClient$1<{
|
|
19
|
+
plugins: SupportedBetterAuthClientPlugins;
|
|
20
|
+
}>>;
|
|
21
|
+
/**
|
|
22
|
+
* Union type of all supported auth adapter instances
|
|
23
|
+
*/
|
|
24
|
+
type NeonAuthAdapter = BetterAuthVanillaAdapterInstance | BetterAuthReactAdapterInstance | SupabaseAuthAdapterInstance;
|
|
25
|
+
/**
|
|
26
|
+
* Configuration for createAuthClient
|
|
27
|
+
*/
|
|
28
|
+
interface NeonAuthConfig<T extends NeonAuthAdapter> {
|
|
29
|
+
/** The adapter builder to use. Defaults to BetterAuthVanillaAdapter() if not specified. */
|
|
30
|
+
adapter?: (url: string) => T;
|
|
31
|
+
/**
|
|
32
|
+
* When true, automatically uses an anonymous token when no user session exists.
|
|
33
|
+
* This enables RLS-based data access for users with the anonymous role.
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
allowAnonymous?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolves the public API type for an adapter.
|
|
40
|
+
* - SupabaseAuthAdapter: exposes its own methods directly (Supabase-compatible API)
|
|
41
|
+
* - BetterAuth adapters: expose the Better Auth client directly
|
|
42
|
+
*/
|
|
43
|
+
type NeonAuthPublicApi<T extends NeonAuthAdapter> = T extends BetterAuthVanillaAdapterInstance ? VanillaBetterAuthClient : T extends BetterAuthReactAdapterInstance ? ReactBetterAuthClient : T;
|
|
44
|
+
/**
|
|
45
|
+
* NeonAuth type - combines base functionality with the appropriate public API
|
|
46
|
+
* This is the return type of createAuthClient()
|
|
47
|
+
*
|
|
48
|
+
* For SupabaseAuthAdapter: exposes Supabase-compatible methods (signInWithPassword, getSession, etc.)
|
|
49
|
+
* For BetterAuth adapters: exposes the Better Auth client directly (signIn.email, signUp.email, etc.)
|
|
50
|
+
*/
|
|
51
|
+
type NeonAuth<T extends NeonAuthAdapter> = {
|
|
52
|
+
adapter: NeonAuthPublicApi<T>;
|
|
53
|
+
getJWTToken: () => Promise<string | null>;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Create a NeonAuth instance that exposes the appropriate API based on the adapter.
|
|
57
|
+
*
|
|
58
|
+
* @param url - The auth service URL (e.g., 'https://auth.example.com')
|
|
59
|
+
* @param config - Configuration with adapter builder
|
|
60
|
+
* @returns NeonAuth instance with the adapter's API exposed directly
|
|
61
|
+
*
|
|
62
|
+
* @example SupabaseAuthAdapter - Supabase-compatible API
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import { createAuthClient, SupabaseAuthAdapter } from '@neondatabase/auth';
|
|
65
|
+
*
|
|
66
|
+
* const auth = createAuthClient('https://auth.example.com', {
|
|
67
|
+
* adapter: SupabaseAuthAdapter(),
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // Supabase-compatible methods
|
|
71
|
+
* await auth.signInWithPassword({ email, password });
|
|
72
|
+
* await auth.getSession();
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @example BetterAuthVanillaAdapter - Direct Better Auth API
|
|
76
|
+
* ```typescript
|
|
77
|
+
* import { createAuthClient, BetterAuthVanillaAdapter } from '@neondatabase/auth';
|
|
78
|
+
*
|
|
79
|
+
* const auth = createAuthClient('https://auth.example.com', {
|
|
80
|
+
* adapter: BetterAuthVanillaAdapter(),
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* // Direct Better Auth API access
|
|
84
|
+
* await auth.signIn.email({ email, password });
|
|
85
|
+
* await auth.signUp.email({ email, password, name: 'John' });
|
|
86
|
+
* await auth.getSession();
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @example BetterAuthReactAdapter - Better Auth with React hooks
|
|
90
|
+
* ```typescript
|
|
91
|
+
* import { createAuthClient, BetterAuthReactAdapter } from '@neondatabase/auth';
|
|
92
|
+
*
|
|
93
|
+
* const auth = createAuthClient('https://auth.example.com', {
|
|
94
|
+
* adapter: BetterAuthReactAdapter(),
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* // Direct Better Auth API with React hooks
|
|
98
|
+
* await auth.signIn.email({ email, password });
|
|
99
|
+
* const session = auth.useSession(); // React hook
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
declare function createInternalNeonAuth<T extends NeonAuthAdapter = BetterAuthVanillaAdapterInstance>(url: string, config?: NeonAuthConfig<T>): NeonAuth<T>;
|
|
103
|
+
declare function createAuthClient$2<T extends NeonAuthAdapter = BetterAuthVanillaAdapterInstance>(url: string, config?: NeonAuthConfig<T>): NeonAuthPublicApi<T>;
|
|
104
|
+
//#endregion
|
|
105
|
+
export { ReactBetterAuthClient as a, createInternalNeonAuth as c, NeonAuthPublicApi as i, NeonAuthAdapter as n, VanillaBetterAuthClient as o, NeonAuthConfig as r, createAuthClient$2 as s, NeonAuth as t };
|
package/dist/next/index.d.mts
CHANGED
|
@@ -1,108 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../better-auth-types-Kq3kGuiz.mjs";
|
|
2
|
+
import { n as SessionData, t as neonAuthMiddleware$1 } from "../index-B4dy0AqC.mjs";
|
|
2
3
|
import * as better_auth_client0 from "better-auth/client";
|
|
3
4
|
import * as better_auth_client_plugins0 from "better-auth/client/plugins";
|
|
4
5
|
import * as jose0 from "jose";
|
|
5
|
-
import
|
|
6
|
+
import * as next_server0 from "next/server";
|
|
6
7
|
import * as better_auth0 from "better-auth";
|
|
7
8
|
import * as _better_fetch_fetch0 from "@better-fetch/fetch";
|
|
8
9
|
import * as nanostores0 from "nanostores";
|
|
9
10
|
|
|
10
|
-
//#region src/next/handler/index.d.ts
|
|
11
|
-
type Params = {
|
|
12
|
-
path: string[];
|
|
13
|
-
};
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* An API route handler to handle the auth requests from the client and proxy them to the Neon Auth.
|
|
17
|
-
*
|
|
18
|
-
* @returns A Next.js API handler functions those can be used in a Next.js route.
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
*
|
|
22
|
-
* Mount the `authApiHandler` to an API route. Create a route file inside `/api/auth/[...all]/route.ts` directory.
|
|
23
|
-
* And add the following code:
|
|
24
|
-
*
|
|
25
|
-
* ```ts
|
|
26
|
-
*
|
|
27
|
-
* import { authApiHandler } from '@neondatabase/auth/next';
|
|
28
|
-
*
|
|
29
|
-
* export const { GET, POST } = authApiHandler();
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
*/
|
|
33
|
-
declare function authApiHandler(): {
|
|
34
|
-
GET: (request: Request, {
|
|
35
|
-
params
|
|
36
|
-
}: {
|
|
37
|
-
params: Promise<Params>;
|
|
38
|
-
}) => Promise<Response>;
|
|
39
|
-
POST: (request: Request, {
|
|
40
|
-
params
|
|
41
|
-
}: {
|
|
42
|
-
params: Promise<Params>;
|
|
43
|
-
}) => Promise<Response>;
|
|
44
|
-
PUT: (request: Request, {
|
|
45
|
-
params
|
|
46
|
-
}: {
|
|
47
|
-
params: Promise<Params>;
|
|
48
|
-
}) => Promise<Response>;
|
|
49
|
-
DELETE: (request: Request, {
|
|
50
|
-
params
|
|
51
|
-
}: {
|
|
52
|
-
params: Promise<Params>;
|
|
53
|
-
}) => Promise<Response>;
|
|
54
|
-
PATCH: (request: Request, {
|
|
55
|
-
params
|
|
56
|
-
}: {
|
|
57
|
-
params: Promise<Params>;
|
|
58
|
-
}) => Promise<Response>;
|
|
59
|
-
};
|
|
60
|
-
//#endregion
|
|
61
|
-
//#region src/next/middleware/index.d.ts
|
|
62
|
-
type NeonAuthMiddlewareOptions = {
|
|
63
|
-
loginUrl?: string;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* A Next.js middleware to protect routes from unauthenticated requests and refresh the session if required.
|
|
67
|
-
*
|
|
68
|
-
* @param loginUrl - The URL to redirect to when the user is not authenticated.
|
|
69
|
-
* @returns A middleware function that can be used in the Next.js app.
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```ts
|
|
73
|
-
* import { neonAuthMiddleware } from "@neondatabase/auth/next"
|
|
74
|
-
*
|
|
75
|
-
* export default neonAuthMiddleware({
|
|
76
|
-
* loginUrl: '/auth/sign-in',
|
|
77
|
-
* });
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
declare function neonAuthMiddleware({
|
|
81
|
-
loginUrl
|
|
82
|
-
}: NeonAuthMiddlewareOptions): (request: NextRequest) => Promise<NextResponse<unknown>>;
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/next/auth/session.d.ts
|
|
85
|
-
type SessionData = {
|
|
86
|
-
session: BetterAuthSession;
|
|
87
|
-
user: BetterAuthUser;
|
|
88
|
-
} | {
|
|
89
|
-
session: null;
|
|
90
|
-
user: null;
|
|
91
|
-
};
|
|
92
|
-
/**
|
|
93
|
-
* A utility function to be used in react server components fetch the session details from the Neon Auth API, if session token is available in cookie.
|
|
94
|
-
*
|
|
95
|
-
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```ts
|
|
99
|
-
* import { neonAuth } from "@neondatabase/auth/next"
|
|
100
|
-
*
|
|
101
|
-
* const { session, user } = await neonAuth()
|
|
102
|
-
* ```
|
|
103
|
-
*/
|
|
104
|
-
declare const neonAuth: () => Promise<SessionData>;
|
|
105
|
-
//#endregion
|
|
106
11
|
//#region src/next/index.d.ts
|
|
107
12
|
declare function createAuthClient(): {
|
|
108
13
|
useActiveOrganization: () => {
|
|
@@ -2230,5 +2135,65 @@ declare function createAuthClient(): {
|
|
|
2230
2135
|
readonly USER_ALREADY_HAS_PASSWORD: "User already has a password. Provide that to delete the account.";
|
|
2231
2136
|
};
|
|
2232
2137
|
};
|
|
2138
|
+
/**
|
|
2139
|
+
* @deprecated
|
|
2140
|
+
* - Moved to `@neondatabase/auth/next/server` and
|
|
2141
|
+
* - Moved to `@neondatabase/neon-js/auth/next/server`
|
|
2142
|
+
*
|
|
2143
|
+
* An API route handler to handle the auth requests from the client and proxy them to the Neon Auth.
|
|
2144
|
+
*/
|
|
2145
|
+
declare function authApiHandler(): {
|
|
2146
|
+
GET: (request: Request, {
|
|
2147
|
+
params
|
|
2148
|
+
}: {
|
|
2149
|
+
params: Promise<{
|
|
2150
|
+
path: string[];
|
|
2151
|
+
}>;
|
|
2152
|
+
}) => Promise<Response>;
|
|
2153
|
+
POST: (request: Request, {
|
|
2154
|
+
params
|
|
2155
|
+
}: {
|
|
2156
|
+
params: Promise<{
|
|
2157
|
+
path: string[];
|
|
2158
|
+
}>;
|
|
2159
|
+
}) => Promise<Response>;
|
|
2160
|
+
PUT: (request: Request, {
|
|
2161
|
+
params
|
|
2162
|
+
}: {
|
|
2163
|
+
params: Promise<{
|
|
2164
|
+
path: string[];
|
|
2165
|
+
}>;
|
|
2166
|
+
}) => Promise<Response>;
|
|
2167
|
+
DELETE: (request: Request, {
|
|
2168
|
+
params
|
|
2169
|
+
}: {
|
|
2170
|
+
params: Promise<{
|
|
2171
|
+
path: string[];
|
|
2172
|
+
}>;
|
|
2173
|
+
}) => Promise<Response>;
|
|
2174
|
+
PATCH: (request: Request, {
|
|
2175
|
+
params
|
|
2176
|
+
}: {
|
|
2177
|
+
params: Promise<{
|
|
2178
|
+
path: string[];
|
|
2179
|
+
}>;
|
|
2180
|
+
}) => Promise<Response>;
|
|
2181
|
+
};
|
|
2182
|
+
/**
|
|
2183
|
+
* @deprecated
|
|
2184
|
+
* - Moved to `@neondatabase/auth/next/server` and
|
|
2185
|
+
* - Moved to `@neondatabase/neon-js/auth/next/server`
|
|
2186
|
+
*
|
|
2187
|
+
* A Next.js middleware to protect routes from unauthenticated requests and refresh the session if required.
|
|
2188
|
+
*/
|
|
2189
|
+
declare function neonAuthMiddleware(args: Parameters<typeof neonAuthMiddleware$1>[0]): (request: next_server0.NextRequest) => Promise<next_server0.NextResponse<unknown>>;
|
|
2190
|
+
/**
|
|
2191
|
+
* @deprecated
|
|
2192
|
+
* - Moved to `@neondatabase/auth/next/server` and
|
|
2193
|
+
* - Moved to `@neondatabase/neon-js/auth/next/server`
|
|
2194
|
+
*
|
|
2195
|
+
* A utility function to be used in react server components fetch the session details from the Neon Auth API, if session token is available in cookie.
|
|
2196
|
+
*/
|
|
2197
|
+
declare function neonAuth(): Promise<SessionData>;
|
|
2233
2198
|
//#endregion
|
|
2234
2199
|
export { authApiHandler, createAuthClient, neonAuth, neonAuthMiddleware };
|
package/dist/next/index.mjs
CHANGED
|
@@ -1,316 +1,41 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { t as BetterAuthReactAdapter } from "../better-auth-react-adapter-
|
|
3
|
-
import { t as createAuthClient$1 } from "../neon-auth-
|
|
4
|
-
import {
|
|
5
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
6
|
-
import { cookies, headers } from "next/headers";
|
|
1
|
+
import "../adapter-core-BQ6ga1zK.mjs";
|
|
2
|
+
import { t as BetterAuthReactAdapter } from "../better-auth-react-adapter-BLKXYcWM.mjs";
|
|
3
|
+
import { t as createAuthClient$1 } from "../neon-auth-ClDZNB9a.mjs";
|
|
4
|
+
import { n as neonAuth$1, r as authApiHandler$1, t as neonAuthMiddleware$1 } from "../middleware-DPLYghmx.mjs";
|
|
7
5
|
|
|
8
|
-
//#region src/next/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region src/next/constants.ts
|
|
13
|
-
const NEON_AUTH_COOKIE_PREFIX = "__Secure-neon-auth";
|
|
14
|
-
const NEON_AUTH_SESSION_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_token`;
|
|
15
|
-
const NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_challange`;
|
|
16
|
-
const NEON_AUTH_HEADER_MIDDLEWARE_NAME = "X-Neon-Auth-Next-Middleware";
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/next/auth/cookies.ts
|
|
20
|
-
/**
|
|
21
|
-
* Extract the Neon Auth cookies from the request headers that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
22
|
-
*
|
|
23
|
-
* @param headers - The request headers.
|
|
24
|
-
* @returns The cookie string with all Neon Auth cookies.
|
|
25
|
-
*/
|
|
26
|
-
function extractRequestCookies(headers$1) {
|
|
27
|
-
const cookieHeader = headers$1.get("cookie");
|
|
28
|
-
if (!cookieHeader) return "";
|
|
29
|
-
const parsedCookies = parseCookies(cookieHeader);
|
|
30
|
-
const result = [];
|
|
31
|
-
for (const [name, value] of parsedCookies.entries()) if (name.startsWith(NEON_AUTH_COOKIE_PREFIX)) result.push({
|
|
32
|
-
name,
|
|
33
|
-
value
|
|
34
|
-
});
|
|
35
|
-
return result.map((cookie) => cookie.name + "=" + cookie.value).join("; ");
|
|
6
|
+
//#region src/next/index.ts
|
|
7
|
+
function createAuthClient() {
|
|
8
|
+
return createAuthClient$1(void 0, { adapter: BetterAuthReactAdapter() });
|
|
36
9
|
}
|
|
37
10
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* @returns The cookies that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
42
|
-
*/
|
|
43
|
-
const extractResponseCookies = (headers$1) => {
|
|
44
|
-
const cookieHeader = headers$1.get("set-cookie");
|
|
45
|
-
if (!cookieHeader) return [];
|
|
46
|
-
return cookieHeader.split(", ").map((c) => c.trim());
|
|
47
|
-
};
|
|
48
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
* Parses the `set-cookie` header from Neon Auth response into the list of ResponseCookies,
|
|
51
|
-
* compatible with NextCookies.
|
|
52
|
-
*
|
|
53
|
-
* @param cookies - The `set-cookie` header from Neon Auth response.
|
|
54
|
-
* @returns The list of ResponseCookies.
|
|
55
|
-
*/
|
|
56
|
-
const parseSetCookies = (cookies$1) => {
|
|
57
|
-
const parsedCookies = parseSetCookieHeader(cookies$1);
|
|
58
|
-
const responseCookies = [];
|
|
59
|
-
for (const entry of parsedCookies.entries()) {
|
|
60
|
-
const [name, parsedCookie] = entry;
|
|
61
|
-
responseCookies.push({
|
|
62
|
-
name,
|
|
63
|
-
value: decodeURIComponent(parsedCookie.value),
|
|
64
|
-
path: parsedCookie.path,
|
|
65
|
-
maxAge: parsedCookie["max-age"] ?? parsedCookie.maxAge,
|
|
66
|
-
httpOnly: parsedCookie.httponly ?? true,
|
|
67
|
-
secure: parsedCookie.secure ?? true,
|
|
68
|
-
sameSite: parsedCookie.samesite ?? "none",
|
|
69
|
-
partitioned: parsedCookie.partitioned
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
return responseCookies;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
//#endregion
|
|
76
|
-
//#region src/next/handler/request.ts
|
|
77
|
-
const PROXY_HEADERS = [
|
|
78
|
-
"user-agent",
|
|
79
|
-
"authorization",
|
|
80
|
-
"referer",
|
|
81
|
-
"content-type"
|
|
82
|
-
];
|
|
83
|
-
const handleAuthRequest = async (baseUrl, request, path) => {
|
|
84
|
-
const headers$1 = prepareRequestHeaders(request);
|
|
85
|
-
const body = await parseRequestBody(request);
|
|
86
|
-
try {
|
|
87
|
-
const upstreamURL = getUpstreamURL(baseUrl, path, { originalUrl: new URL(request.url) });
|
|
88
|
-
return await fetch(upstreamURL.toString(), {
|
|
89
|
-
method: request.method,
|
|
90
|
-
headers: headers$1,
|
|
91
|
-
body
|
|
92
|
-
});
|
|
93
|
-
} catch (error) {
|
|
94
|
-
const message = error instanceof Error ? error.message : "Internal Server Error";
|
|
95
|
-
console.error(`[AuthError] ${message}`, error);
|
|
96
|
-
return new Response(`[AuthError] ${message}`, { status: 500 });
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
const getUpstreamURL = (baseUrl, path, { originalUrl }) => {
|
|
100
|
-
const url = new URL(`${baseUrl}/${path}`);
|
|
101
|
-
if (originalUrl) {
|
|
102
|
-
url.search = originalUrl.search;
|
|
103
|
-
return url;
|
|
104
|
-
}
|
|
105
|
-
return url;
|
|
106
|
-
};
|
|
107
|
-
const prepareRequestHeaders = (request) => {
|
|
108
|
-
const headers$1 = new Headers();
|
|
109
|
-
for (const header of PROXY_HEADERS) if (request.headers.get(header)) headers$1.set(header, request.headers.get(header));
|
|
110
|
-
headers$1.set("Origin", getOrigin(request));
|
|
111
|
-
headers$1.set("Cookie", extractRequestCookies(request.headers));
|
|
112
|
-
headers$1.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
|
|
113
|
-
return headers$1;
|
|
114
|
-
};
|
|
115
|
-
const getOrigin = (request) => {
|
|
116
|
-
return request.headers.get("origin") || request.headers.get("referer")?.split("/").slice(0, 3).join("/") || new URL(request.url).origin;
|
|
117
|
-
};
|
|
118
|
-
const parseRequestBody = async (request) => {
|
|
119
|
-
if (request.body) return request.text();
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
//#endregion
|
|
123
|
-
//#region src/next/handler/response.ts
|
|
124
|
-
const RESPONSE_HEADERS_ALLOWLIST = [
|
|
125
|
-
"content-type",
|
|
126
|
-
"content-length",
|
|
127
|
-
"content-encoding",
|
|
128
|
-
"transfer-encoding",
|
|
129
|
-
"connection",
|
|
130
|
-
"date",
|
|
131
|
-
"set-cookie",
|
|
132
|
-
"set-auth-jwt",
|
|
133
|
-
"set-auth-token",
|
|
134
|
-
"x-neon-ret-request-id"
|
|
135
|
-
];
|
|
136
|
-
const handleAuthResponse = async (response) => {
|
|
137
|
-
return new Response(response.body, {
|
|
138
|
-
status: response.status,
|
|
139
|
-
statusText: response.statusText,
|
|
140
|
-
headers: prepareResponseHeaders(response)
|
|
141
|
-
});
|
|
142
|
-
};
|
|
143
|
-
const prepareResponseHeaders = (response) => {
|
|
144
|
-
const headers$1 = new Headers();
|
|
145
|
-
for (const header of RESPONSE_HEADERS_ALLOWLIST) {
|
|
146
|
-
const value = response.headers.get(header);
|
|
147
|
-
if (value) headers$1.set(header, value);
|
|
148
|
-
}
|
|
149
|
-
return headers$1;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
//#endregion
|
|
153
|
-
//#region src/next/handler/index.ts
|
|
154
|
-
/**
|
|
11
|
+
* @deprecated
|
|
12
|
+
* - Moved to `@neondatabase/auth/next/server` and
|
|
13
|
+
* - Moved to `@neondatabase/neon-js/auth/next/server`
|
|
155
14
|
*
|
|
156
15
|
* An API route handler to handle the auth requests from the client and proxy them to the Neon Auth.
|
|
157
|
-
*
|
|
158
|
-
* @returns A Next.js API handler functions those can be used in a Next.js route.
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
*
|
|
162
|
-
* Mount the `authApiHandler` to an API route. Create a route file inside `/api/auth/[...all]/route.ts` directory.
|
|
163
|
-
* And add the following code:
|
|
164
|
-
*
|
|
165
|
-
* ```ts
|
|
166
|
-
*
|
|
167
|
-
* import { authApiHandler } from '@neondatabase/auth/next';
|
|
168
|
-
*
|
|
169
|
-
* export const { GET, POST } = authApiHandler();
|
|
170
|
-
* ```
|
|
171
|
-
*
|
|
172
16
|
*/
|
|
173
17
|
function authApiHandler() {
|
|
174
|
-
|
|
175
|
-
if (!baseURL) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
|
|
176
|
-
const handler = async (request, { params }) => {
|
|
177
|
-
return await handleAuthResponse(await handleAuthRequest(baseURL, request, (await params).path.join("/")));
|
|
178
|
-
};
|
|
179
|
-
return {
|
|
180
|
-
GET: handler,
|
|
181
|
-
POST: handler,
|
|
182
|
-
PUT: handler,
|
|
183
|
-
DELETE: handler,
|
|
184
|
-
PATCH: handler
|
|
185
|
-
};
|
|
18
|
+
return authApiHandler$1();
|
|
186
19
|
}
|
|
187
|
-
|
|
188
|
-
//#endregion
|
|
189
|
-
//#region src/next/middleware/oauth.ts
|
|
190
|
-
const needsSessionVerification = (request) => {
|
|
191
|
-
const hasVerifier = request.nextUrl.searchParams.has(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
192
|
-
const hasChallenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
|
|
193
|
-
return hasVerifier && hasChallenge;
|
|
194
|
-
};
|
|
195
|
-
const exchangeOAuthToken = async (request, baseUrl) => {
|
|
196
|
-
const url = request.nextUrl;
|
|
197
|
-
const verifier = url.searchParams.get(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
198
|
-
const challenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
|
|
199
|
-
if (!verifier || !challenge) return null;
|
|
200
|
-
const response = await handleAuthResponse(await handleAuthRequest(baseUrl, new Request(request.url, {
|
|
201
|
-
method: "GET",
|
|
202
|
-
headers: request.headers
|
|
203
|
-
}), "get-session"));
|
|
204
|
-
if (response.ok) {
|
|
205
|
-
const headers$1 = new Headers();
|
|
206
|
-
const cookies$1 = extractResponseCookies(response.headers);
|
|
207
|
-
for (const cookie of cookies$1) headers$1.append("Set-Cookie", cookie);
|
|
208
|
-
url.searchParams.delete(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
209
|
-
return NextResponse.redirect(url, { headers: headers$1 });
|
|
210
|
-
}
|
|
211
|
-
return null;
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
//#endregion
|
|
215
|
-
//#region src/next/env-variables.ts
|
|
216
|
-
const NEON_AUTH_BASE_URL = process.env.NEON_AUTH_BASE_URL;
|
|
217
|
-
|
|
218
|
-
//#endregion
|
|
219
|
-
//#region src/next/auth/session.ts
|
|
220
|
-
/**
|
|
221
|
-
* A utility function to be used in react server components fetch the session details from the Neon Auth API, if session token is available in cookie.
|
|
222
|
-
*
|
|
223
|
-
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
224
|
-
*
|
|
225
|
-
* @example
|
|
226
|
-
* ```ts
|
|
227
|
-
* import { neonAuth } from "@neondatabase/auth/next"
|
|
228
|
-
*
|
|
229
|
-
* const { session, user } = await neonAuth()
|
|
230
|
-
* ```
|
|
231
|
-
*/
|
|
232
|
-
const neonAuth = async () => {
|
|
233
|
-
return await fetchSession();
|
|
234
|
-
};
|
|
235
|
-
/**
|
|
236
|
-
* A utility function to fetch the session details from the Neon Auth API, if session token is available in cookie.
|
|
237
|
-
*
|
|
238
|
-
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
239
|
-
*/
|
|
240
|
-
const fetchSession = async () => {
|
|
241
|
-
const baseUrl = NEON_AUTH_BASE_URL;
|
|
242
|
-
const requestHeaders = await headers();
|
|
243
|
-
const upstreamURL = getUpstreamURL(baseUrl, "get-session", { originalUrl: new URL("get-session", baseUrl) });
|
|
244
|
-
const response = await fetch(upstreamURL.toString(), {
|
|
245
|
-
method: "GET",
|
|
246
|
-
headers: { Cookie: extractRequestCookies(requestHeaders) }
|
|
247
|
-
});
|
|
248
|
-
const body = await response.json();
|
|
249
|
-
const cookieHeader = response.headers.get("set-cookie");
|
|
250
|
-
if (cookieHeader) {
|
|
251
|
-
const cookieStore = await cookies();
|
|
252
|
-
parseSetCookies(cookieHeader).map((cookie) => {
|
|
253
|
-
cookieStore.set(cookie.name, cookie.value, cookie);
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
if (!response.ok || body === null) return {
|
|
257
|
-
session: null,
|
|
258
|
-
user: null
|
|
259
|
-
};
|
|
260
|
-
return {
|
|
261
|
-
session: body.session,
|
|
262
|
-
user: body.user
|
|
263
|
-
};
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
//#endregion
|
|
267
|
-
//#region src/next/middleware/index.ts
|
|
268
|
-
const SKIP_ROUTES = [
|
|
269
|
-
"/api/auth",
|
|
270
|
-
"/auth/callback",
|
|
271
|
-
"/auth/sign-in",
|
|
272
|
-
"/auth/sign-up",
|
|
273
|
-
"/auth/magic-link",
|
|
274
|
-
"/auth/email-otp",
|
|
275
|
-
"/auth/forgot-password"
|
|
276
|
-
];
|
|
277
20
|
/**
|
|
21
|
+
* @deprecated
|
|
22
|
+
* - Moved to `@neondatabase/auth/next/server` and
|
|
23
|
+
* - Moved to `@neondatabase/neon-js/auth/next/server`
|
|
24
|
+
*
|
|
278
25
|
* A Next.js middleware to protect routes from unauthenticated requests and refresh the session if required.
|
|
279
|
-
*
|
|
280
|
-
* @param loginUrl - The URL to redirect to when the user is not authenticated.
|
|
281
|
-
* @returns A middleware function that can be used in the Next.js app.
|
|
282
|
-
*
|
|
283
|
-
* @example
|
|
284
|
-
* ```ts
|
|
285
|
-
* import { neonAuthMiddleware } from "@neondatabase/auth/next"
|
|
286
|
-
*
|
|
287
|
-
* export default neonAuthMiddleware({
|
|
288
|
-
* loginUrl: '/auth/sign-in',
|
|
289
|
-
* });
|
|
290
|
-
* ```
|
|
291
26
|
*/
|
|
292
|
-
function neonAuthMiddleware(
|
|
293
|
-
|
|
294
|
-
if (!baseUrl) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
|
|
295
|
-
return async (request) => {
|
|
296
|
-
const { pathname } = request.nextUrl;
|
|
297
|
-
if (pathname.startsWith(loginUrl)) return NextResponse.next();
|
|
298
|
-
if (needsSessionVerification(request)) {
|
|
299
|
-
const response = await exchangeOAuthToken(request, baseUrl);
|
|
300
|
-
if (response !== null) return response;
|
|
301
|
-
}
|
|
302
|
-
if (SKIP_ROUTES.some((route) => pathname.startsWith(route))) return NextResponse.next();
|
|
303
|
-
if ((await fetchSession()).session === null) return NextResponse.redirect(new URL(loginUrl, request.url));
|
|
304
|
-
const reqHeaders = new Headers(request.headers);
|
|
305
|
-
reqHeaders.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
|
|
306
|
-
return NextResponse.next({ request: { headers: reqHeaders } });
|
|
307
|
-
};
|
|
27
|
+
function neonAuthMiddleware(args) {
|
|
28
|
+
return neonAuthMiddleware$1(args);
|
|
308
29
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated
|
|
32
|
+
* - Moved to `@neondatabase/auth/next/server` and
|
|
33
|
+
* - Moved to `@neondatabase/neon-js/auth/next/server`
|
|
34
|
+
*
|
|
35
|
+
* A utility function to be used in react server components fetch the session details from the Neon Auth API, if session token is available in cookie.
|
|
36
|
+
*/
|
|
37
|
+
function neonAuth() {
|
|
38
|
+
return neonAuth$1();
|
|
314
39
|
}
|
|
315
40
|
|
|
316
41
|
//#endregion
|