nice auth flow working with verification and stuff with token
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 <Login />;
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="container h-screen w-screen flex flex-col justify-center mx-10">
|
||||
<SkeletonLoader />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// if (isLoading || isIdle)
|
||||
// return (
|
||||
// <div className="container h-screen w-screen flex flex-col justify-center mx-10">
|
||||
// <SkeletonLoader />
|
||||
// </div>
|
||||
// );
|
||||
|
||||
// if (isError) {
|
||||
// return <Login />;
|
||||
// }
|
||||
if (isError) {
|
||||
return <Login />;
|
||||
}
|
||||
|
||||
// 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 <Login />;
|
||||
}
|
||||
|
||||
@@ -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, {});
|
||||
|
||||
@@ -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<void> {
|
||||
return await NirvanaApi.fetch(`/user/authcheck`, "GET", true);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user