Skip to content

Instantly share code, notes, and snippets.

@isaacgr
Last active June 6, 2019 18:01
Show Gist options
  • Save isaacgr/3cae75c69d5fe5a33c45bcb1c3c2ab94 to your computer and use it in GitHub Desktop.
Save isaacgr/3cae75c69d5fe5a33c45bcb1c3c2ab94 to your computer and use it in GitHub Desktop.
JSON Web Token authorization setup for webserver/webclient
import decode from "jwt-decode"
import jwt from "jsonwebtoken"
class AuthHandlder {
// Get a token from the server
login(username, password) {
const data = {
username,
password,
}
// post request with the login info to the server
return this.fetch(`/api/login`, {
method: "POST",
body: JSON.stringify({
username,
password,
}),
})
.then(res => {
// we will set the token in local storage
// this is storage persistent until explicitly deleted
this.setToken(res.token)
return Promise.resolve(res)
})
.catch(error => {
return Promise.reject(error)
})
}
// Checks if there is a saved token in localstorage and if it's still valid
loggedIn() {
// get the token from localstorage
const token = this.getToken()
return !!token && this.isTokenValid(token)
}
// verify the token is valid
isTokenValid(token) {
try {
return jwt.verify(token, "secretkey", (error, auth) => {
if (error) {
return false
} else {
return true
}
})
} catch (err) {
return false
}
}
// saves the users token to localStorage
setToken(idToken) {
localStorage.setItem("id_token", idToken)
}
// gets the users token from localStorage
getToken() {
return localStorage.getItem("id_token")
}
// clear the users token and data from localStorage
logout() {
localStorage.removeItem("id_token")
}
getProfile() {
// decode the token to get the user info, can be useful
return decode(this.getToken())
}
fetch(url, options) {
// performs api calls sending the required authentication headers
const headers = {
Accept: "application/json",
"Content-Type": "application/json",
}
return fetch(url, {
headers,
...options,
})
.then(this._checkStatus)
.then(response => response.json())
}
_checkStatus(response) {
// raises an error in case response status is not a success
if (response.status >= 200 && response.status < 300) {
// Success status lies between 200 to 300
return response
} else {
let message = ""
return response.json().then(json => {
message = json["message"]
var error = new Error(message)
error.response = response
throw error
})
}
}
}
// create an instance of the handler and export it to be used by the rest of our application
let Auth = new AuthHandler()
export default Auth
const express = require("express")
const bodyParser = require("body-parser")
const jwt = require('jsonwebtoken')
const app = express()
const port = 3000
// parse application/json requests, we'll be making these to login
app.use(bodyParser.json())
app.get("/", (req, res) => res.send("Homepage"))
app.post('/api/login', (request, response) =>{
// get the username and password from the request body
const {username, password} = request.body
// verify it somehow
if (username === "isaac" && password==="jwt"){
// user is authorized, send them a token
jwt.sign(
{username},
"secretkey",
(error, token) => {
if (error){
// return the error message to the user
return response.status(400).json(error['message'])
}
// all good, return the token to the user
return response.json({token})
}
)
} else {
// user is unauthorized, send error
return response.status(404).send('not authorized')
}
})
// verify the token
app.get("/api/verify", verifyToken, (request, response) => {
// we have a token, make sure its valid
jwt.verify(request.token, "secretkey", (error, authData) => {
// something invalid, return
if (error) {
return response.status(403).json({
message: "unauthorized",
})
} else {
// token is valid, return an object with the authData
return response.json({
authorized: true,
authData,
})
}
})
})
// verifyToken middleware to make sure token exists
function verifyToken(request, response, next) {
// get authorization header from request
const bearerHeader = request.headers["authorization"]
// if it exists, then get the token
if (typeof bearerHeader !== "undefined") {
const token = bearerHeader.split(" ")[1]
// add the token to the request object
request.token = token
// move on with the calling function
next()
} else {
// no token, reject
return response.status(403).json({
message: "unauthorized",
})
}
}
app.listen(port, () => console.log(`Server listening on port ${port}!`))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment