diff --git a/packages/api/middleware/auth.ts b/packages/api/middleware/auth.ts index 265bb0a..90493ec 100644 --- a/packages/api/middleware/auth.ts +++ b/packages/api/middleware/auth.ts @@ -2,6 +2,8 @@ import { NextFunction, Request, Response } from "express"; import { loadConfig } from "../config"; +const jwt = require("jsonwebtoken"); + const config = loadConfig(); // used by specific routes that need to authentication @@ -13,16 +15,26 @@ export const authCheck = async ( try { const { authorization } = req.headers; - // verify jwt token - const jwtSecret = config.JWT_TOKEN_SECRET; - if (!authorization) { throw Error("No provided header"); } + // verify jwt token with our api secret + var decoded: JwtClaims = jwt.verify(authorization, config.JWT_TOKEN_SECRET); + + res.locals.jwtClaims = decoded; + next(); } catch (error) { console.log(error); res.status(401).send("unauthorized"); } }; + +export interface JwtClaims { + userId: string; + googleUserId: string; + picture: string; + email: string; + name: string; +} diff --git a/packages/api/routes/user.ts b/packages/api/routes/user.ts index 762b53e..fe79654 100644 --- a/packages/api/routes/user.ts +++ b/packages/api/routes/user.ts @@ -27,11 +27,19 @@ export default function getUserRoutes() { router.get("/login", login); - router.get("/authCheck", authCheck); + router.get("/authcheck", authCheck, handleAuthCheck); return router; } +async function handleAuthCheck(req: Request, res: Response) { + try { + res.status(200).send(); + } catch (error) { + res.status(401).send(); + } +} + /** Create user if doesn't exist * Returns jwt token for client and user details */ diff --git a/packages/desktop/src/components/ProtectedRoute/index.tsx b/packages/desktop/src/components/ProtectedRoute/index.tsx index c9997eb..7c06820 100644 --- a/packages/desktop/src/components/ProtectedRoute/index.tsx +++ b/packages/desktop/src/components/ProtectedRoute/index.tsx @@ -1,49 +1,49 @@ +import { useAuthCheck, useLogin } from "../../controller/index"; + import { $authTokens } from "../../controller/recoil"; import Login from "../../pages/Login"; import NirvanaApi from "../../controller/nirvanaApi"; import { STORE_ITEMS } from "../../electron/constants"; import SkeletonLoader from "../loading/skeleton"; import { useEffect } from "react"; -import { useLogin } from "../../controller/index"; -import { useRecoilValue } from "recoil"; export default function ProtectedRoute({ children, }: { children?: React.ReactNode; }) { - const { mutateAsync } = useLogin(); + const { isLoading, isError, isSuccess, refetch } = useAuthCheck(); useEffect(() => { // on load of this, if we already have jwt tokens in store, - // then try using them with auth check, and if successful with simple dime call, then let them continue + // then try using them with auth check window.electronAPI.store .get(STORE_ITEMS.AUTH_SESSION_JWT) .then((jwtToken: string) => { if (jwtToken) { - // todo use this to do an auth check...set the necessary things to make react query run the check - // check if the jwt token is good - - // then pass onto the api and such - NirvanaApi._jwtToken = jwtToken; + refetch(); } }); }, []); - return ; + if (isLoading) { + return ( +
+ +
+ ); + } - // if (isLoading || isIdle) - // return ( - //
- // - //
- // ); - - // if (isError) { - // return ; - // } + if (isError) { + return ; + } // if we can successfully get user details, we are good to continue - return <>{children}; + // basic auth...any additional auth should be done at lower levels + if (isSuccess) { + return <>{children}; + } + + return ; } diff --git a/packages/desktop/src/controller/index.tsx b/packages/desktop/src/controller/index.tsx index ddf4ad4..a64535a 100644 --- a/packages/desktop/src/controller/index.tsx +++ b/packages/desktop/src/controller/index.tsx @@ -1,10 +1,12 @@ -import NirvanaApi, { login } from "./nirvanaApi"; +import NirvanaApi, { authCheck, login } from "./nirvanaApi"; import { useMutation, useQuery } from "react-query"; -import { $authTokens } from "./recoil"; -import { useRecoilValue } from "recoil"; - // ====== QUERIES +export function useAuthCheck() { + return useQuery("AUTH_CHECK", authCheck, { + retry: false, + }); +} export function useLogin() { return useMutation("LOGIN", login, {}); diff --git a/packages/desktop/src/controller/nirvanaApi.ts b/packages/desktop/src/controller/nirvanaApi.ts index 5166008..62a8d22 100644 --- a/packages/desktop/src/controller/nirvanaApi.ts +++ b/packages/desktop/src/controller/nirvanaApi.ts @@ -20,6 +20,9 @@ export default class NirvanaApi { const fullUrl = localHost + url; let res; + if (privateRoute && !this._jwtToken) + throw Error("No jwt token available!"); + if (privateRoute && this._jwtToken) { res = await fetch(fullUrl, { method: method, @@ -36,10 +39,8 @@ export default class NirvanaApi { } return await res.json(); - } catch (error) { + } catch (error: any) { console.log(error); - - throw Error(error); } } } @@ -55,6 +56,6 @@ export async function login(reqLoginTokens: { ); } -export async function authCheck(jwtToken: string) { - return await NirvanaApi.fetch(`/user/authCheck`, "GET", true); +export async function authCheck(): Promise { + return await NirvanaApi.fetch(`/user/authcheck`, "GET", true); } diff --git a/packages/desktop/src/pages/Login/index.tsx b/packages/desktop/src/pages/Login/index.tsx index b54da00..05a6da9 100644 --- a/packages/desktop/src/pages/Login/index.tsx +++ b/packages/desktop/src/pages/Login/index.tsx @@ -41,6 +41,8 @@ export default function Login() { const { jwtToken, userDetails } = loginResponse; window.electronAPI.store.set(STORE_ITEMS.AUTH_SESSION_JWT, jwtToken); + + window.location.reload(); } );