Update to respond a new access token every request

This commit is contained in:
delivan 2022-12-05 23:16:02 +09:00
parent 143928bd86
commit 01b70389f0
6 changed files with 119 additions and 34 deletions

View File

@ -0,0 +1,32 @@
import { withIronSessionApiRoute } from "iron-session/next";
import type { NextApiRequest, NextApiResponse } from "next";
import { ironOptions } from "../../iron.config";
import { IcnsVerificationInfoResponse } from "../../types/api-response";
import { request } from "../../utils/url";
export default withIronSessionApiRoute(async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
try {
if (!process.env.ICNS_VERIFIER_URI) {
console.log(".env is not set");
return res.status(500).json({ error: "Internal server error" });
}
const icnsVerificationInfo = await request<IcnsVerificationInfoResponse>(
process.env.ICNS_VERIFIER_URI,
{
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(req.body),
},
);
res.status(200).json(icnsVerificationInfo);
} catch (error) {
console.error(error);
res.status(500).json({ error: "Internal server error" });
}
},
ironOptions);

View File

@ -13,29 +13,39 @@ export default withIronSessionApiRoute(async function handler(
!process.env.TWITTER_CLIENT_SECRET ||
!process.env.TWITTER_AUTH_CALLBACK_URI
) {
return res
.status(500)
.send(
console.error(new Error(".env is not set"));
return res.status(500).send({
error:
"Twitter app client id or client secret or callback URI is not set",
);
});
}
if (!req.session.code_verifier) {
return res.status(401).send("No OAuth2.0 code verifier");
return res.status(401).send({
error: "No OAuth2.0 code verifier",
});
}
try {
const params = new URLSearchParams();
if (req.session.refresh_token) {
params.append("grant_type", "refresh_token");
params.append("refresh_token", req.session.refresh_token);
params.append("client_id", process.env.TWITTER_CLIENT_ID);
} else {
const { code, state } = req.query;
if (state !== process.env.TWITTER_AUTH_STATE) {
return res.status(401).send("State isn't matching");
return res.status(401).send({ error: "State isn't matching" });
}
const params = new URLSearchParams();
params.append("grant_type", "authorization_code");
params.append("code", code as string);
params.append("redirect_uri", process.env.TWITTER_AUTH_CALLBACK_URI);
params.append("code_verifier", req.session.code_verifier);
const { access_token: accessToken } =
}
const { access_token: accessToken, refresh_token } =
await request<TwitterOAuth2TokenResponse>(
`${twitterApiBaseUrl}/oauth2/token`,
{
@ -49,6 +59,9 @@ export default withIronSessionApiRoute(async function handler(
body: params,
},
);
req.session.refresh_token = refresh_token;
await req.session.save();
const {
data: { id, username },
} = await request<TwitterUsersMeResponse>(`${twitterApiBaseUrl}/users/me`, {
@ -62,8 +75,8 @@ export default withIronSessionApiRoute(async function handler(
username,
});
} catch (error) {
console.log(error);
res.status(500).send("Internal server error ");
console.error(error);
res.status(500).json({ error: "Internal server error " });
}
},
ironOptions);

View File

@ -14,10 +14,12 @@ export default withIronSessionApiRoute(async function handler(
res: NextApiResponse,
) {
if (
!process.env.TWITTER_AUTH_STATE ||
!process.env.TWITTER_AUTH_CODE_CHALLENGE
!process.env.TWITTER_CLIENT_ID ||
!process.env.TWITTER_AUTH_CALLBACK_URI ||
!process.env.TWITTER_AUTH_STATE
) {
return res.status(500).send("No state or code_challenge");
console.error(new Error(".env is not set"));
return res.status(500).json({ error: "Internal server error" });
}
try {
@ -42,7 +44,7 @@ export default withIronSessionApiRoute(async function handler(
res.status(200).json({ authUrl });
} catch (error) {
console.error(error);
res.status(500).send("Internal server error");
res.status(500).json({ error: "Internal server error" });
}
},
ironOptions);
@ -50,5 +52,6 @@ ironOptions);
declare module "iron-session" {
interface IronSessionData {
code_verifier?: string;
refresh_token?: string;
}
}

View File

@ -1,25 +1,51 @@
import { useEffect, useState } from "react";
import { TwitterAuthInfoResponse } from "../../types/api-response";
import {
IcnsVerificationInfoResponse,
TwitterAuthInfoResponse,
} from "../../types/api-response";
import { VerifierMsg } from "../../types/msg";
import { request } from "../../utils/url";
export default function VerificationPage() {
const [twitterAuthInfo, setTwitterAuthInfo] =
useState<TwitterAuthInfoResponse | null>();
const fetchAccessToken = async (state: string, code: string) => {
const newTwitterAuthInfo: TwitterAuthInfoResponse = await (
await fetch(`/api/twitter-auth-info?state=${state}&code=${code}`)
).json();
setTwitterAuthInfo(newTwitterAuthInfo);
};
useEffect(() => {
const handleVerification = async () => {
const [, state, code] =
window.location.search.match(
/^(?=.*state=([^&]+)|)(?=.*code=([^&]+)|).+$/,
) || [];
const newTwitterAuthInfo = await request<TwitterAuthInfoResponse>(
`/api/twitter-auth-info?state=${state}&code=${code}`,
);
fetchAccessToken(state, code);
console.log(newTwitterAuthInfo);
setTwitterAuthInfo(newTwitterAuthInfo);
const verifierMsg: VerifierMsg = {
name: newTwitterAuthInfo.username,
claimer: "osmo1y5mm5nj5m8ttddt5ccspek6xgyyavehrkak7gq",
contract_address: "osmo1y5mm5nj5m8ttddt5ccspek6xgyyavehrkak7gq",
chain_id: "osmosis-1",
};
const icnsVerificationInfo = await request<IcnsVerificationInfoResponse>(
"/api/icns-verification",
{
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
msg: JSON.stringify(verifierMsg),
authToken: newTwitterAuthInfo.accessToken,
}),
},
);
console.log(icnsVerificationInfo);
};
handleVerification();
}, []);
return (

View File

@ -7,3 +7,8 @@ export interface TwitterAuthInfoResponse {
id: string;
username: string;
}
export interface IcnsVerificationInfoResponse {
signature: number[];
algorithm: string;
}

6
types/msg.ts Normal file
View File

@ -0,0 +1,6 @@
export interface VerifierMsg {
name: string;
claimer: string;
contract_address: string;
chain_id: string;
}