Skip to content

Commit

Permalink
token varification and refresh token fix
Browse files Browse the repository at this point in the history
  • Loading branch information
jigar-arc10 committed Oct 15, 2024
1 parent 4472dbd commit 8df762a
Show file tree
Hide file tree
Showing 12 changed files with 504 additions and 345 deletions.
4 changes: 3 additions & 1 deletion apps/provider-console/next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */

const { withSentryConfig } = require('@sentry/nextjs');
const nextConfig = {
reactStrictMode: false,
compiler: {
Expand Down Expand Up @@ -34,5 +36,5 @@ const nextConfig = {
},
};

module.exports = nextConfig;
module.exports = withSentryConfig(nextConfig);

2 changes: 2 additions & 0 deletions apps/provider-console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"@cosmos-kit/keplr": "^2.12.2",
"@cosmos-kit/leap-extension": "^2.12.2",
"@cosmos-kit/react": "^2.18.0",
"@sentry/nextjs": "^8.34.0",
"@sentry/tracing": "^7.114.0",
"apexcharts": "^3.54.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
Expand Down
8 changes: 8 additions & 0 deletions apps/provider-console/sentry.client.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "http://[email protected]:9000/2",
integrations: [Sentry.replayIntegration()],
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0
});
12 changes: 5 additions & 7 deletions apps/provider-console/src/components/home/HomeContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";
import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
import { Footer } from "@src/components/layout/Footer";
import Layout from "../layout/Layout";
import { useWallet } from "@src/context/WalletProvider";
import networkStore from "@src/store/networkStore";
Expand All @@ -10,16 +9,14 @@ import restClient from "@src/utils/restClient";
import { WalletNotConnected } from "./WalletNotConnected";
import { NotAProvider } from "./NotAProvider";
import { Button, Spinner } from "@akashnetwork/ui/components";
import { ProviderActionDetails } from "../shared/ProviderActionDetails";
import ProviderActionList from "../shared/ProviderActionList";
import Link from "next/link";
import { useAtom } from "jotai";
import providerProcessStore from "@src/store/providerProcessStore";

export function HomeContainer() {
const [, resetProcess] = useAtom(providerProcessStore.resetProviderProcess);
const router = useRouter();
const { isWalletConnected } = useWallet();
const { isWalletConnected, isWalletArbitrarySigned } = useWallet();
const [isLoading, setIsLoading] = useState(false);
const [isProvider, setIsProvider] = useState(false);
const [, setProvider] = useState<any>(null);
Expand All @@ -31,9 +28,11 @@ export function HomeContainer() {
useEffect(() => {
if (isWalletConnected) {
setIsLoading(true);
fetchProviderStatus();
if (isWalletArbitrarySigned) {
fetchProviderStatus();
}
}
}, [isWalletConnected]);
}, [isWalletConnected, isWalletArbitrarySigned]);

const fetchProviderStatus = async () => {
try {
Expand Down Expand Up @@ -97,7 +96,6 @@ export function HomeContainer() {
)}
</div>
</div>
<Footer />
</Layout>
);
}
2 changes: 1 addition & 1 deletion apps/provider-console/src/components/home/NotAProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function NotAProvider() {
<p>Join the Akash Network and offer your compute resources.</p>
<ul className="list-disc pl-5">
<li>Earn by leasing your compute power.</li>
<li>Utilize a streamlined UI with the Praetor App.</li>
<li>Utilize a streamlined UI with the Provider Console App.</li>
<li>Access detailed provider documentation.</li>
<li>Monitor provider status and earnings.</li>
<li>Participate in a decentralized cloud marketplace.</li>
Expand Down
2 changes: 1 addition & 1 deletion apps/provider-console/src/components/layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const LayoutApp: React.FunctionComponent<Props> = ({ children, isLoading, isUsin
<div className="block h-full w-full flex-grow rounded-none md:flex">
<Sidebar onOpenMenuClick={onOpenMenuClick} isNavOpen={isNavOpen} handleDrawerToggle={handleDrawerToggle} isMobileOpen={isMobileOpen} />
<div
className={cn("ease ml-0 h-full flex-grow transition-[margin-left] duration-300", {
className={cn("ease ml-0 min-h-full flex-grow transition-[margin-left] duration-300", {
["md:ml-[240px]"]: isNavOpen,
["md:ml-[57px]"]: !isNavOpen
})}
Expand Down
8 changes: 6 additions & 2 deletions apps/provider-console/src/components/layout/WalletStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { ConnectWalletButton } from "../wallet/ConnectWalletButton";
const DEV_URL = "app-dev.praetor.dev";

export function WalletStatus() {
const { walletName, address, walletBalances, logout, isWalletLoaded, isWalletConnected } = useWallet();
const { walletName, address, walletBalances, logout, isWalletLoaded, isWalletConnected, setIsWalletArbitrarySigned } = useWallet();
const { wallet } = useSelectedChain();
const walletBalance = useTotalWalletBalance();

Expand All @@ -38,7 +38,7 @@ export function WalletStatus() {

const getNonceMessage = (nonce: string) => {
const url = process.env.NODE_ENV === "development" ? DEV_URL : window.location.hostname;
return `${url} wants you to sign in with your Keplr account - ${address} using Nonce - ${nonce}`;
return `provider-beta.console.akash.network wants you to sign in with your Keplr account - ${address} using Nonce - ${nonce}`;
};

const handleWalletConnectSuccess = async () => {
Expand All @@ -57,14 +57,18 @@ export function WalletStatus() {
localStorage.setItem("accessToken", verifySign.data.access_token);
localStorage.setItem("refreshToken", verifySign.data.refresh_token);
localStorage.setItem("walletAddress", address);
setIsWalletArbitrarySigned(true);
} else {
logout();
setIsWalletArbitrarySigned(false);
}
} else {
logout();
setIsWalletArbitrarySigned(false);
}
} catch (error) {
logout();
setIsWalletArbitrarySigned(false);
}
} else {
console.log(response);
Expand Down
37 changes: 26 additions & 11 deletions apps/provider-console/src/context/WalletProvider/WalletProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { UrlService } from "@src/utils/urlUtils";
import { LocalWalletDataType } from "@src/utils/walletUtils";
import { useSelectedChain } from "../CustomChainProvider";
import { useSettings } from "../SettingsProvider";
import { jwtDecode } from "jwt-decode";
import { checkAndRefreshToken } from "@src/utils/tokenUtils";

type Balances = {
uakt: number;
Expand All @@ -30,9 +32,11 @@ type ContextType = {
walletBalances: Balances | null;
isWalletConnected: boolean;
isWalletLoaded: boolean;
isWalletArbitrarySigned: boolean;
connectWallet: () => Promise<void>;
logout: () => void;
setIsWalletLoaded: React.Dispatch<React.SetStateAction<boolean>>;
setIsWalletArbitrarySigned: React.Dispatch<React.SetStateAction<boolean>>;
signAndBroadcastTx: (msgs: EncodeObject[]) => Promise<any>;
refreshBalances: (address?: string) => Promise<Balances>;
};
Expand All @@ -44,6 +48,7 @@ export const WalletProvider = ({ children }) => {
const [isWalletLoaded, setIsWalletLoaded] = useState<boolean>(true);
const [isBroadcastingTx, setIsBroadcastingTx] = useState<boolean>(false);
const [isWaitingForApproval, setIsWaitingForApproval] = useState<boolean>(false);
const [isWalletArbitrarySigned, setIsWalletArbitrarySigned] = useState<boolean>(false);
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
const sigingClient = useRef<SigningStargateClient | null>(null);
const router = useRouter();
Expand All @@ -69,6 +74,21 @@ export const WalletProvider = ({ children }) => {
(async () => {
if (settings?.rpcEndpoint && isWalletConnected) {
sigingClient.current = await createStargateClient();

try {
const validAccessToken = await checkAndRefreshToken();
if (validAccessToken) {
console.log("Access token is valid");
setIsWalletArbitrarySigned(true);
} else {
console.log("No valid access token found");
setIsWalletArbitrarySigned(false);
}
} catch (error) {
console.error("Error checking or refreshing token:", error);
setIsWalletArbitrarySigned(false);
logout(); // Force logout if refresh fails
}
}
})();
}, [settings?.rpcEndpoint, isWalletConnected]);
Expand Down Expand Up @@ -239,16 +259,10 @@ export const WalletProvider = ({ children }) => {
transactionHash: string,
snackVariant: React.ComponentProps<typeof Snackbar>["iconVariant"]
) => {
enqueueSnackbar(
<Snackbar
title={snackTitle}
iconVariant={snackVariant}
/>,
{
variant: snackVariant,
autoHideDuration: 10000
}
);
enqueueSnackbar(<Snackbar title={snackTitle} iconVariant={snackVariant} />, {
variant: snackVariant,
autoHideDuration: 10000
});
};

async function refreshBalances(address?: string): Promise<{ uakt: number; usdc: number }> {
Expand Down Expand Up @@ -282,6 +296,8 @@ export const WalletProvider = ({ children }) => {
address: walletAddress as string,
walletName: username as string,
walletBalances,
isWalletArbitrarySigned,
setIsWalletArbitrarySigned,
isWalletConnected: isWalletConnected,
isWalletLoaded,
connectWallet,
Expand All @@ -302,4 +318,3 @@ export const WalletProvider = ({ children }) => {
export function useWallet() {
return { ...React.useContext(WalletProviderContext) };
}

2 changes: 1 addition & 1 deletion apps/provider-console/src/utils/authClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const errorNotification = (error = "Error Occurred") => {
};

const authClient = axios.create({
baseURL: `https://knight-dev.testcoders.com`,
baseURL: `http://aisrlqh46hd27cm7o29rqo3378.ingress.hurricane.akash.pub`,
timeout: 30000
});

Expand Down
42 changes: 18 additions & 24 deletions apps/provider-console/src/utils/restClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
import axios from "axios";

import authClient from "./authClient";
import { checkAndRefreshToken } from "./tokenUtils";

const errorNotification = (error = "Error Occurred") => {
console.log(error);
};

const restClient = axios.create({
baseURL: `https://b588-99-209-150-74.ngrok-free.app`,
baseURL: `http://5cujrkcvn9e234vilf1iglkf98.ingress.hurricane.akash.pub/`,
timeout: 60000
});

Expand All @@ -30,31 +31,16 @@ restClient.interceptors.response.use(
originalRequest.retry = true;

try {
const refreshToken = localStorage.getItem("refreshToken");
const walletAddress = localStorage.getItem("walletAddress");

const refreshResponse = await authClient.post("/auth/refresh", {
refresh_token: refreshToken,
address: walletAddress
});

if (refreshResponse.data.status === "success") {
localStorage.setItem("accessToken", refreshResponse.data.access_token);
localStorage.setItem("refreshToken", refreshResponse.data.refresh_token);

originalRequest.headers.Authorization = `Bearer ${refreshResponse.data.access_token}`;
return restClient.request(originalRequest);
const newToken = await checkAndRefreshToken();
if (newToken) {
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return restClient(originalRequest);
} else {
// Handle refresh token failure
localStorage.removeItem("accessToken");
localStorage.removeItem("refreshToken");
localStorage.removeItem("walletAddress");
// Redirect to login page or handle as needed
// history.push("/auth/login");
throw new Error("Refresh token failed");
// Token refresh failed, redirect to login or handle accordingly
// For example: history.push("/auth/login");
throw new Error("Token refresh failed");
}
} catch (refreshError) {
// Handle refresh token request error
console.error("Error refreshing token:", refreshError);
throw refreshError;
}
Expand Down Expand Up @@ -87,8 +73,16 @@ restClient.interceptors.response.use(

restClient.interceptors.request.use(async request => {
request.headers = request.headers ?? {};
request.headers.Authorization = `Bearer ${localStorage.getItem("accessToken")}`;
const token = await checkAndRefreshToken();
if (token) {
request.headers.Authorization = `Bearer ${token}`;
} else {
// Handle the case when there's no valid token
// For example: redirect to login page or throw an error
throw new Error("No valid token available");
}
request.headers["ngrok-skip-browser-warning"] = "69420";
return request;
});

export default restClient;
56 changes: 56 additions & 0 deletions apps/provider-console/src/utils/tokenUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { jwtDecode } from 'jwt-decode';
import authClient from './authClient';

interface DecodedToken {
exp: number;
}

export async function checkAndRefreshToken(): Promise<string | null> {
const accessToken = localStorage.getItem('accessToken');

if (!accessToken) {
return null;
}

try {
const decodedToken = jwtDecode<DecodedToken>(accessToken);
const currentTime = Math.floor(Date.now() / 1000);

if (decodedToken.exp > currentTime) {
// Token is still valid
return accessToken;
}

// Token has expired, attempt to refresh
const refreshToken = localStorage.getItem('refreshToken');
const walletAddress = localStorage.getItem('walletAddress');

if (!refreshToken || !walletAddress) {
throw new Error('Refresh token or wallet address not found');
}

const refreshResponse = await authClient.post('/auth/refresh', {
refresh_token: refreshToken,
address: walletAddress,
});

if (refreshResponse.data.status === 'success') {
const newAccessToken = refreshResponse.data.access_token;
const newRefreshToken = refreshResponse.data.refresh_token;

localStorage.setItem('accessToken', newAccessToken);
localStorage.setItem('refreshToken', newRefreshToken);

return newAccessToken;
} else {
throw new Error('Refresh token failed');
}
} catch (error) {
console.error('Error checking or refreshing token:', error);
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('walletAddress');
return null;
}
}

Loading

0 comments on commit 8df762a

Please sign in to comment.