I just started using JWT. I do the login and I send the token as a JSON response to the client. Upon successful login I store that to sessionStorage and then I use that token to access the protected route through the headers of another ajax call(GET) which on success will redirect to that page.
I started by protecting directly the route I am redirecting too, and had no /verify-user route but since on redirection the headers are not sent I found this solution only for verifying the token. However I don't know if this is the good way.
What do you think?
My login on the client:
// Login POST
$('#frm-login').submit(function (e) {
event.preventDefault()
$('button').text('Please wait ...').prop('disabled')
$.ajax({
url: "/login-user",
type: "POST",
data: $('#frm-login').serialize(),
dataType: "json"
}).always(function (response) {
$('button').text('Logging in').prop('disabled')
console.log("Login", response)
if (response.status == "error") {
$('button').removeClass('lime').addClass('red').text('Log in failed. Try again.');
return
}
localStorage.setItem('token', response.token);
console.log(localStorage.token)
$.ajax({
type: "GET",
url: "/verify-user",
headers: {
'Authorization': 'Bearer ' + localStorage.token
}
}).always(function (response) {
console.log("Access", response)
if (response.status == "error") {
$('button').removeClass('lime').addClass('red').text('Log in failed. Try again.');
return
}
if (response.status == 301) {
$(location).attr('pathname', '/LIMELine/chatroom/');
//$('img#profile-img').attr('src', response.responseText.authData.user.avatar)
console.log(response)
}
});
})
})
My login on the server:
/********************* LOGIN *********************/
app.post('/login-user', (req, res) => {
user.loginUser(req.body, (err, jResult) => {
if (err) {
return res.send(jResult)
}
let token = jwt.sign({
user: jResult,
}, "supersecret")
console.log(token);
return res.json({
token: token
})
//add other headers here...
})
})
/********************* VERIFY USER *********************/
app.get('/verify-user', verifyToken, (req, res) => {
jwt.verify(req.token, "supersecret", (err, authData) => {
if (err) {
return res.status(403).json({
message: "No token found"
});
}
return res.status(301).json({
authData
});
})
})
The protected route, which the user should see when logs in
// ********************* MAIN PAGE *********************************************
app.get('/LimeLINE/chatroom' (req, res) => {
try {
// CODE FOR CONTENT OF THE PAGE
return res.json({
authData
});
}
})
})
If you are making a full page redirect (not through ajax but automatically through the browser, like when clicking an untempered anchor tag) the browser won't automatically send the Authorization
HTTP header.
You can either start sending the JWT token using a cookie (which is less standard and ties the client to being a browser but will happen automatically on all full page and AJAX calls) or handle the redirect yourself through the ajax call. Another "hybrid" solution would be to enable both Authorization
header AND cookie as valid authorization methods.
IMO it all depends if your server should accept non browser client currently or in the near future.