feat: enhance security by implementing HttpOnly refresh tokens and in-memory access token management
- Added isomorphic-dompurify for improved XSS protection - Refactored token storage to use in-memory management for access tokens - Implemented server-side route handlers for OAuth token management - Introduced security headers in next.config.js - Removed client-side exposure of client_secret and sensitive tokens - Updated API interceptors to handle token refresh logic - Cleaned up cookie management for refresh tokens
This commit is contained in:
@@ -3,6 +3,7 @@ import { cookies } from "next/headers";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
import { safeJsonParse } from "@/lib/sanitize";
|
||||
import { adaptRepresentationDashboard } from "@/lib/representationAdapters";
|
||||
import { getServerAccessToken } from "@/lib/serverToken";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -13,21 +14,23 @@ async function Dashboard() {
|
||||
try {
|
||||
const cookieStore = await cookies();
|
||||
const userInfo = cookieStore.get("userInfo");
|
||||
const accessToken = cookieStore.get("access_token");
|
||||
|
||||
if (userInfo && accessToken) {
|
||||
if (userInfo) {
|
||||
const parsedUserInfo = safeJsonParse(userInfo.value);
|
||||
const representationUuid = parsedUserInfo?.representation_uuid;
|
||||
|
||||
if (representationUuid) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth() + 1;
|
||||
const accessToken = await getServerAccessToken();
|
||||
if (accessToken) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth() + 1;
|
||||
|
||||
dashboard = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}/dashboard/monthly?year=${year}&month=${month}`,
|
||||
{ headers: { Authorization: `Bearer ${accessToken.value}` } }
|
||||
);
|
||||
dashboard = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}/dashboard/monthly?year=${year}&month=${month}`,
|
||||
{ headers: { Authorization: `Bearer ${accessToken}` } }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { redirect } from "next/navigation";
|
||||
import { cookies } from "next/headers";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
import { safeJsonParse } from "@/lib/sanitize";
|
||||
import { getServerAccessToken } from "@/lib/serverToken";
|
||||
|
||||
async function LayoutPanel({ children }) {
|
||||
const user = await getUser();
|
||||
@@ -20,22 +21,24 @@ async function LayoutPanel({ children }) {
|
||||
try {
|
||||
const cookieStore = await cookies();
|
||||
const userInfo = cookieStore.get("userInfo");
|
||||
const accessToken = cookieStore.get("access_token");
|
||||
|
||||
if (userInfo && accessToken) {
|
||||
if (userInfo) {
|
||||
const parsedUserInfo = safeJsonParse(userInfo.value);
|
||||
if (!parsedUserInfo) return;
|
||||
const representationUuid = parsedUserInfo?.representation_uuid;
|
||||
|
||||
if (representationUuid) {
|
||||
representationInfo = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken.value}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
const accessToken = await getServerAccessToken();
|
||||
if (accessToken) {
|
||||
representationInfo = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { cookies } from "next/headers";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
import { safeJsonParse } from "@/lib/sanitize";
|
||||
import { adaptRepresentationDashboard } from "@/lib/representationAdapters";
|
||||
import { getServerAccessToken } from "@/lib/serverToken";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -13,21 +14,23 @@ async function page() {
|
||||
try {
|
||||
const cookieStore = await cookies();
|
||||
const userInfo = cookieStore.get("userInfo");
|
||||
const accessToken = cookieStore.get("access_token");
|
||||
|
||||
if (userInfo && accessToken) {
|
||||
if (userInfo) {
|
||||
const parsedUserInfo = safeJsonParse(userInfo.value);
|
||||
const representationUuid = parsedUserInfo?.representation_uuid;
|
||||
|
||||
if (representationUuid) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth() + 1;
|
||||
const accessToken = await getServerAccessToken();
|
||||
if (accessToken) {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = now.getMonth() + 1;
|
||||
|
||||
dashboard = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}/dashboard/monthly?year=${year}&month=${month}`,
|
||||
{ headers: { Authorization: `Bearer ${accessToken.value}` } }
|
||||
);
|
||||
dashboard = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}/dashboard/monthly?year=${year}&month=${month}`,
|
||||
{ headers: { Authorization: `Bearer ${accessToken}` } }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { cookies } from "next/headers";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
import { safeJsonParse } from "@/lib/sanitize";
|
||||
import { adaptBankAccount } from "@/lib/representationAdapters";
|
||||
import { getServerAccessToken } from "@/lib/serverToken";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -13,17 +14,19 @@ async function UserAccount() {
|
||||
try {
|
||||
const cookieStore = await cookies();
|
||||
const userInfo = cookieStore.get("userInfo");
|
||||
const accessToken = cookieStore.get("access_token");
|
||||
|
||||
if (userInfo && accessToken) {
|
||||
if (userInfo) {
|
||||
const parsedUserInfo = safeJsonParse(userInfo.value);
|
||||
const representationUuid = parsedUserInfo?.representation_uuid;
|
||||
|
||||
if (representationUuid) {
|
||||
representation = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}`,
|
||||
{ headers: { Authorization: `Bearer ${accessToken.value}` } }
|
||||
);
|
||||
const accessToken = await getServerAccessToken();
|
||||
if (accessToken) {
|
||||
representation = await fetchReq(
|
||||
`${API_URL}/api/v1/representation/${representationUuid}`,
|
||||
{ headers: { Authorization: `Bearer ${accessToken}` } }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user