icns-frontend/pages/api/twitter-auth-url.ts
2022-12-23 22:30:35 +09:00

62 lines
1.8 KiB
TypeScript

import { captureException } from "@sentry/nextjs";
import crypto from "crypto";
import { withIronSessionApiRoute } from "iron-session/next";
import type { NextApiRequest, NextApiResponse } from "next";
import {
twitterOAuthBaseUrl,
twitterOAuthScopes,
} from "../../constants/twitter";
import { ironOptions } from "../../iron.config";
import { base64URLEncode } from "../../utils/encoding";
import { buildQueryString } from "../../utils/url";
export default withIronSessionApiRoute(async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (
!process.env.TWITTER_CLIENT_ID ||
!process.env.TWITTER_AUTH_CALLBACK_URI ||
!process.env.TWITTER_AUTH_STATE
) {
console.error(new Error(".env is not set"));
return res.status(500).json({ error: "Internal server error" });
}
try {
req.session.destroy();
const codeVerifier = base64URLEncode(crypto.randomBytes(32));
req.session.code_verifier = codeVerifier;
await req.session.save();
const codeChallenge = base64URLEncode(
crypto.createHash("sha256").update(codeVerifier).digest(),
);
const authUrlObj = new URL(twitterOAuthBaseUrl);
authUrlObj.search = buildQueryString({
client_id: process.env.TWITTER_CLIENT_ID,
redirect_uri: process.env.TWITTER_AUTH_CALLBACK_URI,
state: process.env.TWITTER_AUTH_STATE,
scope: twitterOAuthScopes.join(" "),
response_type: "code",
code_challenge_method: "s256",
code_challenge: codeChallenge,
});
const authUrl = authUrlObj.toString();
res.status(200).json({ authUrl });
} catch (error) {
console.error(error);
captureException(error);
res.status(500).json({ error: "Internal server error" });
}
},
ironOptions);
declare module "iron-session" {
interface IronSessionData {
code_verifier?: string;
refresh_token?: string;
}
}