@mikandev/next-discord-auth 1.0.2 → 1.0.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/dist/lib/oauth.js +25 -0
- package/dist/redirect.js +6 -0
- package/dist/server-actions.js +30 -2
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/lib/oauth.js
CHANGED
|
@@ -24,3 +24,28 @@ export const ExchangeCodeForTokens = async (config, code) => {
|
|
|
24
24
|
expiresIn: data.expires_in,
|
|
25
25
|
};
|
|
26
26
|
};
|
|
27
|
+
export const RefreshAccessToken = async (config, refreshToken) => {
|
|
28
|
+
const response = await fetch("https://discord.com/api/oauth2/token", {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: {
|
|
31
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
32
|
+
},
|
|
33
|
+
body: new URLSearchParams({
|
|
34
|
+
client_id: config.clientId,
|
|
35
|
+
client_secret: config.clientSecret,
|
|
36
|
+
grant_type: "refresh_token",
|
|
37
|
+
refresh_token: refreshToken,
|
|
38
|
+
scope: config.scopes.join(" "),
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const error = (await response.json());
|
|
43
|
+
throw new Error(`Failed to refresh access token: ${error.error_description || error.message}`);
|
|
44
|
+
}
|
|
45
|
+
const data = (await response.json());
|
|
46
|
+
return {
|
|
47
|
+
accessToken: data.access_token,
|
|
48
|
+
refreshToken: data.refresh_token || refreshToken,
|
|
49
|
+
expiresIn: data.expires_in,
|
|
50
|
+
};
|
|
51
|
+
};
|
package/dist/redirect.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
|
+
import { redirect } from "next/navigation";
|
|
2
3
|
import { getGlobalConfig } from "./index";
|
|
3
4
|
import { cookies } from "next/headers";
|
|
4
5
|
import { ExchangeCodeForTokens } from "./lib/oauth";
|
|
@@ -30,9 +31,14 @@ export const handleRedirect = async (req) => {
|
|
|
30
31
|
avatar: `https://cdn.discordapp.com/avatars/${userData.id}/${userData.avatar}.png`
|
|
31
32
|
},
|
|
32
33
|
expires: new Date(Date.now() + response.expiresIn * 1000).toISOString(),
|
|
34
|
+
accessToken: response.accessToken,
|
|
35
|
+
refreshToken: response.refreshToken,
|
|
33
36
|
};
|
|
34
37
|
const token = jwt.sign(session, config.jwtSecret, {
|
|
35
38
|
expiresIn: response.expiresIn,
|
|
36
39
|
});
|
|
40
|
+
const redirectUri = cookieStore.get("REDIRECT_AFTER")?.value || "/";
|
|
37
41
|
cookieStore.set("AUTH_SESSION", token, { sameSite: "lax", httpOnly: true, secure: true });
|
|
42
|
+
cookieStore.delete("REDIRECT_AFTER");
|
|
43
|
+
return redirect(redirectUri);
|
|
38
44
|
};
|
package/dist/server-actions.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { headers } from "next/headers";
|
|
2
3
|
import { cookies } from "next/headers";
|
|
3
4
|
import { redirect } from "next/navigation";
|
|
4
5
|
import { getGlobalConfig } from "./index";
|
|
6
|
+
import { RefreshAccessToken } from "./lib/oauth";
|
|
5
7
|
import jwt from "jsonwebtoken";
|
|
6
8
|
export const getSession = async () => {
|
|
7
9
|
const config = getGlobalConfig();
|
|
@@ -10,16 +12,42 @@ export const getSession = async () => {
|
|
|
10
12
|
if (!token)
|
|
11
13
|
return null;
|
|
12
14
|
try {
|
|
13
|
-
|
|
15
|
+
const session = jwt.verify(token, config.jwtSecret);
|
|
16
|
+
if (session.expires) {
|
|
17
|
+
const expiresAt = new Date(session.expires);
|
|
18
|
+
if (expiresAt < new Date()) {
|
|
19
|
+
cookieStore.delete("AUTH_SESSION");
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const timeUntilExpiration = expiresAt.getTime() - Date.now();
|
|
24
|
+
if (timeUntilExpiration < 5 * 60 * 1000) { // less than 5 minutes
|
|
25
|
+
const refreshedSession = await RefreshAccessToken(config, session.refreshToken || "");
|
|
26
|
+
if (refreshedSession) {
|
|
27
|
+
session.accessToken = refreshedSession.accessToken;
|
|
28
|
+
session.refreshToken = refreshedSession.refreshToken;
|
|
29
|
+
session.expires = new Date(Date.now() + refreshedSession.expiresIn * 1000).toISOString();
|
|
30
|
+
const newToken = jwt.sign(session, config.jwtSecret);
|
|
31
|
+
cookieStore.set("AUTH_SESSION", newToken, { sameSite: "lax", httpOnly: true, secure: true });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return session;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
14
38
|
}
|
|
15
39
|
catch (error) {
|
|
16
40
|
console.error("Invalid token:", error);
|
|
17
41
|
return null;
|
|
18
42
|
}
|
|
19
43
|
};
|
|
20
|
-
export const signIn = async () => {
|
|
44
|
+
export const signIn = async (redirectTo) => {
|
|
21
45
|
const config = getGlobalConfig();
|
|
22
46
|
const session = await getSession();
|
|
47
|
+
const cookieStore = await cookies();
|
|
48
|
+
const headersList = await headers();
|
|
49
|
+
const redirectUri = redirectTo ?? headersList.get("Referer") ?? "/";
|
|
50
|
+
await cookieStore.set("REDIRECT_AFTER", redirectUri, { sameSite: "lax", httpOnly: true, secure: true });
|
|
23
51
|
if (session) {
|
|
24
52
|
return NextResponse.json({ message: "Already signed in" }, { status: 200 });
|
|
25
53
|
}
|
package/dist/types/index.d.ts
CHANGED