@next-nest-auth/nextauth 0.2.0 → 0.2.2
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/dist/src/auth.d.ts +27 -0
- package/dist/src/auth.js +187 -0
- package/dist/src/auth.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +50 -50
- package/src/auth.ts +184 -186
package/package.json
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
2
|
+
"name": "@next-nest-auth/nextauth",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "tsc -w",
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"nextjs",
|
|
12
|
+
"authentication",
|
|
13
|
+
"nextauth",
|
|
14
|
+
"auth",
|
|
15
|
+
"jwt",
|
|
16
|
+
"token authentication",
|
|
17
|
+
"refresh tokens",
|
|
18
|
+
"secure authentication",
|
|
19
|
+
"session management",
|
|
20
|
+
"nestjs integration",
|
|
21
|
+
"nextjs authentication",
|
|
22
|
+
"nextjs auth",
|
|
23
|
+
"cookie authentication",
|
|
24
|
+
"login",
|
|
25
|
+
"multi-provider authentication",
|
|
26
|
+
"nextjs login",
|
|
27
|
+
"user authentication"
|
|
28
|
+
],
|
|
29
|
+
"author": "Md Shafkat Hussain Tanvir <tanvir0604@gmail.com>",
|
|
30
|
+
"repository": "https://github.com/tanvir0604/nextauth",
|
|
31
|
+
"bugs": "https://github.com/tanvir0604/nextauth/issues",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"type": "commonjs",
|
|
34
|
+
"description": "NextAuth is a frontend authentication package designed for Next.js applications, providing easy integration with NestJS-based backends. It supports login, session management, and token handling (including JWT and refresh tokens) to ensure secure user authentication. With customizable authentication flows and compatibility with multiple providers, NextAuth enables seamless integration between NestJS and Next.js apps.",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"axios": "^1.13.2",
|
|
37
|
+
"js-cookie": "^3.0.5",
|
|
38
|
+
"jsonwebtoken": "^9.0.3",
|
|
39
|
+
"jwt-decode": "^4.0.0",
|
|
40
|
+
"next": "^16.1.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/js-cookie": "^3.0.6",
|
|
44
|
+
"@types/node": "^25.0.3",
|
|
45
|
+
"@types/react": "^19.2.7",
|
|
46
|
+
"typescript": "^5.9.3"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"dist/",
|
|
50
|
+
"src/"
|
|
51
|
+
]
|
|
52
52
|
}
|
package/src/auth.ts
CHANGED
|
@@ -6,229 +6,227 @@ import { NextRequest, NextResponse } from "next/server";
|
|
|
6
6
|
const API_URL = process.env.API_BASE_URL || process.env.NEXT_PUBLIC_API_URL;
|
|
7
7
|
|
|
8
8
|
interface TokenResponse {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
accessToken: string;
|
|
10
|
+
refreshToken: string;
|
|
11
|
+
accessTokenExpiresIn: string;
|
|
12
|
+
refreshTokenExpiresIn: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
interface User {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
sub: string;
|
|
17
|
+
name: string;
|
|
18
|
+
email: string;
|
|
19
|
+
mobile: string;
|
|
20
|
+
role: string;
|
|
21
|
+
pic: string;
|
|
22
|
+
macId: string;
|
|
23
|
+
[key: string]: any;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const convertToSeconds = (expiresIn: string) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
27
|
+
const match = expiresIn.match(/(\d+)([mhd])/);
|
|
28
|
+
if (!match) return 0;
|
|
29
|
+
|
|
30
|
+
const value = parseInt(match[1], 10);
|
|
31
|
+
const unit = match[2];
|
|
32
|
+
|
|
33
|
+
switch (unit) {
|
|
34
|
+
case "m":
|
|
35
|
+
return value * 60;
|
|
36
|
+
case "h":
|
|
37
|
+
return value * 60 * 60;
|
|
38
|
+
case "d":
|
|
39
|
+
return value * 60 * 60 * 24;
|
|
40
|
+
default:
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
export async function refreshToken(req: NextRequest) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const res = NextResponse.next();
|
|
65
|
-
res.cookies.set("access_token", response.accessToken, {
|
|
66
|
-
httpOnly: true,
|
|
67
|
-
secure: process.env.NODE_ENV === "production",
|
|
68
|
-
sameSite: "strict",
|
|
69
|
-
path: "/",
|
|
70
|
-
maxAge: convertToSeconds(response.accessTokenExpiresIn ?? ""),
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
if (!process.env.AUTOEXPIRE_REFRESH_TOKEN) {
|
|
74
|
-
if (process.env.NODE_ENV === "development") {
|
|
75
|
-
console.log(
|
|
76
|
-
"refresh token is not expired and updating expires in",
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
res.cookies.set("refresh_token", response.refreshToken, {
|
|
80
|
-
httpOnly: true,
|
|
81
|
-
secure: process.env.NODE_ENV === "production",
|
|
82
|
-
sameSite: "strict",
|
|
83
|
-
path: "/",
|
|
84
|
-
maxAge: convertToSeconds(response.refreshTokenExpiresIn ?? ""),
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return res;
|
|
89
|
-
} catch (error) {
|
|
90
|
-
throw new Error(error);
|
|
46
|
+
try {
|
|
47
|
+
const refreshToken = req.cookies.get("refresh_token")?.value;
|
|
48
|
+
if (!refreshToken) {
|
|
49
|
+
throw new Error("Token refresh failed, no refresh token");
|
|
50
|
+
}
|
|
51
|
+
const response: TokenResponse = await post(
|
|
52
|
+
`${API_URL}/nestauth/refresh-token`,
|
|
53
|
+
{
|
|
54
|
+
refresh_token: refreshToken,
|
|
55
|
+
},
|
|
56
|
+
{},
|
|
57
|
+
false,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
if (!response || !response.accessToken || !response.refreshToken) {
|
|
61
|
+
throw new Error("Token refresh failed, no response from api");
|
|
91
62
|
}
|
|
63
|
+
|
|
64
|
+
const res = NextResponse.next();
|
|
65
|
+
res.cookies.set("access_token", response.accessToken, {
|
|
66
|
+
httpOnly: true,
|
|
67
|
+
secure: true,
|
|
68
|
+
sameSite: "lax" as const,
|
|
69
|
+
path: "/",
|
|
70
|
+
maxAge: convertToSeconds(response.accessTokenExpiresIn ?? ""),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (!process.env.AUTOEXPIRE_REFRESH_TOKEN) {
|
|
74
|
+
if (process.env.NODE_ENV === "development") {
|
|
75
|
+
console.log("refresh token is not expired and updating expires in");
|
|
76
|
+
}
|
|
77
|
+
res.cookies.set("refresh_token", response.refreshToken, {
|
|
78
|
+
httpOnly: true,
|
|
79
|
+
secure: true,
|
|
80
|
+
sameSite: "lax" as const,
|
|
81
|
+
path: "/",
|
|
82
|
+
maxAge: convertToSeconds(response.refreshTokenExpiresIn ?? ""),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return res;
|
|
87
|
+
} catch (error: any) {
|
|
88
|
+
throw new Error(error?.message ?? "Token refresh failed");
|
|
89
|
+
}
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
export async function authenticate(params: any) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
const cookieStore = await cookies();
|
|
120
|
-
cookieStore.set("access_token", response.accessToken, {
|
|
121
|
-
httpOnly: true,
|
|
122
|
-
secure: process.env.NODE_ENV === "production",
|
|
123
|
-
sameSite: "strict",
|
|
124
|
-
path: "/",
|
|
125
|
-
maxAge: convertToSeconds(response.accessTokenExpiresIn ?? ""),
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
cookieStore.set("refresh_token", response.refreshToken, {
|
|
129
|
-
httpOnly: true,
|
|
130
|
-
secure: process.env.NODE_ENV === "production",
|
|
131
|
-
sameSite: "strict",
|
|
132
|
-
path: "/",
|
|
133
|
-
maxAge: convertToSeconds(response.refreshTokenExpiresIn ?? ""),
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
return response;
|
|
137
|
-
} catch (error) {
|
|
138
|
-
// console.log(error);
|
|
139
|
-
throw new Error(error);
|
|
93
|
+
try {
|
|
94
|
+
const response: TokenResponse = await post(
|
|
95
|
+
`${API_URL}/nestauth/login`,
|
|
96
|
+
params,
|
|
97
|
+
{},
|
|
98
|
+
false,
|
|
99
|
+
);
|
|
100
|
+
if (
|
|
101
|
+
!response ||
|
|
102
|
+
!response.accessToken ||
|
|
103
|
+
!response.refreshToken ||
|
|
104
|
+
!response.accessTokenExpiresIn ||
|
|
105
|
+
!response.refreshTokenExpiresIn
|
|
106
|
+
) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
"Login failed" +
|
|
109
|
+
" API URL: " +
|
|
110
|
+
API_URL +
|
|
111
|
+
" params: " +
|
|
112
|
+
JSON.stringify(params) +
|
|
113
|
+
" response: " +
|
|
114
|
+
JSON.stringify(response),
|
|
115
|
+
);
|
|
140
116
|
}
|
|
117
|
+
const cookieStore = await cookies();
|
|
118
|
+
cookieStore.set("access_token", response.accessToken, {
|
|
119
|
+
httpOnly: true,
|
|
120
|
+
secure: process.env.NODE_ENV === "production",
|
|
121
|
+
sameSite: "lax",
|
|
122
|
+
path: "/",
|
|
123
|
+
maxAge: convertToSeconds(response.accessTokenExpiresIn ?? ""),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
cookieStore.set("refresh_token", response.refreshToken, {
|
|
127
|
+
httpOnly: true,
|
|
128
|
+
secure: process.env.NODE_ENV === "production",
|
|
129
|
+
sameSite: "lax",
|
|
130
|
+
path: "/",
|
|
131
|
+
maxAge: convertToSeconds(response.refreshTokenExpiresIn ?? ""),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return response;
|
|
135
|
+
} catch (error: any) {
|
|
136
|
+
// console.log(error);
|
|
137
|
+
throw new Error(error?.message ?? "Login failed");
|
|
138
|
+
}
|
|
141
139
|
}
|
|
142
140
|
|
|
143
141
|
export async function getAccessToken() {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
const cookieStore = await cookies();
|
|
143
|
+
const access_token = cookieStore.get("access_token")?.value;
|
|
144
|
+
return access_token ?? null;
|
|
147
145
|
}
|
|
148
146
|
|
|
149
147
|
export async function getRefreshToken() {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
const cookieStore = await cookies();
|
|
149
|
+
const refresh_token = cookieStore.get("refresh_token")?.value;
|
|
150
|
+
return refresh_token ?? null;
|
|
153
151
|
}
|
|
154
152
|
|
|
155
153
|
export async function checkAuth() {
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
const accessToken = await getAccessToken();
|
|
155
|
+
return !!accessToken;
|
|
158
156
|
}
|
|
159
157
|
|
|
160
158
|
export async function getUserInfo() {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
159
|
+
const accessToken = await getAccessToken();
|
|
160
|
+
if (!accessToken) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const decoded = jwtDecode(accessToken) as User;
|
|
165
|
+
return decoded;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
171
169
|
}
|
|
172
170
|
|
|
173
171
|
export async function logout() {
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
(await cookies()).delete("access_token");
|
|
173
|
+
(await cookies()).delete("refresh_token");
|
|
176
174
|
}
|
|
177
175
|
|
|
178
176
|
export async function get(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
url: string,
|
|
178
|
+
params: any = {},
|
|
179
|
+
headers: any = {},
|
|
180
|
+
secured = true,
|
|
183
181
|
) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
return null;
|
|
203
|
-
} catch (error) {
|
|
204
|
-
return error;
|
|
182
|
+
const headerData: Record<string, string> = {
|
|
183
|
+
Authorization: "",
|
|
184
|
+
...headers,
|
|
185
|
+
};
|
|
186
|
+
if (secured) {
|
|
187
|
+
const accessToken = await getAccessToken();
|
|
188
|
+
headerData.Authorization = "Bearer " + accessToken;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
const response = await axios.get(url, {
|
|
193
|
+
headers: headerData,
|
|
194
|
+
params: params,
|
|
195
|
+
withCredentials: true,
|
|
196
|
+
});
|
|
197
|
+
if (response.status === 200 || response.status === 201) {
|
|
198
|
+
return response.data;
|
|
205
199
|
}
|
|
200
|
+
return null;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
return error;
|
|
203
|
+
}
|
|
206
204
|
}
|
|
207
205
|
|
|
208
206
|
export async function post(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
207
|
+
url: string,
|
|
208
|
+
data: any = {},
|
|
209
|
+
headers: any = {},
|
|
210
|
+
secured = true,
|
|
213
211
|
) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
return null;
|
|
231
|
-
} catch (error) {
|
|
232
|
-
return error;
|
|
212
|
+
const headerData: Record<string, string> = {
|
|
213
|
+
Authorization: "",
|
|
214
|
+
...headers,
|
|
215
|
+
};
|
|
216
|
+
if (secured) {
|
|
217
|
+
const accessToken = await getAccessToken();
|
|
218
|
+
headerData.Authorization = "Bearer " + accessToken;
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
const response = await axios.post(url, data, {
|
|
222
|
+
headers: headerData,
|
|
223
|
+
withCredentials: true,
|
|
224
|
+
});
|
|
225
|
+
if (response.status === 200 || response.status === 201) {
|
|
226
|
+
return response.data;
|
|
233
227
|
}
|
|
228
|
+
return null;
|
|
229
|
+
} catch (error) {
|
|
230
|
+
return error;
|
|
231
|
+
}
|
|
234
232
|
}
|