One token for check user has login and other token will refresh token for user access to router urls.
Created
March 7, 2022 22:43
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //... | |
| 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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 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} /> | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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> | |
| </> | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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