Skip to content

Instantly share code, notes, and snippets.

@Lightnet
Created March 7, 2022 22:43
Show Gist options
  • Select an option

  • Save Lightnet/39ede1ebe5653022716b90946c0e6900 to your computer and use it in GitHub Desktop.

Select an option

Save Lightnet/39ede1ebe5653022716b90946c0e6900 to your computer and use it in GitHub Desktop.
token setup idea and prototype for one token and other refresh token. reactjs

One token for check user has login and other token will refresh token for user access to router urls.

//...
import { isEmpty } from '../../lib/helper.mjs';
import { checkToken, parseJwt } from '../../lib/helperToken.mjs';
import { refreshToken } from '../controllers/RefreshToken.mjs';
const router = express.Router();
//...
router.get('/token', refreshToken);
export default router;
/*
LICENSE: MIT
Created by: Lightnet
*/
import React,{ createContext, useState, useMemo, useContext, useEffect } from "react";
//import useFetch from "../hook/useFetch.mjs";
import {
parseJwt
//, isEmpty
} from "../../lib/helper.mjs";
import axios from "axios";
export const AuthContext = createContext();
export function useAuth(){
const context = useContext(AuthContext);
if (!context) {
throw new Error(`useAuth must be used within a AuthContext`)
}
return context;
}
export function AuthProvider(props){
const [userID, setUserID] = useState(''); // use?
const [user, setUser] = useState(''); // user name
const [status, setStatus] = useState('loading'); //loading, auth, unauth
//refresh token access
const [token, setToken] = useState(''); // required access
const [expire, setExpire] = useState('');
//refresh token base access without keys but ip
const [baseToken, setBaseToken] = useState(''); // required access
const [baseExpire, setBaseExpire] = useState(0);
useEffect(() => {
refreshToken();
refreshBaseToken();
}, []);
async function refreshToken(){
setStatus('loading')
axios.get('/token').then(function (response) {
console.log(response)
if(response.data.error){
console.log("NOT LOGIN")
setStatus('unauth')
return;
}
const decoded = parseJwt(response.data.accessToken);
//console.log(decoded)
setToken(response.data.accessToken);
setUser(decoded.user);
setExpire(decoded.exp);
console.log(decoded.exp);
setStatus('auth')
}).catch(function (error) {
// handle error
console.log(error);
console.log("TOKEN ERROR...")
setStatus('unauth')
//history.push("/");
})
}
async function refreshBaseToken(){
axios.get('/basetoken').then(function (response) {
console.log(response)
const decoded = parseJwt(response.data.accessToken);
console.log(decoded)
setBaseToken(response.data.accessToken);
setBaseExpire(decoded.exp);
console.log(decoded.exp);
}).catch(function (error) {
// handle error
console.log(error);
console.log("BASE TOKEN ERROR...")
//history.push("/");
})
}
/*
const axiosJWT = axios.create();
axiosJWT.interceptors.request.use(async (config) => {
const currentDate = new Date();
if (expire * 1000 < currentDate.getTime()) {
const response = await axios.get('http://localhost:3000/token');
config.headers.Authorization = `Bearer ${response.data.accessToken}`;
setToken(response.data.accessToken);
const decoded = parseJwt(response.data.accessToken);
//setName(decoded.name);
setExpire(decoded.exp);
}
return config;
}, (error) => {
return Promise.reject(error);
});
const response = await axiosJWT.get('/refreshtest', {
headers: {
Authorization: `Bearer ${token}`
}
});
*/
const value = useMemo(()=>({
status, setStatus,
userID, setUserID,
user, setUser,
token, setToken,
expire, setExpire,
baseToken, setBaseToken,
baseExpire, setBaseExpire
}),[
status,
userID,
user,
token,
expire,
baseToken,
baseExpire
])
return <AuthContext.Provider value={value} {...props} />
}
// https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library
export function parseJwt(token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
};
import jwt from "jsonwebtoken";
import clientDB from "../../lib/database.mjs";
import crypto from 'crypto';
export const refreshToken = async(req, res) => {
try {
const refreshToken = req.cookies.token;
//console.log("refreshToken:", refreshToken)
console.log("/token")
//if(!refreshToken) return res.sendStatus(401);
if(!refreshToken) return res.json({ error:"NOTLOGIN" });;
const db = await clientDB();
const Users = db.model('User');
//const user = await Users.fineOne({refresh_token: refreshToken}).exec()
const user = await Users.findOne({token:refreshToken})
.select('id username tokenSalt')
.exec()
//console.log(user);
if(!user) return res.sendStatus(403);
jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, decoded) => {
if(err) {
console.log(err)
//clear cookies
res.clearCookie('token')
return res.sendStatus(403);
}
//console.log(decoded)
let hash= crypto.createHash('md5').update(req.ip + user.tokenSalt).digest('hex');
if(hash == decoded.hash){//check hash if tmp token expire
//console.log("MATCH HASH")
}else{
return res.sendStatus(403);
}
const accessToken = jwt.sign({id:user.id,user:user.username}, process.env.ACCESS_TOKEN_SECRET,{
expiresIn: '15s'
});
res.json({ accessToken });
});
} catch (error) {
console.log(error);
return res.sendStatus(403);
}
}
import express from 'express';
import { verifyToken } from '../middleware/VerifyToken.mjs';
const router = express.Router();
// middleware check token
//
router.get('/refreshtest', verifyToken, function (req, res) {
//console.log(req.get('authorization'))
//console.log(req.test)
//console.log(req.test1)
res.json({test:"test"})
})
export default router;
import axios from "axios";
import React from "react";
import { parseJwt } from "../../lib/helper.mjs";
import { useAuth } from "./AuthProvider";
export default function TestRefreshToken(){
const {
token
, setToken
, expire
, setExpire
} = useAuth();
const axiosJWT = axios.create();
axiosJWT.interceptors.request.use(async (config) => {
const currentDate = new Date();
if (expire * 1000 < currentDate.getTime()) {
const response = await axios.get('/token');
config.headers.Authorization = `Bearer ${response.data.accessToken}`;
setToken(response.data.accessToken);
const decoded = parseJwt(response.data.accessToken);
//setName(decoded.name);
setExpire(decoded.exp);
}
return config;
}, (error) => {
return Promise.reject(error);
});
async function clickRefreshTest(){
const response = await axiosJWT.get('/refreshtest', {
headers: {
Authorization: `Bearer ${token}`
}
}).then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
return <>
<button onClick={clickRefreshTest}> Test Refresh Token </button>
</>
}
export const verifyToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
//console.log("midd token:",token)
if(token == null) return res.sendStatus(401);
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, decoded) => {
if(err) return res.sendStatus(403);
console.log("PASS")
//pass a variable to next request
//req.test = "token";
//req.test1 = "token1";
//req.email = decoded.email;
next();
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment