@neondatabase/auth 0.1.0-beta.14 → 0.1.0-beta.16
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-BPv4mLT0.mjs → adapter-core-BQ6ga1zK.mjs} +119 -20
- package/dist/{adapter-core-9F3bfyWA.d.mts → adapter-core-DYWYECKK.d.mts} +16 -8
- package/dist/{better-auth-react-adapter-BkeuhSFt.mjs → better-auth-react-adapter-BLKXYcWM.mjs} +1 -1
- package/dist/{supabase-adapter-_2wgvfZ3.d.mts → better-auth-react-adapter-tKs79AwE.d.mts} +204 -290
- package/dist/constants-2bpp2_-f.mjs +30 -0
- package/dist/index-B6dAIdkW.d.mts +100 -0
- package/dist/index.d.mts +5 -104
- package/dist/index.mjs +2 -1
- package/dist/middleware-DXwLKcbA.mjs +305 -0
- package/dist/neon-auth-B_otuPjh.d.mts +105 -0
- package/dist/{neon-auth-BhLZg9v8.mjs → neon-auth-ClDZNB9a.mjs} +1 -1
- package/dist/next/index.d.mts +8 -104
- package/dist/next/index.mjs +4 -310
- package/dist/next/server/index.d.mts +340 -0
- package/dist/next/server/index.mjs +432 -0
- package/dist/react/adapters/index.d.mts +4 -3
- package/dist/react/adapters/index.mjs +2 -1
- package/dist/react/index.d.mts +5 -4
- package/dist/react/index.mjs +4 -4
- 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-rl2coLdb.mjs → supabase-adapter-Bl576usk.mjs} +2 -1
- package/dist/{better-auth-react-adapter-BYvAsZdj.d.mts → supabase-adapter-DtT0d6It.d.mts} +147 -61
- package/dist/types/index.d.mts +3 -7
- package/dist/ui/css.css +1 -1
- package/dist/ui/theme.css +1 -1
- package/dist/ui-DLtIc4wi.mjs +4 -0
- package/dist/vanilla/adapters/index.d.mts +4 -3
- package/dist/vanilla/adapters/index.mjs +2 -1
- package/dist/vanilla/index.d.mts +4 -3
- package/dist/vanilla/index.mjs +2 -1
- package/llms.txt +157 -0
- package/package.json +7 -2
- package/dist/chunk-5DLVHPZS-Bxj7snpZ-EhdAQJMu.mjs +0 -533
- package/dist/ui-C1IRQzLY.mjs +0 -9449
- /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-CE4hLv9E.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
package/dist/next/index.d.mts
CHANGED
|
@@ -1,108 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../better-auth-types-Kq3kGuiz.mjs";
|
|
2
|
+
import { n as neonAuthMiddleware, r as authApiHandler, t as neonAuth } from "../index-B6dAIdkW.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 { NextRequest, NextResponse } from "next/server";
|
|
6
6
|
import * as better_auth0 from "better-auth";
|
|
7
7
|
import * as _better_fetch_fetch0 from "@better-fetch/fetch";
|
|
8
8
|
import * as nanostores0 from "nanostores";
|
|
9
9
|
|
|
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
10
|
//#region src/next/index.d.ts
|
|
107
11
|
declare function createAuthClient(): {
|
|
108
12
|
useActiveOrganization: () => {
|
|
@@ -1132,7 +1036,7 @@ declare function createAuthClient(): {
|
|
|
1132
1036
|
permission: {
|
|
1133
1037
|
readonly organization?: ("delete" | "update")[] | undefined;
|
|
1134
1038
|
readonly member?: ("delete" | "create" | "update")[] | undefined;
|
|
1135
|
-
readonly invitation?: ("
|
|
1039
|
+
readonly invitation?: ("cancel" | "create")[] | undefined;
|
|
1136
1040
|
readonly team?: ("delete" | "create" | "update")[] | undefined;
|
|
1137
1041
|
readonly ac?: ("delete" | "create" | "update" | "read")[] | undefined;
|
|
1138
1042
|
};
|
|
@@ -1141,7 +1045,7 @@ declare function createAuthClient(): {
|
|
|
1141
1045
|
permissions: {
|
|
1142
1046
|
readonly organization?: ("delete" | "update")[] | undefined;
|
|
1143
1047
|
readonly member?: ("delete" | "create" | "update")[] | undefined;
|
|
1144
|
-
readonly invitation?: ("
|
|
1048
|
+
readonly invitation?: ("cancel" | "create")[] | undefined;
|
|
1145
1049
|
readonly team?: ("delete" | "create" | "update")[] | undefined;
|
|
1146
1050
|
readonly ac?: ("delete" | "create" | "update" | "read")[] | undefined;
|
|
1147
1051
|
};
|
|
@@ -1152,7 +1056,7 @@ declare function createAuthClient(): {
|
|
|
1152
1056
|
permission: {
|
|
1153
1057
|
readonly organization?: ("delete" | "update")[] | undefined;
|
|
1154
1058
|
readonly member?: ("delete" | "create" | "update")[] | undefined;
|
|
1155
|
-
readonly invitation?: ("
|
|
1059
|
+
readonly invitation?: ("cancel" | "create")[] | undefined;
|
|
1156
1060
|
readonly team?: ("delete" | "create" | "update")[] | undefined;
|
|
1157
1061
|
readonly ac?: ("delete" | "create" | "update" | "read")[] | undefined;
|
|
1158
1062
|
};
|
|
@@ -1161,7 +1065,7 @@ declare function createAuthClient(): {
|
|
|
1161
1065
|
permissions: {
|
|
1162
1066
|
readonly organization?: ("delete" | "update")[] | undefined;
|
|
1163
1067
|
readonly member?: ("delete" | "create" | "update")[] | undefined;
|
|
1164
|
-
readonly invitation?: ("
|
|
1068
|
+
readonly invitation?: ("cancel" | "create")[] | undefined;
|
|
1165
1069
|
readonly team?: ("delete" | "create" | "update")[] | undefined;
|
|
1166
1070
|
readonly ac?: ("delete" | "create" | "update" | "read")[] | undefined;
|
|
1167
1071
|
};
|
|
@@ -1972,7 +1876,7 @@ declare function createAuthClient(): {
|
|
|
1972
1876
|
permission: {
|
|
1973
1877
|
readonly organization?: ("delete" | "update")[] | undefined;
|
|
1974
1878
|
readonly member?: ("delete" | "create" | "update")[] | undefined;
|
|
1975
|
-
readonly invitation?: ("
|
|
1879
|
+
readonly invitation?: ("cancel" | "create")[] | undefined;
|
|
1976
1880
|
readonly team?: ("delete" | "create" | "update")[] | undefined;
|
|
1977
1881
|
readonly ac?: ("delete" | "create" | "update" | "read")[] | undefined;
|
|
1978
1882
|
};
|
|
@@ -1981,7 +1885,7 @@ declare function createAuthClient(): {
|
|
|
1981
1885
|
permissions: {
|
|
1982
1886
|
readonly organization?: ("delete" | "update")[] | undefined;
|
|
1983
1887
|
readonly member?: ("delete" | "create" | "update")[] | undefined;
|
|
1984
|
-
readonly invitation?: ("
|
|
1888
|
+
readonly invitation?: ("cancel" | "create")[] | undefined;
|
|
1985
1889
|
readonly team?: ("delete" | "create" | "update")[] | undefined;
|
|
1986
1890
|
readonly ac?: ("delete" | "create" | "update" | "read")[] | undefined;
|
|
1987
1891
|
};
|
package/dist/next/index.mjs
CHANGED
|
@@ -1,314 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
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, r as authApiHandler, t as neonAuthMiddleware } from "../middleware-DXwLKcbA.mjs";
|
|
6
5
|
|
|
7
|
-
//#region src/next/errors.ts
|
|
8
|
-
const ERRORS = { 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" };
|
|
9
|
-
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/next/constants.ts
|
|
12
|
-
const NEON_AUTH_COOKIE_PREFIX = "__Secure-neon-auth";
|
|
13
|
-
const NEON_AUTH_SESSION_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_token`;
|
|
14
|
-
const NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME = `${NEON_AUTH_COOKIE_PREFIX}.session_challange`;
|
|
15
|
-
/** Name of the session verifier parameter in the URL, used for the OAUTH flow */
|
|
16
|
-
const NEON_AUTH_SESSION_VERIFIER_PARAM_NAME = "neon_auth_session_verifier";
|
|
17
|
-
const NEON_AUTH_HEADER_MIDDLEWARE_NAME = "X-Neon-Auth-Next-Middleware";
|
|
18
|
-
|
|
19
|
-
//#endregion
|
|
20
|
-
//#region src/next/auth/cookies.ts
|
|
21
|
-
/**
|
|
22
|
-
* Extract the Neon Auth cookies from the request headers that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
23
|
-
*
|
|
24
|
-
* @param headers - The request headers.
|
|
25
|
-
* @returns The cookie string with all Neon Auth cookies.
|
|
26
|
-
*/
|
|
27
|
-
function extractRequestCookies(headers$1) {
|
|
28
|
-
const cookieHeader = headers$1.get("cookie");
|
|
29
|
-
if (!cookieHeader) return "";
|
|
30
|
-
const parsedCookies = parseCookies(cookieHeader);
|
|
31
|
-
const result = [];
|
|
32
|
-
for (const [name, value] of parsedCookies.entries()) if (name.startsWith(NEON_AUTH_COOKIE_PREFIX)) result.push({
|
|
33
|
-
name,
|
|
34
|
-
value
|
|
35
|
-
});
|
|
36
|
-
return result.map((cookie) => cookie.name + "=" + cookie.value).join("; ");
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Extract the Neon Auth cookies from the response headers that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
40
|
-
*
|
|
41
|
-
* @param headers - The response headers.
|
|
42
|
-
* @returns The cookies that starts with the NEON_AUTH_COOKIE_PREFIX.
|
|
43
|
-
*/
|
|
44
|
-
const extractResponseCookies = (headers$1) => {
|
|
45
|
-
const cookieHeader = headers$1.get("set-cookie");
|
|
46
|
-
if (!cookieHeader) return [];
|
|
47
|
-
return cookieHeader.split(", ").map((c) => c.trim());
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
* Parses the `set-cookie` header from Neon Auth response into the list of ResponseCookies,
|
|
52
|
-
* compatible with NextCookies.
|
|
53
|
-
*
|
|
54
|
-
* @param cookies - The `set-cookie` header from Neon Auth response.
|
|
55
|
-
* @returns The list of ResponseCookies.
|
|
56
|
-
*/
|
|
57
|
-
const parseSetCookies = (cookies$1) => {
|
|
58
|
-
const parsedCookies = parseSetCookieHeader(cookies$1);
|
|
59
|
-
const responseCookies = [];
|
|
60
|
-
for (const entry of parsedCookies.entries()) {
|
|
61
|
-
const [name, parsedCookie] = entry;
|
|
62
|
-
responseCookies.push({
|
|
63
|
-
name,
|
|
64
|
-
value: decodeURIComponent(parsedCookie.value),
|
|
65
|
-
path: parsedCookie.path,
|
|
66
|
-
maxAge: parsedCookie["max-age"] ?? parsedCookie.maxAge,
|
|
67
|
-
httpOnly: parsedCookie.httponly ?? true,
|
|
68
|
-
secure: parsedCookie.secure ?? true,
|
|
69
|
-
sameSite: parsedCookie.samesite ?? "none",
|
|
70
|
-
partitioned: parsedCookie.partitioned
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
return responseCookies;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
//#endregion
|
|
77
|
-
//#region src/next/handler/request.ts
|
|
78
|
-
const PROXY_HEADERS = [
|
|
79
|
-
"user-agent",
|
|
80
|
-
"authorization",
|
|
81
|
-
"referer",
|
|
82
|
-
"content-type"
|
|
83
|
-
];
|
|
84
|
-
const handleAuthRequest = async (baseUrl, request, path) => {
|
|
85
|
-
const headers$1 = prepareRequestHeaders(request);
|
|
86
|
-
const body = await parseRequestBody(request);
|
|
87
|
-
try {
|
|
88
|
-
const upstreamURL = getUpstreamURL(baseUrl, path, { originalUrl: new URL(request.url) });
|
|
89
|
-
return await fetch(upstreamURL.toString(), {
|
|
90
|
-
method: request.method,
|
|
91
|
-
headers: headers$1,
|
|
92
|
-
body
|
|
93
|
-
});
|
|
94
|
-
} catch (error) {
|
|
95
|
-
const message = error instanceof Error ? error.message : "Internal Server Error";
|
|
96
|
-
console.error(`[AuthError] ${message}`, error);
|
|
97
|
-
return new Response(`[AuthError] ${message}`, { status: 500 });
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
const getUpstreamURL = (baseUrl, path, { originalUrl }) => {
|
|
101
|
-
const url = new URL(`${baseUrl}/${path}`);
|
|
102
|
-
if (originalUrl) {
|
|
103
|
-
url.search = originalUrl.search;
|
|
104
|
-
return url;
|
|
105
|
-
}
|
|
106
|
-
return url;
|
|
107
|
-
};
|
|
108
|
-
const prepareRequestHeaders = (request) => {
|
|
109
|
-
const headers$1 = new Headers();
|
|
110
|
-
for (const header of PROXY_HEADERS) if (request.headers.get(header)) headers$1.set(header, request.headers.get(header));
|
|
111
|
-
headers$1.set("Origin", getOrigin(request));
|
|
112
|
-
headers$1.set("Cookie", extractRequestCookies(request.headers));
|
|
113
|
-
headers$1.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
|
|
114
|
-
return headers$1;
|
|
115
|
-
};
|
|
116
|
-
const getOrigin = (request) => {
|
|
117
|
-
return request.headers.get("origin") || request.headers.get("referer")?.split("/").slice(0, 3).join("/") || new URL(request.url).origin;
|
|
118
|
-
};
|
|
119
|
-
const parseRequestBody = async (request) => {
|
|
120
|
-
if (request.body) return request.text();
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
//#endregion
|
|
124
|
-
//#region src/next/handler/response.ts
|
|
125
|
-
const RESPONSE_HEADERS_ALLOWLIST = [
|
|
126
|
-
"content-type",
|
|
127
|
-
"content-length",
|
|
128
|
-
"content-encoding",
|
|
129
|
-
"transfer-encoding",
|
|
130
|
-
"connection",
|
|
131
|
-
"date",
|
|
132
|
-
"set-cookie",
|
|
133
|
-
"set-auth-jwt",
|
|
134
|
-
"set-auth-token",
|
|
135
|
-
"x-neon-ret-request-id"
|
|
136
|
-
];
|
|
137
|
-
const handleAuthResponse = async (response) => {
|
|
138
|
-
return new Response(response.body, {
|
|
139
|
-
status: response.status,
|
|
140
|
-
statusText: response.statusText,
|
|
141
|
-
headers: prepareResponseHeaders(response)
|
|
142
|
-
});
|
|
143
|
-
};
|
|
144
|
-
const prepareResponseHeaders = (response) => {
|
|
145
|
-
const headers$1 = new Headers();
|
|
146
|
-
for (const header of RESPONSE_HEADERS_ALLOWLIST) {
|
|
147
|
-
const value = response.headers.get(header);
|
|
148
|
-
if (value) headers$1.set(header, value);
|
|
149
|
-
}
|
|
150
|
-
return headers$1;
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
//#endregion
|
|
154
|
-
//#region src/next/handler/index.ts
|
|
155
|
-
/**
|
|
156
|
-
*
|
|
157
|
-
* An API route handler to handle the auth requests from the client and proxy them to the Neon Auth.
|
|
158
|
-
*
|
|
159
|
-
* @returns A Next.js API handler functions those can be used in a Next.js route.
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
*
|
|
163
|
-
* Mount the `authApiHandler` to an API route. Create a route file inside `/api/auth/[...all]/route.ts` directory.
|
|
164
|
-
* And add the following code:
|
|
165
|
-
*
|
|
166
|
-
* ```ts
|
|
167
|
-
*
|
|
168
|
-
* import { authApiHandler } from '@neondatabase/auth/next';
|
|
169
|
-
*
|
|
170
|
-
* export const { GET, POST } = authApiHandler();
|
|
171
|
-
* ```
|
|
172
|
-
*
|
|
173
|
-
*/
|
|
174
|
-
function authApiHandler() {
|
|
175
|
-
const baseURL = process.env.NEON_AUTH_BASE_URL;
|
|
176
|
-
if (!baseURL) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
|
|
177
|
-
const handler = async (request, { params }) => {
|
|
178
|
-
return await handleAuthResponse(await handleAuthRequest(baseURL, request, (await params).path.join("/")));
|
|
179
|
-
};
|
|
180
|
-
return {
|
|
181
|
-
GET: handler,
|
|
182
|
-
POST: handler,
|
|
183
|
-
PUT: handler,
|
|
184
|
-
DELETE: handler,
|
|
185
|
-
PATCH: handler
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
//#endregion
|
|
190
|
-
//#region src/next/middleware/oauth.ts
|
|
191
|
-
const needsSessionVerification = (request) => {
|
|
192
|
-
const hasVerifier = request.nextUrl.searchParams.has(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
193
|
-
const hasChallenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
|
|
194
|
-
return hasVerifier && hasChallenge;
|
|
195
|
-
};
|
|
196
|
-
const exchangeOAuthToken = async (request, baseUrl) => {
|
|
197
|
-
const url = request.nextUrl;
|
|
198
|
-
const verifier = url.searchParams.get(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
199
|
-
const challenge = request.cookies.get(NEON_AUTH_SESSION_CHALLENGE_COOKIE_NAME);
|
|
200
|
-
if (!verifier || !challenge) return null;
|
|
201
|
-
const response = await handleAuthResponse(await handleAuthRequest(baseUrl, new Request(request.url, {
|
|
202
|
-
method: "GET",
|
|
203
|
-
headers: request.headers
|
|
204
|
-
}), "get-session"));
|
|
205
|
-
if (response.ok) {
|
|
206
|
-
const headers$1 = new Headers();
|
|
207
|
-
const cookies$1 = extractResponseCookies(response.headers);
|
|
208
|
-
for (const cookie of cookies$1) headers$1.append("Set-Cookie", cookie);
|
|
209
|
-
url.searchParams.delete(NEON_AUTH_SESSION_VERIFIER_PARAM_NAME);
|
|
210
|
-
return NextResponse.redirect(url, { headers: headers$1 });
|
|
211
|
-
}
|
|
212
|
-
return null;
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
//#endregion
|
|
216
|
-
//#region src/next/env-variables.ts
|
|
217
|
-
const NEON_AUTH_BASE_URL = process.env.NEON_AUTH_BASE_URL;
|
|
218
|
-
|
|
219
|
-
//#endregion
|
|
220
|
-
//#region src/next/auth/session.ts
|
|
221
|
-
/**
|
|
222
|
-
* 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.
|
|
223
|
-
*
|
|
224
|
-
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
225
|
-
*
|
|
226
|
-
* @example
|
|
227
|
-
* ```ts
|
|
228
|
-
* import { neonAuth } from "@neondatabase/auth/next"
|
|
229
|
-
*
|
|
230
|
-
* const { session, user } = await neonAuth()
|
|
231
|
-
* ```
|
|
232
|
-
*/
|
|
233
|
-
const neonAuth = async () => {
|
|
234
|
-
return await fetchSession();
|
|
235
|
-
};
|
|
236
|
-
/**
|
|
237
|
-
* A utility function to fetch the session details from the Neon Auth API, if session token is available in cookie.
|
|
238
|
-
*
|
|
239
|
-
* @returns - `{ session: Session, user: User }` | `{ session: null, user: null}`.
|
|
240
|
-
*/
|
|
241
|
-
const fetchSession = async () => {
|
|
242
|
-
const baseUrl = NEON_AUTH_BASE_URL;
|
|
243
|
-
const requestHeaders = await headers();
|
|
244
|
-
const upstreamURL = getUpstreamURL(baseUrl, "get-session", { originalUrl: new URL("get-session", baseUrl) });
|
|
245
|
-
const response = await fetch(upstreamURL.toString(), {
|
|
246
|
-
method: "GET",
|
|
247
|
-
headers: { Cookie: extractRequestCookies(requestHeaders) }
|
|
248
|
-
});
|
|
249
|
-
const body = await response.json();
|
|
250
|
-
const cookieHeader = response.headers.get("set-cookie");
|
|
251
|
-
if (cookieHeader) {
|
|
252
|
-
const cookieStore = await cookies();
|
|
253
|
-
parseSetCookies(cookieHeader).map((cookie) => {
|
|
254
|
-
cookieStore.set(cookie.name, cookie.value, cookie);
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
if (!response.ok || body === null) return {
|
|
258
|
-
session: null,
|
|
259
|
-
user: null
|
|
260
|
-
};
|
|
261
|
-
return {
|
|
262
|
-
session: body.session,
|
|
263
|
-
user: body.user
|
|
264
|
-
};
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
//#endregion
|
|
268
|
-
//#region src/next/middleware/index.ts
|
|
269
|
-
const SKIP_ROUTES = [
|
|
270
|
-
"/api/auth",
|
|
271
|
-
"/auth/callback",
|
|
272
|
-
"/auth/sign-in",
|
|
273
|
-
"/auth/sign-up",
|
|
274
|
-
"/auth/magic-link",
|
|
275
|
-
"/auth/email-otp",
|
|
276
|
-
"/auth/forgot-password"
|
|
277
|
-
];
|
|
278
|
-
/**
|
|
279
|
-
* A Next.js middleware to protect routes from unauthenticated requests and refresh the session if required.
|
|
280
|
-
*
|
|
281
|
-
* @param loginUrl - The URL to redirect to when the user is not authenticated.
|
|
282
|
-
* @returns A middleware function that can be used in the Next.js app.
|
|
283
|
-
*
|
|
284
|
-
* @example
|
|
285
|
-
* ```ts
|
|
286
|
-
* import { neonAuthMiddleware } from "@neondatabase/auth/next"
|
|
287
|
-
*
|
|
288
|
-
* export default neonAuthMiddleware({
|
|
289
|
-
* loginUrl: '/auth/sign-in',
|
|
290
|
-
* });
|
|
291
|
-
* ```
|
|
292
|
-
*/
|
|
293
|
-
function neonAuthMiddleware({ loginUrl = "/auth/sign-in" }) {
|
|
294
|
-
const baseUrl = NEON_AUTH_BASE_URL;
|
|
295
|
-
if (!baseUrl) throw new Error(ERRORS.MISSING_AUTH_BASE_URL);
|
|
296
|
-
return async (request) => {
|
|
297
|
-
const { pathname } = request.nextUrl;
|
|
298
|
-
if (pathname.startsWith(loginUrl)) return NextResponse.next();
|
|
299
|
-
if (needsSessionVerification(request)) {
|
|
300
|
-
const response = await exchangeOAuthToken(request, baseUrl);
|
|
301
|
-
if (response !== null) return response;
|
|
302
|
-
}
|
|
303
|
-
if (SKIP_ROUTES.some((route) => pathname.startsWith(route))) return NextResponse.next();
|
|
304
|
-
if ((await fetchSession()).session === null) return NextResponse.redirect(new URL(loginUrl, request.url));
|
|
305
|
-
const reqHeaders = new Headers(request.headers);
|
|
306
|
-
reqHeaders.set(NEON_AUTH_HEADER_MIDDLEWARE_NAME, "true");
|
|
307
|
-
return NextResponse.next({ request: { headers: reqHeaders } });
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
//#endregion
|
|
312
6
|
//#region src/next/index.ts
|
|
313
7
|
function createAuthClient() {
|
|
314
8
|
return createAuthClient$1(void 0, { adapter: BetterAuthReactAdapter() });
|