next-integrate
Version:
An authentication library for making integrations in your Next.js Web Application
1,380 lines (1,359 loc) • 29.5 kB
JavaScript
// src/index.ts
import { NextRequest } from "next/server";
// src/utils/qs.ts
function qs(obj) {
const params = new URLSearchParams();
Object.keys(obj).forEach((key) => {
const value = obj[key];
if (Array.isArray(value)) {
value.forEach((val) => params.append(key, val));
} else {
params.append(key, value);
}
});
return params.toString();
}
// src/providers/accuranker.ts
function getAccurankerAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://app.accuranker.com/oauth/authorize/?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/accuranker",
...props
})}`;
}
async function getAccurankerAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig({
code,
redirect_uri: base_url + "/api/auth/integration/accuranker",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "accuranker",
...tokens
});
return {
provider: "accuranker",
...tokens
};
}
function getTokenReqConfig(body) {
return {
url: "https://app.accuranker.com/oauth/token/",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/click-up.ts
function getClickUpAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://app.clickup.com/api?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/click-up",
...props
})}`;
}
async function getClickUpAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig2({
code,
redirect_uri: base_url + "/api/auth/integration/click-up",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "click-up",
...tokens
});
return {
provider: "click-up",
...tokens
};
}
function getTokenReqConfig2(body) {
return {
url: "https://api.clickup.com/api/v2/oauth/token",
method: "POST",
headers: {
accept: "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/discord.ts
function getDiscordAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://discord.com/oauth2/authorize?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/discord",
...props
})}`;
}
async function getDiscordAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig3({
code,
redirect_uri: base_url + "/api/auth/integration/discord",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "discord",
...tokens
});
return {
provider: "discord",
...tokens
};
}
function getTokenReqConfig3(body) {
return {
url: "https://discord.com/api/oauth2/token",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/facebook.ts
function getFacebookAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://www.facebook.com/v20.0/dialog/oauth?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/facebook",
...props
})}`;
}
async function getFacebookAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig4({
code,
redirect_uri: base_url + "/api/auth/integration/facebook",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "facebook",
...tokens
});
return {
provider: "facebook",
...tokens
};
}
function getTokenReqConfig4(body) {
return {
url: "https://graph.facebook.com/v20.0/oauth/access_token?",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/github.ts
function getGithubAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://github.com/login/oauth/authorize?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/github",
...props
})}`;
}
async function getGithubAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig5({
code,
redirect_uri: base_url + "/api/auth/integration/github",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "github",
...tokens
});
return {
provider: "github",
...tokens
};
}
function getTokenReqConfig5(body) {
return {
url: "https://github.com/login/oauth/access_token",
method: "POST",
headers: {
Accept: "application/json"
},
body: new URLSearchParams(body)
};
}
// src/providers/google.ts
function getGoogleAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://accounts.google.com/o/oauth2/v2/auth?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/google",
...props
})}`;
}
async function getGoogleAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig6({
code,
redirect_uri: base_url + "/api/auth/integration/google",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "google",
...tokens
});
return {
provider: "google",
...tokens
};
}
function getTokenReqConfig6(body) {
return {
url: "https://oauth2.googleapis.com/token",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/klaviyo.ts
async function getKlaviyoAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
code_challenge,
...props
}) {
return `https://www.klaviyo.com/oauth/authorize?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/klaviyo",
code_challenge_method: "S256",
code_challenge,
...props
})}`;
}
async function getKlaviyoAccessToken({
code,
base_url,
client_id,
client_secret,
callback,
code_verifier
}) {
const { url, ...init } = getTokenReqConfig7(
{
code,
redirect_uri: base_url + "/api/auth/integration/klaviyo",
grant_type: "authorization_code",
client_secret,
client_id,
code_verifier: code_verifier || ""
},
{
client_id,
client_secret
}
);
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "klaviyo",
...tokens
});
return {
provider: "klaviyo",
...tokens
};
}
function getTokenReqConfig7(body, { client_id, client_secret }) {
const BASIC = Buffer.from(`${client_id}:${client_secret}`).toString("base64");
return {
url: "https://a.klaviyo.com/oauth/token",
method: "POST",
headers: {
Authorization: `Basic ${BASIC}`,
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/linkedin.ts
function getLinkedinAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://www.linkedin.com/oauth/v2/authorization?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/linkedin",
...props
})}`;
}
async function getLinkedinAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig8({
code,
redirect_uri: base_url + "/api/auth/integration/linkedin",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "linkedin",
...tokens
});
return {
provider: "linkedin",
...tokens
};
}
function getTokenReqConfig8(body) {
return {
url: "https://www.linkedin.com/oauth/v2/accessToken",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/notion.ts
function getNotionAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://api.notion.com/v1/oauth/authorize?${qs({
response_type: "code",
owner: "user",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/notion",
...props
})}`;
}
async function getNotionAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig9(
{
code,
redirect_uri: base_url + "/api/auth/integration/notion",
grant_type: "authorization_code",
client_secret,
client_id
},
{
client_id,
client_secret
}
);
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "notion",
...tokens
});
return {
provider: "notion",
...tokens
};
}
function getTokenReqConfig9(body, { client_id, client_secret }) {
const BASIC = Buffer.from(`${client_id}:${client_secret}`).toString("base64");
return {
url: "https://api.notion.com/v1/oauth/token",
method: "POST",
headers: {
Authorization: `Basic ${BASIC}`,
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/pinterest.ts
function getPinterestAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://www.pinterest.com/oauth/?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/pinterest",
...props
})}`;
}
async function getPinterestAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig10(
{
code,
redirect_uri: base_url + "/api/auth/integration/pinterest",
grant_type: "authorization_code",
client_secret,
client_id
},
{
client_id,
client_secret
}
);
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "pinterest",
...tokens
});
return {
provider: "pinterest",
...tokens
};
}
function getTokenReqConfig10(body, { client_id, client_secret }) {
const BASIC = Buffer.from(`${client_id}:${client_secret}`).toString("base64");
return {
url: "https://api.pinterest.com/v5/oauth/token",
method: "POST",
headers: {
Authorization: `Basic ${BASIC}`,
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/slack.ts
function getSlackAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://slack.com/oauth/v2/authorize?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/slack",
...props
})}`;
}
async function getSlackAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig11({
code,
redirect_uri: base_url + "/api/auth/integration/slack",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "slack",
...tokens
});
return {
provider: "slack",
...tokens
};
}
function getTokenReqConfig11(body) {
return {
url: "https://slack.com/api/oauth.v2.access",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/snapchat.ts
function getSnapchatAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://accounts.snapchat.com/login/oauth2/authorize?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/snapchat",
...props
})}`;
}
async function getSnapchatAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig12({
code,
redirect_uri: base_url + "/api/auth/integration/snapchat",
grant_type: "authorization_code",
client_secret,
client_id
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "snapchat",
...tokens
});
return {
provider: "snapchat",
...tokens
};
}
function getTokenReqConfig12(body) {
return {
url: "https://accounts.snapchat.com/login/oauth2/access_token",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/spotify.ts
function getSpotifyAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://accounts.spotify.com/authorize?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/spotify",
...props
})}`;
}
async function getSpotifyAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig13(
{
code,
redirect_uri: base_url + "/api/auth/integration/spotify",
grant_type: "authorization_code",
client_secret,
client_id
},
{
client_id,
client_secret
}
);
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "spotify",
...tokens
});
return {
provider: "spofity",
...tokens
};
}
function getTokenReqConfig13(body, { client_id, client_secret }) {
const BASIC = Buffer.from(`${client_id}:${client_secret}`).toString("base64");
return {
url: "https://accounts.spotify.com/api/token",
method: "POST",
headers: {
Authorization: `Basic ${BASIC}`,
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/tiktok.ts
function getTiktokAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
code_challenge,
...props
}) {
return `https://www.tiktok.com/v2/auth/authorize?${qs({
response_type: "code",
client_key: client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/tiktok",
code_challenge_method: "S256",
code_challenge,
...props
})}`;
}
async function getTiktokAccessToken({
code,
base_url,
client_id,
client_secret,
callback,
code_verifier
}) {
const { url, ...init } = getTokenReqConfig14({
code,
redirect_uri: base_url + "/api/auth/integration/tiktok",
grant_type: "authorization_code",
client_secret,
client_key: client_id,
code_verifier: code_verifier || ""
});
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "tiktok",
...tokens
});
return {
provider: "tiktok",
...tokens
};
}
function getTokenReqConfig14(body) {
return {
url: "https://open.tiktokapis.com/v2/oauth/token/",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/providers/trustpilot.ts
function getTrustpilotAuthorizeUrl({
client_id,
scope,
base_url,
client_secret,
...props
}) {
return `https://authenticate.trustpilot.com?${qs({
response_type: "code",
client_id,
scope,
redirect_uri: base_url + "/api/auth/integration/trustpilot",
...props
})}`;
}
async function getTrustpilotAccessToken({
code,
base_url,
client_id,
client_secret,
callback
}) {
const { url, ...init } = getTokenReqConfig15(
{
code,
redirect_uri: base_url + "/api/auth/integration/trustpilot",
grant_type: "authorization_code",
client_secret,
client_id
},
{
client_id,
client_secret
}
);
const res = await fetch(url, init);
const tokens = await res.json();
await callback({
provider: "trustpilot",
...tokens
});
return {
provider: "trustpilot",
...tokens
};
}
function getTokenReqConfig15(body, { client_id, client_secret }) {
const BASIC = Buffer.from(`${client_id}:${client_secret}`).toString("base64");
console.log(BASIC);
return {
url: "https://api.trustpilot.com/v1/oauth/oauth-business-users-for-applications/accesstoken",
method: "POST",
headers: {
Authorization: `Basic ${BASIC}`,
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams(body)
};
}
// src/helpers.ts
async function generateAuthURL({
params,
base_url,
client_id,
scope,
code_challenge,
...props
}) {
if (!base_url) {
throw new Error("base_url is required");
}
if (!client_id) {
throw new Error("client_id is required");
}
if (params.includes("integration/google")) {
const url = getGoogleAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/pinterest")) {
const url = getPinterestAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/facebook")) {
const url = getFacebookAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/snapchat")) {
const url = getSnapchatAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/spotify")) {
const url = getSpotifyAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/slack")) {
const url = getSlackAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/klaviyo")) {
const url = await getKlaviyoAuthorizeUrl({
client_id,
scope,
base_url,
code_challenge,
...props
});
return url;
}
if (params.includes("integration/notion")) {
const url = getNotionAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/discord")) {
const url = getDiscordAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/github")) {
const url = getGithubAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/tiktok")) {
const url = getTiktokAuthorizeUrl({
client_id,
scope,
base_url,
code_challenge,
...props
});
return url;
}
if (params.includes("integration/trustpilot")) {
const url = getTrustpilotAuthorizeUrl({
client_id,
scope,
base_url,
code_challenge,
...props
});
return url;
}
if (params.includes("integration/accuranker")) {
const url = getAccurankerAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/click-up")) {
const url = getClickUpAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
if (params.includes("integration/linkedin")) {
const url = getLinkedinAuthorizeUrl({
client_id,
scope,
base_url,
...props
});
return url;
}
}
async function generateTokens({
code,
params,
base_url,
client_id,
client_secret,
callback,
code_verifier
}) {
if (!base_url) {
throw new Error("base_url is required");
}
if (!client_id) {
throw new Error("client_id is required");
}
if (!client_secret) {
throw new Error("client_secret is required");
}
if (params.includes("integration/google")) {
const tokens = await getGoogleAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/pinterest")) {
const tokens = await getPinterestAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/facebook")) {
const tokens = await getFacebookAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/snapchat")) {
const tokens = await getSnapchatAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/spotify")) {
const tokens = await getSpotifyAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/slack")) {
const tokens = await getSlackAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/klaviyo")) {
const tokens = await getKlaviyoAccessToken({
base_url,
client_id,
client_secret,
code,
code_verifier,
callback
});
return tokens;
}
if (params.includes("integration/notion")) {
const tokens = await getNotionAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/discord")) {
const tokens = await getDiscordAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/github")) {
const tokens = await getGithubAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/tiktok")) {
const tokens = await getTiktokAccessToken({
base_url,
client_id,
client_secret,
code,
callback,
code_verifier
});
return tokens;
}
if (params.includes("integration/trustpilot")) {
const tokens = await getTrustpilotAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/accuranker")) {
const tokens = await getAccurankerAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/click-up")) {
const tokens = await getClickUpAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
if (params.includes("integration/linkedin")) {
const tokens = await getLinkedinAccessToken({
base_url,
client_id,
client_secret,
code,
callback
});
return tokens;
}
}
// src/auth.ts
function NextIntegrate(auth) {
return { auth };
}
// src/handler.ts
function base64URLEncode(str) {
return str.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}
async function generateCodes() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
const verifier = base64URLEncode(Buffer.from(array));
async function sha256(plain) {
const encoder = new TextEncoder();
const data = encoder.encode(plain);
return await crypto.subtle.digest("SHA-256", data);
}
async function generateCodeChallenge(verifier2) {
const hashed = await sha256(verifier2);
return base64URLEncode(Buffer.from(hashed));
}
return {
code_verifier: verifier,
code_challenge: await generateCodeChallenge(verifier)
};
}
var placerholder = {
auth_url: "/",
redirect: "/",
options: null,
codeChallenge: "",
callback: () => {
}
};
async function handler({
context,
req,
auth,
cookieStore,
debug = false
}) {
const { code_verifier, code_challenge } = await generateCodes();
const params = (await context.params).integration;
const code = req.nextUrl.searchParams.get("code");
if (debug) {
console.log("code_verifier", code_verifier);
console.log("code_challenge", code_challenge);
}
const newName = req.nextUrl.searchParams.get("name");
const newRedirect = req.nextUrl.searchParams.get("redirect");
if (debug) {
console.log("Name", newName);
console.log("Redirect", newRedirect);
}
if (!code) {
if (debug) {
console.log("Setting cookies");
}
(await cookieStore).set("name", newName || "");
(await cookieStore).set("redirect", newRedirect || "");
(await cookieStore).set("code_verifier", code_verifier);
}
const name = (await cookieStore).get("name")?.value;
const redirect = (await cookieStore).get("redirect")?.value;
if (debug) {
console.log("Getting newly set cookies");
console.log("Name", name);
console.log("Redirect", redirect);
}
if (!name) {
if (debug) {
console.log("Name is required");
}
return {
...placerholder,
error: "Name is required"
};
}
if (debug) {
console.log("Getting providers");
}
const { providers, base_url } = auth;
if (debug) {
console.log("Providers", providers);
console.log("Base URL", base_url);
}
const provider = providers.find((p) => p.provider === params[1]);
if (debug) {
console.log("Provider", provider);
}
const integration = provider?.integrations.find((i) => i.name === name);
if (debug) {
console.log("Integration", integration);
}
if (!provider || !name || !integration) {
if (debug) {
console.log("Invalid integration");
}
return {
...placerholder,
error: "Invalid integration"
};
}
const options = {
...integration.options,
client_id: provider.client_id,
client_secret: provider.client_secret,
code_challenge,
base_url,
params: params.join("/")
};
if (debug) {
console.log("Options", options);
}
const auth_url = await generateAuthURL(options);
if (debug) {
console.log("Auth URL", auth_url);
}
if (!auth_url) {
if (debug) {
console.log("Invalid redirect URL");
}
return {
...placerholder,
error: "Invalid redirect URL"
};
}
return {
auth_url,
redirect: redirect?.replaceAll("__HASH__", "#").replaceAll("__AND__", "&") || "/",
options,
callback: integration.callback,
error: null
};
}
async function exchange({
options,
callback,
code,
cookieStore,
debug = false
}) {
if (!options) return;
if (debug) {
console.log("Options", options);
}
const code_verifier = (await cookieStore).get("code_verifier")?.value;
if (debug) {
console.log("Code verifier", code_verifier);
}
const tokens = await generateTokens({
...options,
code_verifier,
callback,
code
});
if (debug) {
console.log("Tokens", tokens);
}
(await cookieStore).delete("name");
(await cookieStore).delete("redirect");
(await cookieStore).delete("code_verifier");
if (debug) {
console.log("Cleared cookies");
}
return tokens;
}
async function clearCookies({
cookieStore
}) {
(await cookieStore).delete("name");
(await cookieStore).delete("redirect");
(await cookieStore).delete("code_verifier");
}
// src/integrate.ts
function integrate({
name,
provider,
redirect,
base_path
}) {
if (!name || !provider || !redirect) {
throw new Error("Name, redirect and provider are required");
}
let redirectUrl = redirect.replaceAll("#", "__HASH__").replaceAll("&", "__AND__");
let url = `/api/auth/integration/${provider}?name=${name}&redirect=${redirectUrl}`;
if (base_path) {
url = `${base_path}/api/auth/integration/${provider}?name=${name}&redirect=${redirectUrl}`;
}
return url;
}
export {
NextIntegrate,
NextRequest,
clearCookies,
exchange,
generateAuthURL,
generateTokens,
handler,
integrate
};