@neondatabase/auth 0.1.0-beta.2 → 0.1.0-beta.4
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 +4 -2
- package/dist/index.mjs +3 -0
- package/dist/next/index.d.mts +67 -16
- package/dist/next/index.mjs +203 -58
- package/dist/react/adapters/index.mjs +2 -0
- package/dist/react/index.mjs +3 -1
- package/dist/react/ui/index.mjs +1 -1
- package/dist/{ui-CNFBSekF.mjs → ui-BQAaHqx4.mjs} +12 -27
- package/dist/vanilla/adapters/index.mjs +2 -0
- package/dist/vanilla/index.mjs +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -215,10 +215,12 @@ Multiple concurrent `getSession()` calls are automatically deduplicated:
|
|
|
215
215
|
|
|
216
216
|
For Next.js projects, this package provides built-in integration via `@neondatabase/auth/next`. See the [Next.js Setup Guide](./NEXT-JS.md) for:
|
|
217
217
|
|
|
218
|
-
-
|
|
219
|
-
-
|
|
218
|
+
- Settting up the auth handler with `authApiHandler()`
|
|
219
|
+
- Protecting routes with `neonAuthMiddleware()`
|
|
220
|
+
- creating the auth client with `createAuthClient()` for client components
|
|
220
221
|
- Configuring the `NeonAuthUIProvider`
|
|
221
222
|
- Importing styles (with or without Tailwind CSS)
|
|
223
|
+
- Access session and users details with `neonAuth()` in server components
|
|
222
224
|
|
|
223
225
|
## CSS for UI Components
|
|
224
226
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import "./adapter-core-BDOw-gBC.mjs";
|
|
2
|
+
import "./better-auth-react-adapter-FnBHa2nr.mjs";
|
|
3
|
+
import "./supabase-adapter-ggmqWgPe.mjs";
|
|
1
4
|
import { n as createInternalNeonAuth, t as createAuthClient } from "./neon-auth-C9XTFffv.mjs";
|
|
2
5
|
|
|
3
6
|
export { createAuthClient, createInternalNeonAuth };
|
package/dist/next/index.d.mts
CHANGED
|
@@ -5,12 +5,32 @@ import { NextRequest, NextResponse } from "next/server";
|
|
|
5
5
|
import * as better_auth0 from "better-auth";
|
|
6
6
|
import * as _better_fetch_fetch0 from "@better-fetch/fetch";
|
|
7
7
|
import * as nanostores0 from "nanostores";
|
|
8
|
+
import { Session, User } from "better-auth/types";
|
|
8
9
|
|
|
9
10
|
//#region src/next/handler/index.d.ts
|
|
10
11
|
type Params = {
|
|
11
12
|
path: string[];
|
|
12
13
|
};
|
|
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(): {
|
|
14
34
|
GET: (request: Request, {
|
|
15
35
|
params
|
|
16
36
|
}: {
|
|
@@ -41,23 +61,54 @@ declare const toNextJsHandler: (baseUrl: string) => {
|
|
|
41
61
|
//#region src/next/middleware/index.d.ts
|
|
42
62
|
type NeonAuthMiddlewareOptions = {
|
|
43
63
|
loginUrl?: string;
|
|
44
|
-
/**
|
|
45
|
-
* The Neon Auth base URL
|
|
46
|
-
* Defaults to `process.env.NEON_AUTH_BASE_URL`
|
|
47
|
-
*
|
|
48
|
-
* If not provided, and if not in the environment, the middleware will throw an error.
|
|
49
|
-
*
|
|
50
|
-
* @throws {Error} If the authURL is not provided and not in the environment.
|
|
51
|
-
*/
|
|
52
|
-
authBaseUrl?: string;
|
|
53
64
|
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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/core/better-auth-types.d.ts
|
|
85
|
+
type BetterAuthSession = Session;
|
|
86
|
+
type BetterAuthUser = User;
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/next/auth/session.d.ts
|
|
89
|
+
type SessionData = {
|
|
90
|
+
session: BetterAuthSession;
|
|
91
|
+
user: BetterAuthUser;
|
|
92
|
+
} | {
|
|
93
|
+
session: null;
|
|
94
|
+
user: null;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* 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.
|
|
98
|
+
*
|
|
99
|
+
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { neonAuth } from "@neondatabase/auth/next"
|
|
104
|
+
*
|
|
105
|
+
* const { session, user } = await neonAuth()
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
declare const neonAuth: () => Promise<SessionData>;
|
|
58
109
|
//#endregion
|
|
59
110
|
//#region src/next/index.d.ts
|
|
60
|
-
declare
|
|
111
|
+
declare function createAuthClient(): {
|
|
61
112
|
useActiveOrganization: () => {
|
|
62
113
|
data: better_auth0.Prettify<{
|
|
63
114
|
id: string;
|
|
@@ -2360,4 +2411,4 @@ declare const createAuthClient: () => {
|
|
|
2360
2411
|
};
|
|
2361
2412
|
};
|
|
2362
2413
|
//#endregion
|
|
2363
|
-
export { createAuthClient,
|
|
2414
|
+
export { authApiHandler, createAuthClient, neonAuth, neonAuthMiddleware };
|
package/dist/next/index.mjs
CHANGED
|
@@ -1,29 +1,99 @@
|
|
|
1
|
+
import "../adapter-core-BDOw-gBC.mjs";
|
|
1
2
|
import { t as BetterAuthReactAdapter } from "../better-auth-react-adapter-FnBHa2nr.mjs";
|
|
3
|
+
import "../supabase-adapter-ggmqWgPe.mjs";
|
|
2
4
|
import { t as createAuthClient$1 } from "../neon-auth-C9XTFffv.mjs";
|
|
5
|
+
import { parseCookies, parseSetCookieHeader } from "better-auth/cookies";
|
|
3
6
|
import { NextRequest, NextResponse } from "next/server";
|
|
7
|
+
import { cookies, headers } from "next/headers";
|
|
4
8
|
|
|
9
|
+
//#region src/next/errors.ts
|
|
10
|
+
const ERRORS = {
|
|
11
|
+
MISSING_AUTH_BASE_URL: "Missing environment variable: NEON_AUTH_BASE_URL. \n You must provide the auth url of your Neon Auth instance in environment variables",
|
|
12
|
+
NEON_AUTH_MIDDLEWARE_NOT_FOUND: "You are calling `neonAuth` on a route that is not covered by `neonAuthMiddleware`. Make sure it is running on all paths you are calling `neonAuth` from by updating your middleware config in `(middleware|proxy).(js|ts)`."
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
5
16
|
//#region src/next/constants.ts
|
|
6
17
|
const NEON_AUTH_COOKIE_PREFIX = "__Secure-neon-auth";
|
|
7
18
|
const NEON_AUTH_SESSION_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_token`;
|
|
8
19
|
const NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_challange`;
|
|
9
20
|
/** Name of the session verifier parameter in the URL, used for the OAUTH flow */
|
|
10
21
|
const NEON_AUTH_SESSION_VERIFIER_PARAM_NAME = "neon_auth_session_verifier";
|
|
22
|
+
const NEON_AUTH_HEADER_MIDDLEWARE_NAME = "X-Neon-Auth-Next-Middleware";
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/next/auth/cookies.ts
|
|
26
|
+
/**
|
|
27
|
+
* Extract the Neon Auth cookies from the request headers that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
28
|
+
*
|
|
29
|
+
* @param headers - The request headers.
|
|
30
|
+
* @returns The cookie string with all Neon Auth cookies.
|
|
31
|
+
*/
|
|
32
|
+
function extractRequestCookies(headers$1) {
|
|
33
|
+
const cookieHeader = headers$1.get("cookie");
|
|
34
|
+
if (!cookieHeader) return "";
|
|
35
|
+
const parsedCookies = parseCookies(cookieHeader);
|
|
36
|
+
const result = [];
|
|
37
|
+
for (const [name, value] of parsedCookies.entries()) if (name.startsWith(NEON_AUTH_COOKIE_PREFIX)) result.push({
|
|
38
|
+
name,
|
|
39
|
+
value
|
|
40
|
+
});
|
|
41
|
+
return result.map((cookie) => cookie.name + "=" + cookie.value).join("; ");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract the Neon Auth cookies from the response headers that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
45
|
+
*
|
|
46
|
+
* @param headers - The response headers.
|
|
47
|
+
* @returns The cookies that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
48
|
+
*/
|
|
49
|
+
const extractResponseCookies = (headers$1) => {
|
|
50
|
+
const cookieHeader = headers$1.get("set-cookie");
|
|
51
|
+
if (!cookieHeader) return [];
|
|
52
|
+
return cookieHeader.split(", ").map((c) => c.trim());
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* Parses the `set-cookie` header from Neon Auth response into the list of ResponseCookies,
|
|
57
|
+
* compatible with NextCookies.
|
|
58
|
+
*
|
|
59
|
+
* @param cookies - The `set-cookie` header from Neon Auth response.
|
|
60
|
+
* @returns The list of ResponseCookies.
|
|
61
|
+
*/
|
|
62
|
+
const parseSetCookies = (cookies$1) => {
|
|
63
|
+
const parsedCookies = parseSetCookieHeader(cookies$1);
|
|
64
|
+
const responseCookies = [];
|
|
65
|
+
for (const entry of parsedCookies.entries()) {
|
|
66
|
+
const [name, parsedCookie] = entry;
|
|
67
|
+
responseCookies.push({
|
|
68
|
+
name,
|
|
69
|
+
value: decodeURIComponent(parsedCookie.value),
|
|
70
|
+
path: parsedCookie.path,
|
|
71
|
+
maxAge: parsedCookie["max-age"] ?? parsedCookie.maxAge,
|
|
72
|
+
httpOnly: parsedCookie.httponly ?? true,
|
|
73
|
+
secure: parsedCookie.secure ?? true,
|
|
74
|
+
sameSite: parsedCookie.samesite ?? "none",
|
|
75
|
+
partitioned: parsedCookie.partitioned
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return responseCookies;
|
|
79
|
+
};
|
|
11
80
|
|
|
12
81
|
//#endregion
|
|
13
82
|
//#region src/next/handler/request.ts
|
|
14
83
|
const PROXY_HEADERS = [
|
|
15
84
|
"user-agent",
|
|
16
85
|
"authorization",
|
|
17
|
-
"referer"
|
|
86
|
+
"referer",
|
|
87
|
+
"content-type"
|
|
18
88
|
];
|
|
19
89
|
const handleAuthRequest = async (baseUrl, request, path) => {
|
|
20
|
-
const
|
|
21
|
-
const headers = prepareRequestHeaders(request);
|
|
90
|
+
const headers$1 = prepareRequestHeaders(request);
|
|
22
91
|
const body = await parseRequestBody(request);
|
|
23
92
|
try {
|
|
24
|
-
|
|
93
|
+
const upstreamURL = getUpstreamURL(baseUrl, path, { originalUrl: new URL(request.url) });
|
|
94
|
+
return await fetch(upstreamURL.toString(), {
|
|
25
95
|
method: request.method,
|
|
26
|
-
headers,
|
|
96
|
+
headers: headers$1,
|
|
27
97
|
body
|
|
28
98
|
});
|
|
29
99
|
} catch (error) {
|
|
@@ -32,29 +102,25 @@ const handleAuthRequest = async (baseUrl, request, path) => {
|
|
|
32
102
|
return new Response(`[AuthError] ${message}`, { status: 500 });
|
|
33
103
|
}
|
|
34
104
|
};
|
|
105
|
+
const getUpstreamURL = (baseUrl, path, { originalUrl }) => {
|
|
106
|
+
const url = new URL(`${baseUrl}/${path}`);
|
|
107
|
+
if (originalUrl) {
|
|
108
|
+
url.search = originalUrl.search;
|
|
109
|
+
return url;
|
|
110
|
+
}
|
|
111
|
+
return url;
|
|
112
|
+
};
|
|
35
113
|
const prepareRequestHeaders = (request) => {
|
|
36
|
-
const headers = new Headers();
|
|
37
|
-
headers.set(
|
|
38
|
-
|
|
39
|
-
headers.set("
|
|
40
|
-
headers.set("
|
|
41
|
-
headers
|
|
42
|
-
return headers;
|
|
114
|
+
const headers$1 = new Headers();
|
|
115
|
+
for (const header of PROXY_HEADERS) if (request.headers.get(header)) headers$1.set(header, request.headers.get(header));
|
|
116
|
+
headers$1.set("Origin", getOrigin(request));
|
|
117
|
+
headers$1.set("Cookie", extractRequestCookies(request.headers));
|
|
118
|
+
headers$1.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
|
|
119
|
+
return headers$1;
|
|
43
120
|
};
|
|
44
121
|
const getOrigin = (request) => {
|
|
45
122
|
return request.headers.get("origin") || request.headers.get("referer")?.split("/").slice(0, 3).join("/") || new URL(request.url).origin;
|
|
46
123
|
};
|
|
47
|
-
const extractRequestCookies = (headers) => {
|
|
48
|
-
const cookieHeader = headers.get("cookie");
|
|
49
|
-
if (!cookieHeader) return "";
|
|
50
|
-
const cookies = cookieHeader.split(";").map((c) => c.trim());
|
|
51
|
-
const result = [];
|
|
52
|
-
for (const cookie of cookies) {
|
|
53
|
-
const [name] = cookie.split("=");
|
|
54
|
-
if (name.startsWith(NEON_AUTH_COOKIE_PREFIX)) result.push(cookie);
|
|
55
|
-
}
|
|
56
|
-
return result.join(";");
|
|
57
|
-
};
|
|
58
124
|
const parseRequestBody = async (request) => {
|
|
59
125
|
if (request.body) return request.text();
|
|
60
126
|
};
|
|
@@ -81,19 +147,38 @@ const handleAuthResponse = async (response) => {
|
|
|
81
147
|
});
|
|
82
148
|
};
|
|
83
149
|
const prepareResponseHeaders = (response) => {
|
|
84
|
-
const headers = new Headers();
|
|
150
|
+
const headers$1 = new Headers();
|
|
85
151
|
for (const header of RESPONSE_HEADERS_ALLOWLIST) {
|
|
86
152
|
const value = response.headers.get(header);
|
|
87
|
-
if (value) headers.set(header, value);
|
|
153
|
+
if (value) headers$1.set(header, value);
|
|
88
154
|
}
|
|
89
|
-
return headers;
|
|
155
|
+
return headers$1;
|
|
90
156
|
};
|
|
91
157
|
|
|
92
158
|
//#endregion
|
|
93
159
|
//#region src/next/handler/index.ts
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
160
|
+
/**
|
|
161
|
+
*
|
|
162
|
+
* An API route handler to handle the auth requests from the client and proxy them to the Neon Auth.
|
|
163
|
+
*
|
|
164
|
+
* @returns A Next.js API handler functions those can be used in a Next.js route.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
*
|
|
168
|
+
* Mount the `authApiHandler` to an API route. Create a route file inside `/api/auth/[...all]/route.ts` directory.
|
|
169
|
+
* And add the following code:
|
|
170
|
+
*
|
|
171
|
+
* ```ts
|
|
172
|
+
*
|
|
173
|
+
* import { authApiHandler } from '@neondatabase/auth/next';
|
|
174
|
+
*
|
|
175
|
+
* export const { GET, POST } = authApiHandler();
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
*/
|
|
179
|
+
function authApiHandler() {
|
|
180
|
+
const baseURL = process.env.NEON_AUTH_BASE_URL;
|
|
181
|
+
if (!baseURL) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
|
|
97
182
|
const handler = async (request, { params }) => {
|
|
98
183
|
return await handleAuthResponse(await handleAuthRequest(baseURL, request, (await params).path.join("/")));
|
|
99
184
|
};
|
|
@@ -104,42 +189,85 @@ const toNextJsHandler = (baseUrl) => {
|
|
|
104
189
|
DELETE: handler,
|
|
105
190
|
PATCH: handler
|
|
106
191
|
};
|
|
107
|
-
}
|
|
192
|
+
}
|
|
108
193
|
|
|
109
194
|
//#endregion
|
|
110
195
|
//#region src/next/middleware/oauth.ts
|
|
111
196
|
const needsSessionVerification = (request) => {
|
|
112
197
|
const hasVerifier = request.nextUrl.searchParams.has(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
113
198
|
const hasChallenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
|
|
114
|
-
|
|
115
|
-
return hasVerifier && hasChallenge && !hasSession;
|
|
199
|
+
return hasVerifier && hasChallenge;
|
|
116
200
|
};
|
|
117
|
-
const
|
|
201
|
+
const exchangeOAuthToken = async (request, baseUrl) => {
|
|
118
202
|
const url = request.nextUrl;
|
|
119
203
|
const verifier = url.searchParams.get(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
120
204
|
const challenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
|
|
121
205
|
if (!verifier || !challenge) return null;
|
|
122
|
-
const response = await
|
|
206
|
+
const response = await handleAuthResponse(await handleAuthRequest(baseUrl, new Request(request.url, {
|
|
207
|
+
method: "GET",
|
|
208
|
+
headers: request.headers
|
|
209
|
+
}), "get-session"));
|
|
123
210
|
if (response.ok) {
|
|
124
|
-
const headers = new Headers();
|
|
125
|
-
const cookies = extractResponseCookies(response.headers);
|
|
126
|
-
for (const cookie of cookies) headers.append("Set-Cookie", cookie);
|
|
211
|
+
const headers$1 = new Headers();
|
|
212
|
+
const cookies$1 = extractResponseCookies(response.headers);
|
|
213
|
+
for (const cookie of cookies$1) headers$1.append("Set-Cookie", cookie);
|
|
127
214
|
url.searchParams.delete(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
128
|
-
return NextResponse.redirect(url, { headers });
|
|
215
|
+
return NextResponse.redirect(url, { headers: headers$1 });
|
|
129
216
|
}
|
|
130
217
|
return null;
|
|
131
218
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
219
|
+
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region src/next/env-variables.ts
|
|
222
|
+
const NEON_AUTH_BASE_URL = process.env.NEON_AUTH_BASE_URL;
|
|
223
|
+
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region src/next/auth/session.ts
|
|
226
|
+
/**
|
|
227
|
+
* 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.
|
|
228
|
+
*
|
|
229
|
+
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* import { neonAuth } from "@neondatabase/auth/next"
|
|
234
|
+
*
|
|
235
|
+
* const { session, user } = await neonAuth()
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
const neonAuth = async () => {
|
|
239
|
+
if (!(await headers()).has(NEON_AUTH_HEADER_MIDDLEWARE_NAME)) throw new Error(ERRORS.NEON_AUTH_MIDDLEWARE_NOT_FOUND);
|
|
240
|
+
return await fetchSession();
|
|
138
241
|
};
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
242
|
+
/**
|
|
243
|
+
* A utility function to fetch the session details from the Neon Auth API, if session token is available in cookie.
|
|
244
|
+
*
|
|
245
|
+
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
246
|
+
*/
|
|
247
|
+
const fetchSession = async () => {
|
|
248
|
+
const baseUrl = NEON_AUTH_BASE_URL;
|
|
249
|
+
const requestHeaders = await headers();
|
|
250
|
+
const upstreamURL = getUpstreamURL(baseUrl, "get-session", { originalUrl: new URL("get-session", baseUrl) });
|
|
251
|
+
const response = await fetch(upstreamURL.toString(), {
|
|
252
|
+
method: "GET",
|
|
253
|
+
headers: { Cookie: extractRequestCookies(requestHeaders) }
|
|
254
|
+
});
|
|
255
|
+
const body = await response.json();
|
|
256
|
+
const cookieHeader = response.headers.get("set-cookie");
|
|
257
|
+
if (cookieHeader) {
|
|
258
|
+
const cookieStore = await cookies();
|
|
259
|
+
parseSetCookies(cookieHeader).map((cookie) => {
|
|
260
|
+
cookieStore.set(cookie.name, cookie.value, cookie);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (!response.ok || body === null) return {
|
|
264
|
+
session: null,
|
|
265
|
+
user: null
|
|
266
|
+
};
|
|
267
|
+
return {
|
|
268
|
+
session: body.session,
|
|
269
|
+
user: body.user
|
|
270
|
+
};
|
|
143
271
|
};
|
|
144
272
|
|
|
145
273
|
//#endregion
|
|
@@ -153,27 +281,44 @@ const SKIP_ROUTES = [
|
|
|
153
281
|
"/auth/email-otp",
|
|
154
282
|
"/auth/forgot-password"
|
|
155
283
|
];
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
284
|
+
/**
|
|
285
|
+
* A Next.js middleware to protect routes from unauthenticated requests and refresh the session if required.
|
|
286
|
+
*
|
|
287
|
+
* @param loginUrl - The URL to redirect to when the user is not authenticated.
|
|
288
|
+
* @returns A middleware function that can be used in the Next.js app.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* import { neonAuthMiddleware } from "@neondatabase/auth/next"
|
|
293
|
+
*
|
|
294
|
+
* export default neonAuthMiddleware({
|
|
295
|
+
* loginUrl: '/auth/sign-in',
|
|
296
|
+
* });
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
function neonAuthMiddleware({ loginUrl = "/auth/sign-in" }) {
|
|
300
|
+
const baseUrl = NEON_AUTH_BASE_URL;
|
|
301
|
+
if (!baseUrl) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
|
|
159
302
|
return async (request) => {
|
|
160
303
|
const { pathname } = request.nextUrl;
|
|
161
304
|
if (pathname.startsWith(loginUrl)) return NextResponse.next();
|
|
162
305
|
if (needsSessionVerification(request)) {
|
|
163
|
-
const response = await
|
|
306
|
+
const response = await exchangeOAuthToken(request, baseUrl);
|
|
164
307
|
if (response !== null) return response;
|
|
165
308
|
}
|
|
166
309
|
if (SKIP_ROUTES.some((route) => pathname.startsWith(route))) return NextResponse.next();
|
|
167
|
-
if (
|
|
168
|
-
|
|
310
|
+
if ((await fetchSession()).session === null) return NextResponse.redirect(new URL(loginUrl, request.url));
|
|
311
|
+
const reqHeaders = new Headers(request.headers);
|
|
312
|
+
reqHeaders.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
|
|
313
|
+
return NextResponse.next({ request: { headers: reqHeaders } });
|
|
169
314
|
};
|
|
170
|
-
}
|
|
315
|
+
}
|
|
171
316
|
|
|
172
317
|
//#endregion
|
|
173
318
|
//#region src/next/index.ts
|
|
174
|
-
|
|
319
|
+
function createAuthClient() {
|
|
175
320
|
return createAuthClient$1(void 0, { adapter: BetterAuthReactAdapter() });
|
|
176
|
-
}
|
|
321
|
+
}
|
|
177
322
|
|
|
178
323
|
//#endregion
|
|
179
|
-
export { createAuthClient,
|
|
324
|
+
export { authApiHandler, createAuthClient, neonAuth, neonAuthMiddleware };
|
package/dist/react/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { n as dist_exports, r as useTheme, t as NeonAuthUIProvider } from "../ui-
|
|
1
|
+
import { n as dist_exports, r as useTheme, t as NeonAuthUIProvider } from "../ui-BQAaHqx4.mjs";
|
|
2
|
+
import "../adapter-core-BDOw-gBC.mjs";
|
|
2
3
|
import { t as BetterAuthReactAdapter } from "../better-auth-react-adapter-FnBHa2nr.mjs";
|
|
4
|
+
import "../adapters-Dkx0zoMR.mjs";
|
|
3
5
|
|
|
4
6
|
var AcceptInvitationCard = dist_exports.AcceptInvitationCard;
|
|
5
7
|
var AccountSettingsCards = dist_exports.AccountSettingsCards;
|
package/dist/react/ui/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { n as dist_exports, r as useTheme, t as NeonAuthUIProvider } from "../../ui-
|
|
2
|
+
import { n as dist_exports, r as useTheme, t as NeonAuthUIProvider } from "../../ui-BQAaHqx4.mjs";
|
|
3
3
|
|
|
4
4
|
var AcceptInvitationCard = dist_exports.AcceptInvitationCard;
|
|
5
5
|
var AccountSettingsCards = dist_exports.AccountSettingsCards;
|
|
@@ -10,40 +10,25 @@ var __defProp = Object.defineProperty;
|
|
|
10
10
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
11
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
12
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
13
|
-
var __export = (all
|
|
13
|
+
var __export = (all) => {
|
|
14
14
|
let target = {};
|
|
15
|
-
for (var name in all) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
if (symbols) {
|
|
22
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
23
|
-
}
|
|
15
|
+
for (var name in all) __defProp(target, name, {
|
|
16
|
+
get: all[name],
|
|
17
|
+
enumerable: true
|
|
18
|
+
});
|
|
24
19
|
return target;
|
|
25
20
|
};
|
|
26
21
|
var __copyProps = (to, from, except, desc) => {
|
|
27
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
}
|
|
22
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
23
|
+
key = keys[i];
|
|
24
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
25
|
+
get: ((k) => from[k]).bind(null, key),
|
|
26
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
27
|
+
});
|
|
37
28
|
}
|
|
38
29
|
return to;
|
|
39
30
|
};
|
|
40
|
-
var __reExport = (target, mod, secondTarget,
|
|
41
|
-
if (symbols) {
|
|
42
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
43
|
-
secondTarget && __defProp(secondTarget, Symbol.toStringTag, { value: "Module" });
|
|
44
|
-
}
|
|
45
|
-
__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default");
|
|
46
|
-
};
|
|
31
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
47
32
|
|
|
48
33
|
//#endregion
|
|
49
34
|
//#region ../auth-ui/dist/index.mjs
|
package/dist/vanilla/index.mjs
CHANGED
package/package.json
CHANGED